Filter와 Interceptor, 둘 다 전후처리 용도로 사용될 수 있다는 점에선 동일한 것 같다.
구체적으로 어떤 차이가 있는 지 정리해보았다.

Filter

Filter는 Java의 Servlet 스펙에서 정의된 개념이다.
Java Servlet의 스펙이므로 스프링 프레임워크가 없이도 사용 가능하다.
SpringMVC를 사용하는 경우 DispatcherServlet 전후로 호출된다.

Interceptor

Interceptor는 스프링의 스펙으로, Filter와 목적은 동일하나 좀 더 세분화된 컨트롤을 제공한다.

When to use Interceptor

세분화된 컨트롤을 하고자 하는 경우

Filter는 전, 후 처리만 가능하지만 Interceptor는 preHandle, postHandler, afterCompletion로 세분화된다.
그 외 WebContentInterceptor, LocaleChangeInterceptor 등의 상황에 맞게 활용할 수 있는 다양한 인터페이스를 제공한다.

ModelAndView를 컨트롤 해야하는 경우

Filter는 DispatcherServlet의 영역이 아니기 때문에 ModelAndView에 접근이 불가하다.
Interceptor는 DispatcherServlet 사이클 안에서 사용되므로 ModelAndView를 접근할 수 있다.

public interface HandlerInterceptor {
    // ... 생략
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            @Nullable ModelAndView modelAndView) throws Exception {
    }

When to use Filter

HttpServletRequest, HttpServletResponse를 유연하게 컨트롤하고자 하는 경우

Filter는 다음 Filter로 체이닝을 할때 새로운 HttpServletRequest, HttpServletResponse를 넘길 수 있다.
Interceptor는 이미 DispatcherServlet으로 넘어온 상태이기 때문에 HttpServletRequest, HttpServletResponse를 다른 인스턴스로 교체할 수 있는 방법이 없다.

예를 들어 다음 상황에서 Filter가 좀 더 유연하다.

  • ServletRequest의 Body를 여러번 읽어야 하는 경우 (ex: 로깅)
    ServletRequest의 Body는 한 번 밖에 읽을 수 없다. 여러번 읽을 수 있게 원본 Request에서 읽은 내용을 byte[] 버퍼에 저장해둔 새로운 ServeletRequest를 정의하여 넘길 수 있다.

이처럼 재정의한 인스턴스로 넘길 수 있기 때문에 유연하게 내가 원하는 기능을 추가할 수 있을 것이다.

참고로 SpringSecurity는 Filter 기반으로 동작한다. (링크)

Appendix

다음은 Filter에서 HttpServletRequest, HttpServletResponse를 수정하는 예시다.

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
      throws IOException, ServletException {
        HttpServletRequest currentRequest = (HttpServletRequest) servletRequest;
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(currentRequest);
        chain.doFilter(wrappedRequest, servletResponse);
    }

'개발 > Spring' 카테고리의 다른 글

[Spring] 스프링 빈(Bean) 라이프사이클  (0) 2020.05.23
[SpringMVC] CORS 처리  (2) 2020.03.31

+ Recent posts