Back-End/Spring

[Spring MVC2][예외 처리와 오류 페이지] - 필터와 인터셉터

얄루몬 2022. 5. 28. 16:01

💻본 포스팅은 '스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 김영한'님의 강의를 듣고 작성되었습니다.

https://inf.run/vQHp

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의

웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있

www.inflearn.com


목차
1. 오류 발생 시에 WAS 내부의 재호출 시의 중복 호출 해결 방안 
2. 서블릿 예외 처리 - 필터
3. 스프링이 제공하는 기능 - 인터셉터 중복 호출 제거

오류 발생 시에 WAS 내부의 재호출 시의 중복 호출 해결 방안 

예외 발생 or response.sendError( ) 발생 시 오류 페이지 요청 흐름

컨트롤러에서 발생한 예외 or sendError( )의 흐름
WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)

WAS가 해당 예외 처리 페이지를 다시 요청 하는 흐름
WAS `/error-page/500` 다시 요청 -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러(/errorpage/500) -> View
👉이때 에외 처리 페이지를 다시 요청하면서 필터, 서블릿, 인터셉터를 모조리 다시 중복 호출하는 문제가 발생하고 이는 매우 비효율적이다.
  • 위에서 살펴본바와 같이 오류가 발생하면 오류 페이지 호출을 위해 WAS 내부에서 다시 중복 호출을 하게 된다.
  • 이는 매우 비효율적인 일이고 이를 해결 하기 위한 방법을 살펴보자

서블릿 예외 처리 - 필터

아래를 통해서 필터의 중복 호출 제거 방법을 살펴보자

DispatcherType

필터는 위에 같은 상황을 위해서 dispatcherType이라는 옵션을 제공한다.

  • 고객이 처음 요청할 경우
    • dispatcherType = REQUEST
  • 예외나 sendError( )로 중복 요청인 경우
    • dispatcherType = ERROR 
  • 이를 사용해서 서블릿은 실제 고객이 요청한 것인지 서버 내부에서 오류 페이지를 요청하는 것인지 DispatcherType을 통해 구분할 수 있는 방법을 제공한다.
    • 서버 내부에서 오류 페이지를 요청? 
      • 예외나 sendError가 WAS로 전달되면 서버 내부에서 클라이언트는 재요청의 흐름을 알 수 없게 하면서 서버 내부에서 재요청을 처리한다. 그렇기에 필터 -> 서블릿 -> 인터셉터를 재요청 하는 곳은 서버가 된다. 
DispatcherType
- REQUEST : 클라이언트 요청
- ERROR : 오류 요청
- FORWARD : MVC에서 배웠던 서블릿에서 다른 서블릿이나 JSP를 호출할 때 RequestDispatcher.forward(request, response);
- INCLUDE : 서블릿에서 다른 서블릿이나 JSP의 결과를 포함할 때 RequestDispatcher.include(request, response);
- ASYNC : 서블릿 비동기 호출

필터와 DispatcherType

필터와 DispatcherType이 어떻게 사용되는지 알아보자

filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST,DispatcherType.ERROR);
  • 생성한 필터 클래스를 @Bean으로 등록해야 사용하는 것은 앞선 포스팅에서 말했다. 
  • 등록할 때 DispatcherType을 넣어 클라이언트 요청, 오류 페이지 요청에도 필터가 호출되게 했다.
    • 아무것도 넣지 않을 경우엔 DispatcherType.REQUEST가 호출되며 클라이언트 요청이 있는 경우에만 필터가 적용된다.
    • 오류 페이지 요청 전용 필터를 적용하고 싶다면 DispatcherType.ERROR만 지정해주면 된다.

서블릿 예외 처리 - 인터셉터

아래를 통해 인터셉터 중복 호출 제거 방법을 알아보자. 

스프링이 제공하는 기능 - 인터셉터 중복 호출 제거

필터는 필터를 등록할 때 어떤 DispatcherType인 경우에 필터를 적용할 수 있는지 선택을 할 수 있었다. 그러나 인터셉터의 경우엔 스프링이 제공하는 기능이기 때문에 DistpacherType과 무관하게 항상 호출된다.

  • DispatcherType : 스프링이 제공하는 기능
  • filter: 서블릿이 제공하는 기능
  • interceptor: 스프링이 제공하는 
    • DispatcherType과 interceptor는 스프링이 제공하고 있기 때문에 선택이 아닌 항상 호출된다.

excludPathPatterns( )

인터셉터는 DispatcherType 적용 여부와 무관하게 항상 호출되기 때문에 오류 페이지 경로를 excludPathPatterns( )를 사용해서 빼주면 된다.

앞서서 인터셉터 등록 방식은 살펴보았다.

.excludePathPatterns(
 "/css/**", "/*.ico"
 , "/error", "/error-page/**" //오류 페이지 경로
 );

필터 - Dispatcher와 인터셉터 - 경로 중복 호출 제거로 중복 호출을 제거한 전체 흐름

1. WAS(/error-ex, dispatchType=REQUEST) -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러
2. WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)
3. WAS 오류 페이지 확인
4. WAS(/error-page/500, dispatchType=ERROR) -> 필터(x) -> 서블릿 -> 인터셉터(x) -> 컨트롤러(/error-page/500) -> View