Servlet 수준 예외 처리
스프링의 예외 처리를 알아보기 전, 순수 서블릿 컨테이너는 예외를 어떻게 처리하는지 알 필요가 있다.
서블릿은 2가지 방식으로 예외 처리를 지원한다.
Execption
response.sendError(상태 코드, 에러 메시지)
자바 직접 실행
자바의 메인 메서드를 직접 실행하는 경우 main 이라는 이름의 스레드가 실행된다.
실행 도중에 예외를 잡지 못하고 처음 실행한 main() 메서드를 넘어서 예외를 던지면, 예외 정보를 남기고 해당 스레드는 종료된다.
main() 메소드를 실행했을 때, 예외를 못 잡으면 계속 부모까지 올라간다. → 상위 메서드에게 계속 예외를 던진다.
main() 밖으로 예외가 던져지면 예외 정보를 남기고 스레드가 종료됨.
웹 애플리케이션
웹 애플리케이션은 요청마다 스레드가 할당되고, 서블릿 컨테이너 안에서 실행된다.
애플리케이션에서 예외가 발생했는데, try ~ catch로 예외를 처리하면 아무런 문제가 없지만,
예외를 잡지 못하고 서블릿 밖으로까지 예외가 전달되면 어떻게 될까?
결국 톰캣과 같은 WAS 까지 예외가 전달된다. WAS는 예외를 어떻게 처리할까?
WAS는 404, 500 상태 코드를 만들어서 반환한다.
response.sendError()
오류가 발생했을 때 HttpServletResponse가 제공하는 sendError() 메소드를 사용해도 된다.
이는 서블릿 API의 일부로, 낮은 수준의 예외 처리 메커니즘이다.
이것을 호출한다고 예외가 발생하는 것은 아니지만, 서블릿 컨테이너에게 오류가 발생했다고 전달한다.
sendError()에 전달해 준 상태 코드에 맞게 에러를 응답한다.
sendError()를 호출하면 response 내부에 에러 상태를 저장한다. 그리고 서블릿 컨테이너는 클라이언트에게 응답하기 전에 response에 sendError()가 호출된 적이 있는지 확인한다. 만약 호출이 되었다면 설정한 상태 코드에 맞게 에러를 제공한다.
서블릿 예외 에러 페이지 생성
WebServerFactoryCustomizer<ConfigurableWebServerFactory> 클래스를 재정의하면 원하는 에러 페이지를 나타나게 할 수 있다.
“/custom-page”를 처리할 컨트롤러도 생성해야 한다.WAS까지 에러가 전파되면 WAS는 다시 컨트롤러를 호출
에러 페이지 작동 원리
서블릿은 Exception이 발생해서 서블릿 밖으로 전달되거나 response.sendError()가 호출되면 설정된 오류 페이지를 찾는다.
[sendError 흐름]
클라이언트는 1번 요청했는데, 사실상 컨트롤러는 2번 호출하는 것이다. 클라이언트는 이런 것을 모른다.
필터, 서블릿, 인터셉터 등등 모두 2번씩 호출됨
WAS가 컨트롤러를 다시 호출할 떄, 에러 정보를 request attribute에 담아서 호출함.
attribute 속성에는
exception_type, message, URI, 상태 코드, dispatchType등이 존재함.
서블릿 예외 처리
필터
위에서 필터가 총 2번 호출된다고 했다.
그런데 로그인 인증 체크를 생각해 보면, 이미 한번 필터나 인터셉터에서 사용자 정보 체크를 한다.
서버 내부에서 오류 페이지를 호출한다고 해서, 해당 필터나 인터셉터가 한 번 더 호출되는 것은 비효율적이다.
그래서 요청이 클라이언트로부터 발생한 것인지, 에러 페이지를 출력하기 위한 요청인지 내부에서 구분하기 위해서 서블릿은 attirbute에서 DispatcherType 이라는 정보를 제공한다.
서블릿 스펙은 클라이언트가 요청한 것인지 아닌지 구분할 수 있다.
새로운 필터를 구현하고 이를 등록할 때, 어떤 DisPatchType만 받을지 설정할 수 있다.
로그를 확인해 보면 CustomFilter가 2번 호출되는 것도 확인할 수 있다.
만약 setDispatcherTypes()에 아무것도 설정하지 않는다면 REQUEST가 디폴트 값이다.
dispathType으로 중복 호출을 막을 수 있다.
인터셉터
Filter와 다르게 DispatchType을 설정할 수 없다. excludePathPatterns() 설정을 통해서 제어할 수 있다.
Last updated