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 |