Controller의 Exception 처리
Controller를 작성할 때 예외 상황을 고려하면 처리해야 하는 작업이 엄청나게 늘어날 수 밖에 없습니다. 스프링 MVC에서는 이러한 작업을 다음과 같은 방식으로 처리할 수 있습니다.
- @ExceptionHandler와 @ControllerAdvice를 이용한 처리
- @ResponseEntity를 이용하는 예외 메시지 구성
@ControllerAdvice
@ControllerAdvice
는 AOP(Aspect-Oriented-Programming)를 이용하는 방식이다. AOP는 핵심적인 로직은 아니지만 프로그램에서 필요한 '공통적인 관심사(cross-concern)는 분리'하자는 개념이다. Controller를 작성할 때는 메서드의 모든 예외상항을 전부 핸들링해야 한다면 중복적이고 많은 양의 코드를 작성해야 하지만, AOP방식을 이용하면 공통적인 예외사항에 대해서는 별도로 @ControllerAdvice를 이용해서 분리하는 방식입니다.
예제를 위해 프로젝트에 org.noel.exception이라는 패키지를 생성하고, CommonExceptionAdvice 클래스를 생성한다.
CommonExceptionAdvice
는 @ControllerAdvice 어노테이션을 적용하지만 예외 처리를 목적으로 생성하는 클래스이므로 별도의 로직을 처리하지는 않는다.
▶ CommonExceptionAdvice 클래스
package org.noel.exception;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import lombok.extern.log4j.Log4j;
@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";
}
}
CommonExceptionAdvice 클래스에는 @ControllerAdvice라는 어노테이션과 @ExceptionHandler라는 어노테이션을 사용하고 있습니다. @ControllerAdvice
는 해당 객체가 스프링의 컨트롤러에서 발생하는 예외를 처리하는 존재임을 명시하는 용도로 사용하고, @ExceptionHandler
어노테이션의 속성으로는 Exception 클래스 타입을 지정할 수 있습니다. 위와 같은 경우 Exception.class를 지정하였으므로 모든 예외에 대한 처리가 except() 만을 이용해서 처리할 수 있습니다.
만일 특정한 타입의 예외를 다루고 싶다면 Exception.class 대신 구체적인 예외의 클래스를 지정해야 합니다. org.noel.exception 패키지는 servlet-context.xml에서 인식하지 않기 때문에 을 이용해서 해당 패키지의 내용을 조사하도록 해야 합니다.
servlet-context.xml에 <context:component-scan base-package="org.noel.exception"/>을 추가합니다.
CommonExceptionAdvice의 except() 리턴값은 문자열이므로 JSP파일의 경로가 됩니다. JSP는 error-page.jsp이므로 /WEB-INF/views 폴더 내에 작성해야 합니다.
▶ error_page.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ 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>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</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>
예외의 메시지가 정상적으로 출력된느지 확인해 보려면 고의로 숫자나 날짜 등의 파라미터 값을 변환에 문제 있게 만들어서 호출해 볼 수 있습니다. 예를 들어, 'sample/ex-04?name=aaa&age=11&page=9'와 호출해야 하는 URL에서 고의로 age 값을 'bbb'와 같은 문자열로 전송하였을 때 보이는 화면입니다.
404 에러 페이지
WAS의 구동 중 가장 흔한 에러와 관련된 HTTP 상태 코드는 '404'와 '500' 에러 코드이다. 500 메시지는 'Internal Server Error'이므로 @ExceptionHandler를 이용해서 처리되지만, 잘못된 URL을 호출할 때 보이는 404 에러 메시지의 경우는 조금 다르게 처리하는 것이 좋습니다.
스프링 MVC의 모든 요청은 DispatcherServlet을 이용해서 처리되므로 404 에러도 같이 처리할 수 있도록 web.xml을 수정합니다.
org.noel.exception.CommonExceptionAdvice에는 다음과 같이 메서드를 추가합니다.
▶ CommonExceptionAdvice 클래스의 일부
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handle404(NoHandlerFoundException ex) {
return "custom404";
}
에러 메시지는 custom404.jsp를 작성해서 처리합니다.
▶ custom404.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>해당 URL은 존재하지 않습니다.</h1>
</body>
</html>
브라우저에서 존재하지 않는 URL을 호출하면 custom404.jsp 페이지가 보이는 것을 확인할 수 있습니다.('/sample/..로 시작하는 URL의 경우에는 SampleController가 무조건 동작하므로 이를 제외한 경로로 테스트합니다!)
'Back-end > Spring Web Project' 카테고리의 다른 글
[Spring Web Project] 스프링 MVC 프로젝트의 기본 구성(2) - 테이블 생성 (0) | 2023.11.27 |
---|---|
[Spring] 스프링 MVC 프로젝트의 기본 구성(1) (0) | 2023.11.24 |
[Spring Web Project] 스프링 MVC의 Controller(3) - 파일 업로드 처리 (0) | 2023.11.24 |
[Spring Web Project] 스프링 MVC의 Controller(2) - Controller의 리턴 타입 (1) | 2023.11.21 |
[Spring Web Project] 스프링 MVC의 Controller(1) - Controller의 파라미터 (1) | 2023.11.21 |