Spring

Spring에서의 예외, 에러 처리

윤밥밥 2024. 11. 2. 14:48

Spring을 사용하다가 @RestControllerAdvice 를 사용하지 않으면 Spring에서 어떻게 예외를 처리하는 지 궁금해졌다.

 

그래서 이에 대해 알아보고자 한다.

Spring의 기본 예외 핸들링


1. BasicErrorController

Spring의 기본 예외 처리는 공식 문서를 통해 알 수 있었다.

기본적으로 모든 예외가 발생하면 /error 경로로 Spring이 재요청하여 기본적으로 등록되어 있는 BasicErrorController에서 예외 응답을 반환한다고 한다.

 

컨트롤러에서 BasicErrorController로의 예외 전달

Spring Boot에서 예외가 발생되고, @RestControllerAdvice 및 @ExceptionHandler 에서 예외가 처리되지 않으면 에러가 처음 요청을 컨트롤러에 매핑 시켜준 DispatcherServlet으로 전달되게 된다.

예외를 받은 DispatcherServlet은 /error 경로의 BasicErrorController 메서드를 호출하여 예외를 처리한다.

 

BasicErrorController를 까보면 위와 같이 @RequestMapping 을 통해 특정 API 호출(/error)에 대해 응답을 하는 구조임을 알 수 있다.

 

또한 /error 로 요청이 들어오면 클라이언트의 Accept 헤더에 따라 적절한 응답 형식을 결정하여 다음 두 메서드 중 하나를 호출한다.

  • errorHtml 메서드
  • error 메서드

 

errorHtml 메서드

/error 경로의 요청을 받지만 produces 속성을 통해 요청 헤더의 컨텐츠 타입(Content-Type)을 지정하여, 요청 헤더에 Accept: text/html 이 명시되어 있는 경우에만 이 메서드로 매핑된다.

즉 이 메서드가 호출되면 html로 에러를 응답한다.

 

error 메서드

Json 등 text/html 을 제외한 모든 칸텐츠 타입의 요청을 받는다.

응답은 Json 형태로 반환한다.

응답 형식은 다음과 같다.

{
	"type": "<https://example.org/problems/unknown-project>",
	"title": "Unknown project",
	"status": 404,
	"detail": "No project found for id 'spring-unknown'",
	"instance": "/projects/spring-unknown"
}

 

2. WAS의 에러(예외x) 처리

만약 요청 처리 도중에 OutOfMemory 같은 Exception 이 아닌 Error 가 발생하면 Spring 내부적으로 처리할 수 없기에 BasicErrorController가 처리하지 않고 WAS가 처리하게 된다.

WAS는 자신의 예외 처리 메커니즘을 통해 500 Internal Server Error 페이지를 생성하여 클라이언트한테 반환한다.


요청 과정을 통해 보는 예외 처리


일반적인 요청 흐름

Tomcat(WAS) -> 필터 -> 디스패처 서블릿 -> 인터셉터 -> 컨트롤러

BasicErrorController에서 예외가 처리될 경우의 요청 흐름

Tomcat(WAS) -> 필터 -> 디스패처 서블릿 -> 인터셉터 -> 컨트롤러
 -> 에외 발생 -> 인터셉터 -> 디스패처 서블릿 -> 인터센터 -> 컨트롤러(예외 처리, BasicErrorController) 

WAS에서의 예외가 처리될 경우의 요청 흐름

Tomcat(WAS) -> 필터 -> 디스패처 서블릿 -> 인터셉터 -> 컨트롤러
 -> 에외 발생 -> 인터셉터 -> 디스패처 서블릿 -> 디스패처 서블릿 처리 불가 예외 판단
 -> 필터 -> Tomcat(WAS) -> Tomcat(예외처리) -> 클라이언트

참고

https://docs.spring.io/spring-boot/reference/web/servlet.html#web.servlet.spring-mvc.error-handling

 

Servlet Web Applications :: Spring Boot

For servlet application, Spring Boot includes support for embedded Tomcat, Jetty, and Undertow servers. Most developers use the appropriate starter to obtain a fully configured instance. By default, the embedded server listens for HTTP requests on port 808

docs.spring.io