404 Not Found Error
웹서버에 존재하지 않는 자원을 요청했을 때, 즉 Mapping이 정의되지 않은 path로 이동했을 때 스프링 웹 서버는 다음과 같은 Not Found error 객체를 응답으로 내보낸다.
{
"timestamp": "yyyy-MM-ddTHH:mm:14.441+00:00",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/{NOT_SUPPORTED_URI}"
}
스프링 mvc 구조에서 별도의 viewName 설정이 없다면 위 응답이 ModelAndView 객체의 attribute값으로 들어가게 되고, "error.html"파일이 viewName이 되어 response가 만들어진다.
예컨데, 템플릿 엔진으로 thymeleaf를 썼을 때 html 파일을 다음과 같이 구성하고
<h3 class="text-center">ERROR</h3>
<h5 class="text-center mb-3" th:text="${'"error" : '+error}"></h5>
<h5 class="text-center mb-3" th:text="${'"status" : '+status}"></h5>
<h5 class="text-center mb-3" th:text="${'"message" : '+message}"></h5>
mapper가 없는 임의의 path로 이동하면 아래와 같은 결과가 나온다. 흔히 아는 "404 Not Found" 에러가 발생한 모습이다.
스프링에선 @ControllerAdvice + @ExceptionHandler 조합으로 에러 핸들링을 한다. ControllerAdvice는 컨트롤러 Bean에 전역적으로 작용하는 aspect이기 때문에 컨트롤러 로직 수행중 던져진 예외들은 @ExceptionHandler method에 의해 처리된다.
그러나 404 에러는 요청이 컨트롤러에 매핑되지 못해서 발생하는 에러다. 해당 요청은 컨트롤러까지 가지도 못한다는 뜻이다. 때문에 컨트롤러 로직 수행중 발생하는 에러를 담당하는 @ControllerAdvice는 404 에러를 처리해주지 못한다.
그렇다면 어떻게 해야할까?
공식 문서
Spring Boot 공식 문서를 참고해보면, 특정 statuscode 오류에 맞는 view 파일을 설정해줄 수 있다. 예를들어, 404 Not Found 오류가 떴을 때 resources/error 디렉토리 아래에 다음과 같이 404.html 파일을 넣어두면 상태코드가 404인 에러일 때 해당 html 파일이 응답된다.
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
템플릿 엔진으로 thymeleaf를 사용할 경우, 위와 같이 templates/error 디렉토리에 404.html 파일을 추가한 뒤 재하지 않는 path로 이동하면 해당 html이 렌더링된다.