서블릿 예외처리에서 학습 했던 에러처리를 스프링 부트에서는 모두 기본으로 제공한다. /error
라는 경로로 기본 오류 페이지로 설정해두고 예외가 발생하면 /error
url을 기본으로 호출하게된다.
우리가 등록했던 WebServerCustomizer
의 @Component를 주석처리한 후 진행해보자!
해당 class를 spring에 등록하지 않게되면 스프링 부트는 자동으로 BasicErrorController
의 /error
를 기본으로 요청하게 된다.
규칙에 맞게
다음과 같이 파일을 만들어주면 부트가 자동으로 파일을 찾아서 연결시켜준다.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
</head>
<body>
<div class="container" style="max-width: 600px">
<div class="py-5 text-center">
<h2>4xx 오류 화면 스프링부트 화면</h2>
</div>
<div>
<p>오류 화면 입니다.</p>
</div>
<hr class="my-4">
</div> <!-- /container -->
</body>
</html>
파일 내용은 다음과 같으며 에러 코드만 수정해서 사용해주면 된다.
서블릿처럼 등록과정 없이 에러 페이지가 처리되는 것을 확인할 수 있다.
스프링 부트 에러 페이지 규칙
- 뷰 템플릿
resources/templates/error/500.html
resources/templates/error/5xx.html- 정적 리소스( static , public )
resources/static/error/400.htmlresources/static/error/404.html
resources/static/error/4xx.html- 적용 대상이 없을 때 뷰 이름( error )
resources/templates/error.html
해당 경로 위치에 HTTP 상태 코드 이름의 뷰 파일을 넣어두면 된다.
뷰 템플릿이 정적 리소스보다 우선순위가 높고, 404, 500처럼 구체적인 것이 5xx처럼 덜 구체적인 것 보다
우선순위가 높다.
5xx, 4xx 라고 하면 500대, 400대 오류를 처리해준다
BasicErrorController
는 기본적으로 model에 전달해주는 데이터들이 있는데
* timestamp: Fri Feb 05 00:00:00 KST 2021
* status: 400
* error: Bad Request
* exception: org.springframework.validation.BindException
* trace: 예외 trace
* message: Validation failed for object='data'. Error count: 1
* errors: Errors(BindingResult)
* path: 클라이언트 요청 경로 (`/hello`)
시간, 상태값, 에러 메세지, exception 정보 등 다음과 같은 정보를 model에 담아서 전달해준다. 해당 데이터를 템플릿에서 동적으로 처리하여 사용할 수 있다.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
</head>
<body>
<div class="container" style="max-width: 600px">
<div class="py-5 text-center">
<h2>500 오류 화면 스프링 부트 제공</h2>
</div>
<div>
<p>오류 화면 입니다.</p>
</div>
<ul>
<li>오류 정보</li>
<ul>
<li th:text="|timestamp: ${timestamp}|"></li>
<li th:text="|path: ${path}|"></li>
<li th:text="|status: ${status}|"></li>
<li th:text="|message: ${message}|"></li>
<li th:text="|error: ${error}|"></li>
<li th:text="|exception: ${exception}|"></li>
<li th:text="|errors: ${errors}|"></li>
<li th:text="|trace: ${trace}|"></li>
</ul>
</li>
</ul>
<hr class="my-4">
</div> <!-- /container --></body>
</html>
다음과 같은 데이터가 나오는데 위에서 말해준 데이터랑 다르게 null이 많이 보인다. 해당 이유는 에러에 대한 정보를 고객에게 모두 노출한다면 보안상 취약점이 생기거나 고객에게 혼란을 줄 수 있기 때문에 기본적으로 값을 가리도록되어 있다.
하지만 해당 내용을 설정 파일을 통해 노출시킬 수도 있는데
server.error.include-exception=true
server.error.include-message=always
server.error.include-stacktrace=always
server.error.include-binding-errors=always
설정 이후에는 다음과 같이 에러의 대한 정보가 그대로 노출되는 것을 확인할 수 있다.
설정 옵션
never : 사용하지 않음
always :항상 사용
on_param : 파라미터가 있을 때 사용
3가지가 존재하며 on_param의 경우
http://localhost:8080/error-ex?message=&errors=&trace=
url에 다음과 같이 파라미터로 넘기게 되면 파라미터에 추가된 내용이 노출된다.
이 외에 더 Exception page에 대해 학습하고 싶거나 확장성을 고민하고 있다면
ErrorController
인터페이스를 상속받아서 구현하거나 BasicErrorController
를 상속 받아서 기능을 추가할 수 있다.