지난 포스팅에서 서블릿을 활용한 예외 처리 방법에 대해서 알아보았다.
그런데 WebServerCustomizer를 생성하거나, 에러 페이지를 추가하고, 컨트롤러를 생성하는 등의 복잡한 과정이 필요했다. 이번에는 스프링부트를 활용하여 이 과정이 어떻게 생략되는지 확인해보자.
스프링부트 기본 제공 기능
- ErrorPage를 자동으로 등록한다.
상태코드나 예외를 설정하지 않으면 new ErrorPage("/error")가 기본 에러 페이지로 등록된다.
서블릿 밖으로 예외가 전달되거나, response.sendError()가 호출되면 모든 에러는 /error를 호출하게 된다.
- BasicErrorController라는 컨트롤러를 자동으로 빈으로 등록한다.
1번에서 등록한 /error를 매핑해서 처리해준다.
- 참고로 ErrorPage를 등록해주는 역할을 ErrorMvcAutoConfiguration이 한다.
- 스프링 부트가 기본으로 제공하는 에러 메커니즘도 다른 기능과 마찬가지로 WebServerCustomizer처럼 사용자가 정의한 빈이 있다면 적용되지 않으므로 기존에 생성했던 WebServerCustomizer는 빈 등록을 하지 않도록 하자.
그럼 코드로 구현하고 결과를 확인해보자
컨트롤러 등록
- 예외를 발생시키기 위한 컨트롤러부터 생성해보자.
@Slf4j
@Controller
public class ServletExceptionController {
@GetMapping("/error-ex")
public void errorEx() {
throw new RuntimeException("예외 발생!");
}
@GetMapping("/error-404")
public void error404(HttpServletResponse response) throws IOException {
response.sendError(404, "404오류!");
}
@GetMapping("/error-400")
public void error400(HttpServletResponse response) throws IOException {
response.sendError(400, "400오류!");
}
@GetMapping("/error-500")
public void error500(HttpServletResponse response) throws IOException {
response.sendError(500, "500오류!");
}
뷰 생성
- 이제 각 에러를 확인하기 위한 뷰를 생성하자.

- 생성 후에 각 에러를 발생시키면




따로 예외에 따라서 ErrorPage를 등록하지 않았는데도 각 예외에 매핑되는 뷰를 자동으로 찾아주는 것을 확인할 수 있다.
이것 또한 마찬가지로 뷰를 선택하는 우선순위에 대한 규칙이 있다.
뷰 선택 우선순위
-
뷰 템플릿
타임리프나 jsp같은 동적인 페이지가 높은 우선순위를 갖는다
현재의 경우 resources/templates/error/500.html
-
정적 리소스(static, public)
단순한 정적인 페이지일 경우
resources/static/error/500.html
-
적용대상이 없을 때
resources/templates/error.html
- 또한 같은 패키지 안에서도 뷰의 이름이 얼마나 구체적이냐에 따라 우선순위가 정해지는데 예를 들어,
resources/templates/error/500.html
resources/templates/error/5xx.html
이 두개의 뷰가 있을 경우 500.html이 높은 우선순위를 갖게 된다.
- 만약 400에러가 발생했는데, 우리처럼 400.html이 존재하지 않는다면 4xx.html이 대신 매핑된다.
- 예외의 경우도 결국 서버의 문제이므로 500에러와 같이 처리된다.
에러 정보 표시하기
- BasicErrorController는 에러 정보를 model에 담아 뷰로 전송하는데, 이를 이용해 에러 정보를 확인할 수 있다.

그런데 막상 해당 페이지로 접근해보면 에러 정보가 담겨있지 않은 것을 확인할 수 있는데, appllication.properties에 설정을 추가해주자.
server.error.include-exception=true
server.error.include-message=always
server.error.include-stacktrace=always
server.error.include-binding-errors=always
- 여기서 각 키의 value에는
never : 사용하지 않음
always : 항상 사용

on_param : 파라미터가 있을 때 사용
등의 값이 들어갈 수 있다.

- 하지만 이런 정보는 사용자에게도 불편함을 끼치고, 보안상 문제가 생길 수 있으므로 개발 서버에서만 사용하고 운영서버에서는 사용하지 않도록 하자.
그 외 스프링 부트 에러 관련 옵션
- server.error.whitelabel.enabled=true : 에러 화면을 찾지 못했을 때, 스프링의 whitelabel 에러 페이지를 띄운다.
- server.error.path=/error : 에러 페이지 경로로서, 스프링이 자동으로 등록하는 글로벌 에러 페이지 경로와 BasicErrorController의 경로에 함께 사용된다.
근데 별로 쓸일이 없다고 한다.
- 에러 공통 처리 컨트롤러를 수정하고 싶다면, ErrorController나 BasicErrorController를 상속받아서 사용하자.
출처 : 김영한 스프링MVC2편