[Spring MVC] 컨트롤러의 Exception 처리

    반응형

    이 글은 코드로 배우는 스프링 웹 프로젝트(남가람북스, 구멍가게 코딩단)을 읽고 공부한 내용을 바탕으로 정리한 글입니다.


    스프링 MVC에서 Controller를 작성할 때 Exception을 처리하는 방식은 크게 두가지 방식으로 처리합니다.

    • @ExceptionHandler@ControllerAdvice를 이용한 처리
    • @ResponseEntity를 이용하는 예외 메시지 구성

    1. @ControllerAdvice

    AOP(Aspect-Oriented-Programming) 방식을 이용하여 공통적인 예외사항에 대해서는 별도로 @ControllerAdvice를 이용해서 분리하는 방식입니다.

    💡 AOP(Aspect-Oriented-Programming)이란?
    '핵심적인 로직은 아니지만 프로그램에서 필요한 공통적인 관심사(cross-concern)은 분리하자'는 개념입니다.

    예제를 위해서 exception 패키지를 생성하고, CommonExceptionAdvice 클래스를 생성하겠습니다. (CommonExceptionAdvice 클래스는 예외 처리 목적의 클래스로 별도의 로직을 처리하지 않습니다.)

    import lombok.extern.log4j.Log4j;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    
    @ControllerAdvice
    @Log4j
    public class CommonExceptionAdvice {
    
        @ExceptionHandler(Exception.class)
        public String except(Exception ex, Model model) {
            log.error("Exception ----- " + ex.getMessage());
            model.addAttribute("exception", ex);
            log.error(model);
            return "error_page";
        }
    
    }
    • @ControllerAdvice: 해당 객체가 스프링의 컨트롤러에서 발생하는 예외를 처리하는 클래스라는 것을 알려줍니다. 
    • @ExceptionHandler: 파라미터로 전달되는 예외타입을 처리한다는 것을 의미합니다. 위에서는 @ExceptionHandler의 파라미터로 Exception.class를 지정해줬으므로 모든 예외에 대한 처리가 except() 메서드에서 처리됩니다. (특정한 타입의 예외를 다루고 싶다면 Exception.class 대신에 처리하고 싶은 예외의 클래스를 지정해주면 됩니다!)

    이때, @ControllerAdvice 등의 어노테이션을 스프링에 인식시켜줄려면 exception 패키지가 스캔될 수 있도록 dispatcher-servlet.xml에서 <component-scan>에 exception 패키지를 추가해주어야 합니다.

    <context:component-scan base-package="com.hellomygreenworld.ex01.exception" />
    

    except() 메서드의 리턴값이 "error_page"라는 String 값이므로 views/error_page.jsp 파일을 작성해주겠습니다.

    <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ page session="false" import="java.util.* "%>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
      <title>error_page</title>
    </head>
    <body>
      <h4><c:out value="${ exception.getMessage() }"></c:out></h4>
      <ul>
        <c:forEach items="${ exception.getStackTrace() }" var="stack">
          <li><c:out value="${ stack }"></c:out></li>
        </c:forEach>
      </ul>
    </body>
    </html>
    

     

    그리고 나서 sampleDtoage 값에 int로 변환할 수 없는 값을 넣어 예외가 일어나게 하면 다음과 같이 작성한 error_page.jsp가 보여집니다.

     

    2. 404 에러 페이지

    지금까지는 Controller 처리에서 에러가 난 경우를 Exception 처리해주었고, 이번에는 잘못된 URL을 호출할 때 보이는 404 에러를 처리해보도록 하겠습니다. 스프링 MVC의 모든 요청은 DispatcherServlet을 이용해서 처리되므로(https://eunbin00.tistory.com/128) 404 같이 처리될 수 있도록 web.xml을 수정합니다.

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-config/dispatcher-servlet.xml</param-value>
        </init-param>
        <init-param>
            <param-name>throwExceptionIfNoHandlerFound</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    Controller에는 NoHandlerFoundException를 처리하도록 어노테이션과 함께 메서드를 추가로 작성합니다.

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handle404(NoHandlerFoundException ex) {
        return "custom404";
    }

    그리고 views/custom404.jsp 페이지도 작성해줍니다.

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <title>404_error</title>
    </head>
    <body>
      <h4>해당 URL은 존재하지 않습니다.</h4>
    </body>
    </html>
    

    그러면 아래와 같이 존재하지 않는 페이지를 요청했을 때, 예외처리가 되는 것을 확인할 수 있습니다!

    반응형

    'Java > Spring' 카테고리의 다른 글

    [Spring MVC] Persistence Tier CRUD 구현  (0) 2023.01.11
    [Spring boot] Maria DB 설정  (0) 2023.01.06
    [Spring MVC] 파일업로드 처리  (0) 2023.01.03
    [Spring MVC] Controller  (0) 2023.01.03
    [Spring MVC] 기본 구조  (0) 2023.01.02

    댓글