Spring은 공통적으로 여러 작업을 처리함으로써 중복된 코드를 제거할 수 있도록 많은 기능을 제공해주고 있습니다. 그 중에서 필터와 인터셉터의 차이에 대해서 알아보려고 합니다.
디스패처 서블릿(Dispatcher Servlet)에 요청이 전달되기 전, 후에 url 패턴에 맞는 모든 요청에 대해 부가작업을 처리할 수 있는 기능을 이야기합니다. 디스패처 서블릿은 스프링의 가장 앞단에 존재하는 프론트 컨트롤러이므로 스프링 컨테이너가 아닌 웹 컨테이너에 의해서 관리가 됩니다. 즉, 필터는 스프링 범위 밖에서 처리가 되는 것을 의미합니다.
필터를 추가하기 위해서는 Filter 인터페이스를 구현해야하며, 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() {}
}
init 메소드: 필터 객체를 초기화하고 서비스에 추가하기 위한 메소드입니다. 웹 컨테이너가 1회 init 메소드를 호출하여 필터 객체를 초기화하면 이후의 요청들은 doFilter를 통해 처리가 됩니다.
doFilter 메소드: Http요청이 디스패처 서블릿으로 전달되기 전에 웹 컨테이너에 의해 실행되는 메소드입니다. doFilter의 파라미터인 FilterChain의 doFilter를 통해 다음 대상으로 요청을 처리하게 됩니다.
즉, chain.doFilter 전후로 우리가 필요한 처리과정을 넣어줌으로써 원하는 처리를 진행할 수 있습니다.
destroy 메소드: 필터 객체를 서비스에서 제거하고 사용하는 자원을 반환하기 위한 메소드입니다. 이 메소드는 웹 컨테이너에 의해서 1번 호출되며 이후에는 doFilter에 의해 처리되지 않습니다.
Filter와 달리 Spring이 제공하는 기술로 디스패처 서블릿(Dispatcher Servlet)이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공합니다.
즉, 필터와 달리 인터셉터는 스프링 컨텍스트에서 동작을 합니다.
디스패처 서블릿은 핸들러 매핑을 통해 적절한 컨트롤러를 찾도록 요청을하는데, 그 결과로 실행 체인을 돌려줍니다. 이 실행 체인은 1개 이상의 인터셉터가 등록되어 있다면 순차적으로 인터셉터들을 거쳐 컨트롤러가 실행되도록 하고, 만약 인터셉터가 없다면 바로 컨트롤러를 실행합니다.
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
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 {
}
}
preHandle 메소드: 컨트롤러가 호출되기 전에 실행되는 메소드로, 그렇기 때문에 컨트롤러 이전에 처리해야하는 전처리 작업이나 요청 정보를 가공하거나 추가하는 경우에 사용이 되며, preHandle의 3번째 파라미터인 handle 파라미터는 핸들러 매핑이 찾아준 컨트롤러 빈에 매핑되는 @RequestMapping의 메소드 정보를 추상화한 객체입니다.
preHandle의 반환 타입은 boolean으로 true일 경우 다음단계로 진행이 됩니다.
postHandle 메소드: 컨트롤러를 호출한 후에 실행되는 메소드로 컨틀롤러 이후에 처리해야하는 후처리 작업이 있을 때 사용이 됩니다. 이 메소드에는 컨트롤러가 반환하는 ModelAndView 타입의 정보가 제공되는데, 최근에는 Json형태로 데이터를 저장하는 RestAPI기반의 컨트롤러를 만들면서 자주 사용되지는 않습니다.
또한, 컨트롤러 하위 계층에서 작업을 진행하다가 중간에 예외가 발생하면 postHandle은 호출되지 않습니다.
afterCompletion 메소드: 모든 뷰에서 최종 결과를 생성하는 일을 포함해 모든 작업이 완료된 후에 실행되는 메소드입니다. 이 메소드는 요청 처리 중에 사용한 리소스를 반환할 때 사용하기에 적합합니다.
또한 postHandler와는 달리 컨트롤러 하위 계층에서 작업을 진행하다가 중간에 예외가 발생하더라도 반드시 호출이 됩니다.