개발 시, 공통적으로 처리해야 하는 로직들이 생길 때가 많다.
이럴 때마다 공통 업무에 관련된 코드들을 페이지 마다 작성한다면 중복 코드가 많아지고, 서버에 부하를 줄 수도 있다.
이런 문제를 처리하기 위해 Spring에서는 공통적으로 여러 작업을 처리함으로써 중복 코드를 제거 할 수 있는 기능들인 필터와 인터셉터를 지원하고 있다.
필터와 인터셉터 모두 공통 관심사를 처리할 때 사용되는 기능들이다.

필터는 Servlet 스펙에 정의된 기능으로, 요청과 응답을 거른 뒤 정제하는 역할을 하며, Dispatcher Servlet보다 먼저 동작하는 레벨에서 요청을 처리한다.
즉, 사용자의 요청이 Spring MVC의 핵심 컨트롤러인 DispatcherServlet에 도달하기 전에 먼저 거치게 되는 중간 단계라고 할 수 있다.
필터는 자바 웹 애플리케이션이 작동하는 가장 바깥 영역에서 동작하기 때문에, 정적 자원을 포함한 모든 HTTP 요청에 대해 적용된다.
또한, 스프링 컨테이너가 아닌 톰캣과 같은 웹 컨테이너에 의해 관리가 되며, 스프링 범위 밖에서 처리된다.
필터를 사용하기 위해서는 javax.servlet.Filter 인터페이스를 구현해야 하며, 다음과 같은 메소드를 가진다.
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() {}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("필터 초기화");
}
chain.doFilter()로 전, 후에 필요한 처리 과정을 넣어서 원하는 처리를 진행할 수 있다.@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 요청 전 처리
System.out.println("요청 전 필터 처리");
chain.doFilter(request, response); // 다음 필터 또는 서블릿 호출
// 응답 후 처리
System.out.println("응답 후 필터 처리");
}
@Override
public void destroy() {
System.out.println("필터 종료");
}
➡️필터는 기본적으로 스프링과 무관하게 전역적으로 처리해야 하는 작업들을 처리할 수 있다.

인터셉터는 Spring MVC에서 제공하는 기능으로, DispatcherServlet이 요청을 받아 Controller를 호출하기 전 / 후, 그리고 응답이 렌더링 되기 직전에 끼어들어 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공한다.
웹 컨테이너에서 동작하는 필터와 달리 인터셉터는 스프링 컨텍스트에서 동작한다.
디스패처 서블릿이 핸들러매핑을 통해 컨트롤러를 찾도록 요청하는데, 그 결과로 실행 체인(HandlerExecutionChain)을 돌려준다.
여기에 인터셉터가 등록되어 있다면 순차적으로 인터셉터들을 거쳐 컨트롤러가 실행되도록 하고, 인터셉터가 없다면 바로 컨트롤러를 실행한다.
인터셉터를 추가하기 위해서 org.springframework.web.servlet의 HandlerInterceptor 인터페이스를 구현해야하며, 다음과 같은 메서드를 가진다.
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception;
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("Interceptor - preHandle");
return true; // false를 리턴하면 요청이 컨트롤러까지 가지 않음
}
ModelAndView 타입의 정보가 제공되는데, 최근에는 JSON 형태로 데이터를 제공하는 RestAPI기반의 컨트롤러(@RestController)를 만들면서 자주 사용되지 않는다.@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor - postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
System.out.println("Interceptor - afterCompletion");
}
➡️인터셉터에서는 클라이언트의 요청과 관련되어 전역적으로 처리해야하는 작업들을 처리할 수 있다.
| 항목 | Filter | Interceptor |
|---|---|---|
| 기반 기술 | Servlet 스펙 | Spring MVC |
| 관리되는 컨테이너 | 웹 컨테이너 | 스프링 컨테이너 |
| 동작 위치 | DispatcherServlet 이전 | DispatcherServlet 이후 |
| 적용 대상 | 모든 요청 (정적 리소스 포함) | 스프링 컨트롤러 요청만 |
| 용도 | 1. 공통된 보안 및 인증/인가 관련 작업 2. 모든 요청에 대한 로깅 또는 감사 3. 이미지/데이터 압축 및 문자열 코딩 4. Spring과 분리되어야 하는 기능 | 1. 세부적인 보안 및 인증/인가 공통 작업 2. API 호출에 대한 로깅 또는 감사 3. Controller로 넘겨주는 정보(데이터)의 가공 |
필터와 인터셉트 모두 비즈니스 로직과 분리되어 특정 요구사항(보안, 인증, 인코딩 등)을 만족시켜야할 때 적용 한다.
필터는 특정 요청과 컨트롤러에 관계 없이 전역적으로 처리해야하는 작업이나 웹 어플리케이션에 전반적으로 사용되는 기능을 구현할 때 적용하고,
인터셉터는 클라이언트의 요청과 관련된 작업에 대해 추가적인 요구사항을 만족해야할 때 적용한다.