스프링은 어플리케이션에서 발생가능한 에러들에 대해 다양한 처리방법을 제공합니다.
어플리케이션 내부에서 발생되는 에러를 감지하고 각각에 대한 적절한 처리를 하기 위해, 서블릿의 에러 처리 플로우에 대해 알아볼 필요가 있습니다. 이번 포스팅에서 이에 대해 중점적으로 다뤄 보겠습니다.
Spring MVC에서 모든 요청은 디스패쳐 서블릿을 통합니다. 디스패쳐 서블릿은 요청에 따라 HandlerMapping 객체를 통해 적절한 컨트롤러를 실행합니다. 이 과정은 디스패쳐 서블릿의 doDispatch() 함수 내에서 실행됩니다. 함수내에 try-catch문 을 통해 감지된 에러는 적절한 HandlerExceptionResolver를 선택해 에러를 처리하게 됩니다. 따라서, 아래와 같은 워크 플로우를 가집니다.
1. DispatcherServlet - 디스패쳐 서블릿은 스프링 컨테이너에 등록된 핸들러 ( @Controller )중 하나를 선택하여 이를 처리합니다.
2. DispatcherServlet - 컨트롤러가 위임받은 요청을 처리할때 Exception이 발생하면, 이를 디스패쳐가 감지합니다
(자세히는, DispatcherServlet - processDispatchResult()는 모든 요청에 대해 실행되게 됩니다. 다만, Exception 파라미터가 null 이 아닐 시 다음 메소드를 실행하여 에러에 대한 적절한 처리가 실행되도록 합니다.)
3. DispatcherServlet - processHandlerException() 해당 디스패쳐 서블릿에 등록된 HandlerExceptionResolver를 순차적으로 적용하여 처리합니다. 이때, 에러가 처리 된다면, 즉시 반환됩니다.
인터셉터의 preHandle(), postHandle(), afterCompletion() 는 정상적으로 요청이 처리됐을때, 모두 실행됩니다.
반면에, 요청 처리 중 에러 발생 시 preHandle(), afterCompletion() 둘만 실행되게 됩니다.
즉, 에러 인스턴스들은 HandlerExceptionResolver로 등록된 빈들을 통해 처리 됩니다.
스프링 부트는, HandlerExceptionResolver를 빈으로 등록하여 사용하는 대신, 에러처리를 위한 여러 기본 구성을 제공합니다. 이를 파악하기 위해, WebMvcConfigurationSupport 클래스를 들여다 봅니다.
위에서 알 수 있듯, 총 세가지 HandlerExceptionResolver가 0 순위로 등록됩니다. 이들은 리스트로 구현되며 리스트에 삽입된 순서로 에러 핸들링이 시작됩니다. 따라서, 0순위이면서도 내부적으로 아래와 같은 처리 순서를 가집니다.
- ExceptionHandlerExceptionResolver
(1) 먼저, 에러가 발생한 컨트롤러 내에 적합한 @ExceptionHandler이 있으면 그를 실행합니다.
(2) 이때 찾지 못하면, @ControllerAdvice의 적절한 @ExceptionHandler를 찾아 그를 실행합니다.
핸들링 가능한 @ExceptionHandler를 아무것도 찾지 못하면, 다음 리졸버로 에러처리가 위임됩니다. - ResponseStatusExceptionResolver
에러를 처리할 수 있는 @ExceptionHandler를 찾지 못한 경우, 이 HandlerExceptionResolver로 에러처리가 위임됩니다.
(1) 먼저, 에러 객체가 ResponseStatusException인지 확인 합니다. 맞다면, 적절한 로직을 수행합니다.
(2) 처리되지 못했을때, 에러 객체에 @ResopnseStatus가 붙어있는지를 확인하고, 이에 따라 에러를 처리합니다.
(3) 에러 객체가 다른 에러 때문에 발생된 것인지를 확인하고, 해당 함수를 재귀적으로 실행합니다. 이를 통해 더 근본적인 에러를 찾을 수 있습니다.
발생된 에러 인스턴스에 ResponseStatusException @ResponseStatus가 없다면, 다음 리졸버로 에러처리가 위임됩니다. - DefaultHandlerExceptionResolver
(1) 스프링에서 발생된 에러인지를 확인합니다.
아닐시 null을 반환하여 다음 리졸버로 넘깁니다. 이 경우, 500대 에러가 발생하게 됩니다.
이상으로 스프링의 에러처리 플로우에 대해 알아봤습니다. 긴글 읽어주셔서 감사합니다 :)
'SpringBoot' 카테고리의 다른 글
[Spring] Spring Security 인증 구성 (0) | 2024.01.02 |
---|---|
[Spring] 다수의 SecurityFilterChain 구성 방법 (0) | 2024.01.01 |
[Spring] Spring Security Architecture (1) | 2023.12.29 |
[Spring] RestTemplate (1) | 2023.12.29 |
SpringBoot의 작동원리를 직접 구현 해보며 이해하자(1) - Servlet (0) | 2023.12.22 |