[Spring] 필터(Filter)와 인터셉터(Interceptor)의 개념 및 차이

썸머·2022년 11월 4일

공통 관심사의 분리

  • 공통 관심사란 여러 로직에서 공통으로 관심이 있는 것이다.

  • 예를 들어, 상품 관리 컨트롤러에서 로그인 여부를 체크하는 로직을 하나하나 작성하면 되겠지만, 등록,수정,삭제,조회 등등 상품관리의 모든 컨트롤러 로직에 공통으로 로그인 여부를 확인해야한다.

  • 이러한 공통 관심사는 스프링의 AOP로도 해결할 수 있지만, 웹과 관련한 공통 관심사는 지금부터 설명할 서블릿 필터 또는 스프링 인터셉터를 사용하는 것이 좋다.

필터(Filter)

필터는 서블릿이 지원하는 수문장

  • 필터 흐름

    HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러

  • 필터 제한

    HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러 //로그인 사용자
    HTTP 요청 -> WAS -> 필터(적절하지 않은 요청이라 판단, 서블릿 호출X) //비 로그인 사용자

  • 필터 체인

    HTTP 요청 -> WAS -> 필터1 -> 필터2 -> 필터3 -> 서블릿 -> 컨트롤러

         -> 중간에 필터를 자유롭게 추가할 수 있다.

  • 필터 인터페이스
public interface Filter {
 public default void init(FilterConfig filterConfig) throws ServletException 
{}
 public void doFilter(ServletRequest request, ServletResponse response,
 FilterChain chain) throws IOException, ServletException;
 public default void destroy() {}
}

1) init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다.
2) doFilter(): 고객의 요청이 올 때 마다 해당 메서드가 호출된다. 필터의 로직을 구현하면 된다.
3) destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.

  • 필터 등록하는 방법
@Configuration
public class WebConfig {
 @Bean
 public FilterRegistrationBean logFilter() {
 FilterRegistrationBean<Filter> filterRegistrationBean = new
FilterRegistrationBean<>();
 filterRegistrationBean.setFilter(new LogFilter());
 filterRegistrationBean.setOrder(1);
 filterRegistrationBean.addUrlPatterns("/*");
 return filterRegistrationBean;
 }
}

1) FilterRegistrationBean을 사용한다.

  • @ServletComponentScan, @WebFilter(filterName="logFilter", urlPatterns = "/*")로도 필터 등록이 가능하지만 필터 순서 조절이 안된다.

2) setFilter(new LogFilter()) : 등록할 필터를 지정한다.
3) setOrder(1) : 필터는 체인으로 동작한다. 따라서 순서가 필요하다. 낮을 수록 먼저 동작한다.
4) addUrlPatterns("/*") : 필터를 적용할 URL 패턴을 지정한다. 한번에 여러 패턴을 지정할 수 있다.

인터셉터(Interceptor)

  • 스프링 인터셉터 흐름

    HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러

  • 스프링 인터셉터 제한

    HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 -> 컨트롤러 //로그인 사용자
    HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터(적절하지 않은 요청이라 판단, 컨트롤러 호출
    X) // 비 로그인 사용자

  • 스프링 인터셉터 체인

    HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 인터셉터1 -> 인터셉터2 -> 컨트롤러

  • 스프링 인터셉터 인터페이스

public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse 
response,
 Object handler) throws Exception {}
default void postHandle(HttpServletRequest request, HttpServletResponse 
response,
 Object handler, @Nullable ModelAndView modelAndView)
throws Exception {}
default void afterCompletion(HttpServletRequest request, HttpServletResponse 
response,
 Object handler, @Nullable Exception ex) throws
Exception {}
}


1) preHandle : 컨트롤러 호출 전에 호출된다. (더 정확히는 핸들러 어댑터 호출 전에 호출된다.) preHandle 의 응답값이 true 이면 다음으로 진행하고, false 이면 더는 진행하지 않는다. false인 경우 나머지 인터셉터는 물론이고, 핸들러 어댑터도 호출되지 않는다. 그림에서 1번에서 끝이 나버린다.
2) postHandle : 컨트롤러 호출 후에 호출된다. (더 정확히는 핸들러 어댑터 호출 후에 호출된다.)
3) afterCompletion : 뷰가 렌더링 된 이후에 호출된다.


예외가 발생시
1) preHandle : 컨트롤러 호출 전에 호출된다.
2) postHandle : 컨트롤러에서 예외가 발생하면 postHandle 은 호출되지 않는다.
3) afterCompletion : afterCompletion 은 항상 호출된다. 이 경우 예외를 파라미터 로 받아서 어떤 예외가 발생했는지 로그로 출력할 수 있다

필터와 인터셉터 차이

차이점필터인터셉터
제공자서블릿스프링 MVC
제공 함수doFilter()preHandle(), postHandle(), afterCompletion()
profile
썸머의 개발블로그

0개의 댓글