스프링에서의 예외처리에 대해 조금 더 자세히 알아보았습니다.
여기서의 예외 처리는 사용자에게 못생긴 404, 500 페이지를 직접적으로 보여주지 않기 위해 사용하는 방법을 말합니다.
(= 에러 페이지 출력의 방식)
다뤄볼 에러페이지 처리 방식은 네 가지입니다.
(1) jsp의 errorPage를 이용하는 방법
(2) web.xml 설정을 통한 방법
(3) ExceptionHandler annotation을 이용한 방법
(4) ControllerAdvice 를 이용한 방법
(1) errorPage 이용
우선 스프링 이전에 사용하던, 아주 직관적인 방법으로는 아래와 같이 jsp 페이지에서의 표시법이 있습니다.
1
|
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" errorPage="에러페이지명.jsp"%>
|
cs |
원하는 에러페이지에 errorPage="에러페이지명.jsp"를 입력하고 에러페이지명에 맞는 jsp 페이지를 생성합니다.
그 다음, 해당 페이지가 에러 페이지가 맞다는 것을 컴파일러에게 알려 주기 위해
에러페이지명.jsp 에 다음의 내용을 기재합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true"%>
<% response.setStatus(200); %>
<!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>
<h2> DB Error </h2>
<%= exception.getMessage() %>
</body>
</html>
|
cs |
여기서 중요한 부분은 isErrorPage가 true로 되어 있다는 점이고, response,setStatus가 200(=정상 상태)로 되어 있다는 점입니다. 그리고 원하는 메시지를 기재한 다음, exception의 내용을 알기 위해 getMessage를 사용합니다.
매우 직관적인 방법이지만, 스크립트릿을 사용하게 되어야 하는 것과 페이지마다 이걸 해줘야 한다는 번거로움이 있습니다. include를 이용하면 매 페이지마다 할 필요는 없겠지만... 모양이 좋지는 않습니다. 지금 저 가르쳐주시는 강사님은 이 방법을 선호하시는 듯하나, 저는 선호하지 않습니다. 스프링 또는 다른 시스템이 해 줄 수 있는 일은 최대한 맡기고, 개발자는 로직 구현에만 집중해야 한다고 생각합니다...
(2) web.xml 설정을 통한 방법
큰 차이는 없습니다. web.xml에서 아래의 내용을 추가합니다.
1
2
3
4
|
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/views/error/error404.jsp</location>
</error-page>
|
cs |
그리고 기재한 위치에 error404.jsp 파일을 만들고 에러페이지의 내용을 기재합니다.
1번 방법과 별다른 차이는 없습니다만, 에러코드별로 만들 수 있다는 차이가 있습니다.
마찬가지로 별로 선호하지 않습니다. 에러코드별로 만드는 것조차 번거롭습니다 !!!!
(3) @ExceptionHandler를 통한 방법
만들어 둔 Controller 파일에 아래의 메소드를 추가하는 방식입니다.
1
2
3
4
5
6
7
8
|
// 예외처리부
@ExceptionHandler(RuntimeException.class)
public String exceptionHandler(Model model, Exception e) {
e.printStackTrace();
model.addAttribute("exception", e);
return "error/exception";
}
|
cs |
(저 e.printStackTrace 부분은 logger를 통해서도 출력이 가능합니다.)
이렇게 하면 데이터베이스에서 발생하는 에러를 모두 error 폴더 내의 exception.jsp로 보내 줍니다.
이때 exception.jsp 파일은 아래와 같이 작성하실 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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>
<article>
<div>
<p> 데이터 처리 과정에서 문제가 발생하였습니다. </p>
<p> 관리자에게 문의하여 주십시오. </p>
<h3>${exception.getMessage()}</h3>
<ul>
<c:forEach items="${exception.getStackTrace()}" var="stack">
<li>${stack.toString()}</li>
</c:forEach>
</ul>
</div>
</article>
</body>
</html>
|
cs |
적어도 스크립트릿을 사용하지 않는다는 점에서 위안을 느끼고 있습니다.
저야 정말 라이트한 웹앱만 만드는 단계이므로 이정도만 해도 사실 불편함은 없습니다만,
컨트롤러를 여러 개 사용하기 시작하는 순간 번거로움이 생겨납니다.
그래서 아예 예외 전용의 컨트롤러 클래스 파일을 작성하게 됩니다.
(4) @ControllerAdvice를 이용한 방법
별도의 컨트롤러 클래스 파일을 생성하여 처리하는 방법입니다.
아래와 같은 방식으로 작성하고, annotation을 통해 받도록 해 줍니다. ^_^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package com.heegene.web.error.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class CommonExceptionAdvice {
private static final Logger logger = LoggerFactory.getLogger(CommonExceptionAdvice.class);
@ExceptionHandler(RuntimeException.class)
public String errorException(Model model, Exception e) {
logger.info("Controller advice 방식의 에러페이지 \n\n Exception -> " + e.getMessage());
model.addAttribute("exception", e);
return "error/exception";
}
}
|
cs |
이렇게 하면 전체 적용을 받을 수 있습니다.
제가 만들어 둔 exception.jsp의 경우 stacktrace를 전부 다 가져오도록 설정해 두어
오히려 더 못생긴 에러페이지이지만, 에러페이지의 일부만 출력하거나 하는 식으로
훨씬 더 예쁜 에러페이지 처리를 하실 수 있습니다!
이상입니다.
'Developments' 카테고리의 다른 글
200814 Spring Security 구현 (0) | 2020.08.14 |
---|---|
200811 Spring MVC를 이용한 블로그 시스템 1.0 (0) | 2020.08.11 |
200805 Spring boot를 이용한 일기장 Webapp (0) | 2020.08.04 |
200804 Spring MVC 게시판(ver.1.0) (0) | 2020.08.04 |
[이럴땐이렇게] org.mockito import가 안 될 때 (org.mockito cannot be resolved) (0) | 2020.07.30 |