
Filter와 Interceptor
Filter와 Interceptor에 대해서 좀 더 자세하게 알고 싶어서 정리하려고 합니다.
🏷️ Filter
필터(Filter) 디스패처 서블릿에 요청이 전달되기 전/후에 어떠한 작업을 처리할 수 있는 기능을 제공합니다. 디스패처 서블릿은 스프링 컨텍스트의 영역이 아닌, WAS 같은 톰캣 영역에서 관리된다. 호출 순서는 다음과 같습니다.

package jakarta.servlet;
import java.io.IOException;
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {}
void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
default void destroy() {}
}
필터를 설정하려면 위와 같이 javax.servlet 패키지의 Filter(Interface)를 구현해야 하는데, 이 클래스가 구성하고 있는 메서드는 총 3개입니다.
✅ Init(FilterConfig)
웹 컨테이너가 서비스를 시작하고 있다는 것을 필터에게 알려주기 위해 사용되며, 서블릿 컨테이너는 필터를 인스턴스화 한 후 딱 한 번 init 메서드를 호출합니다.
FilterConfig : 필터의 초기화를 위한 설정 정보를 제공하는 객체
필터가 필터링 작업을 수행하도록 요청받기 전에 init 메서드가 성공적으로 완료되어야 하며, 이 메서드가 실행되어 필터 객체가 초기화되었다면, 이후의 요청들은 모두 doFilter를 거치게 됩니다.
✅ doFilter(ServletRequest, ServletResponse, FilterChain)
클라이언트의 요청/응답이 체인을 통과할 때 마다 컨테이너에 의해 호출되며, 필터 체인이 이 메서드에 전달되면 필터가 요청 및 응답을 체인의 다음 엔티티로 전달할 수 있습니다.
ServletRequest : 요청에 대한 정보를 제공하는 객체
ServletResponse : 응답에 대한 정보를 제공하는 객체
FilterChain : 다음 필터 또는 서블릿으로 요청을 전달하는 데 사용되는 객체
여러 개의 필터가 존재할 때 다음 필터로 넘어갈 때마다 FilterChain의 doFilter 메서드를 사용해서 필요한 동작을 하도록 만들 수 있습니다.
✔️ chain.doFilter(request, response)를 호출하지 않으면 다음 단계(다음 필터나 서블릿)로 진행되지 않고 요청이 중단됩니다.
✅ destroy()
웹 컨테이너가 서비스를 중단하고 있다는 것을 필터에게 알려주기 위해 사용된다. 이 메서드는 필터의 doFilter 메서드 내의 모든 스레드가 종료되거나 시간 초과가 난 경우에만 호출됩니다.
웹 컨테이너가 이 메서드를 호출한 이후 필터 인스턴스에서 doFilter 메서드를 다시 호출하지 않으며, 이 메서드가 호출되면 필터가 보유 중인 리소스(예: 메모리, 파일 핸들, 스레드)를 삭제합니다.
🏷️ Interceptor
인터셉터는 필터와 달리 스프링 프레임워크가 제공하는 기술로 스프링에서 직접 제공하는 기능이기 때문에 디스패처 서블릿이 컨트롤러를 호출하기 전/후에 어떠한 작업을 처리할 수 있습니다. 당연하게도 인터셉터는 스프링에서 제공하는 기능이기도 하고 디스패처 서블릿을 중심으로 처리되기 때문에 웹 컨텍스트가 아닌 스프링 컨텍스트에서 실행된다.
보통 디스패처 서블릿은 핸들러 매핑을 통해 클라이언트가 요청한 API에 맞는 컨트롤러를 찾아주는데, 찾아주는 과정에서 인터셉터가 등록되어 있다면 차례대로 거쳐서 컨트롤러가 실행됩니다. 만약 인터셉터가 존재하지 않는다면 핸들러 매핑은 곧바로 컨트롤러를 실행하게 되며, 호출 순서는 다음과 같습니다.

package org.springframework.web.servlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
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(HttpServletRequest, HttpServletResponse, Object)
디스패처 서블릿이 컨트롤러에게 작업을 위임하기 전에 실행되며, 보통 컨트롤러 이전에 처리해야 하는 전처리 작업 또는 요청 정보를 가공하거나 추가하는 경우에 많이 사용합니다.
HttpServletRequest : 요청에 대한 정보를 제공하는 객체
HttpServletResponse : 응답에 대한 정보를 제공하는 객체
Object handler : 실행될 컨트롤러의 메서드 정보
preHandle 메서드는 boolean 값을 반환해야 하며, 반환 값이 true면 요청을 계속 처리하고, false면 요청 처리를 중단하고 다른 위치로 리디렉션하거나 예외를 던질 수 있습니다.
✅ postHandle(HttpServletRequest, HttpServletResponse, Object, ModelAndView)
디스패처 서블릿이 컨트롤러에게 작업을 위임하고, 해당 컨트롤러의 메서드가 실행된 후에 호출됩니다.
ModelAndView
컨트롤러에서 반환된 ModelAndView 객체로, 이 객체를 통해 뷰에 전달할 데이터를 조작하거나 추가할 수 있습니다. 하지만 최근에는 Json 형태의 데이터를 반환하도록 할 수 있는 @RestController가 생기면서 많이 사용되지 않는 메서드입니다.
✅ void afterCompletion(HttpServletRequest, HttpServletResponse, Object, Exception)
디스패처 서블릿을 포함한 모든 작업이 완료된 후에 실행됩니다.
Exception
요청 처리 중 발생한 예외를 나타내는 객체로, 예외가 발생하지 않은 경우 null이 반환됩니다. 요청 처리가 완료된 후에 호출되며, 주로 리소스 정리 또는 추가적인 작업을 수행하는데 사용됩니다.
🏷️ 사용 이유
✅ 필터를 사용하는 이유
필터는 기본적으로 WAS 단에서 동작하기 때문에 주로 스프링과 무관한 기능들을 처리하게 됩니다. 예를 들면 아래와 같은 기능들이 있습니다.
- 보안 및 인증 관련 작업
- 이미지/데이터 압축 및 문자열 인코딩
필터는 인터셉터보다 앞단에서 동작하기 때문에 보안 처리로 올바른 요청이 아닐 경우 요청을 차단할 수 있고 웹 애플리케이션에 전반적으로 사용되는 기능을 구현하기에 적합니다.
✅ 인터셉터를 사용하는 이유
인터셉터는 Controller가 실행되기 전/후에 추가적인 작업을 실행할 수 있는데 대표적인 예시는 권한을 검증하는 로직 등이 있습니다. 만약 인터셉터를 사용하지 않을 때 권한을 검증하는 로직이 필요하다면, 권한이 필요한 모든 컨트롤러에 권한을 검증하는 로직이 작성되어 있어야 합니다.
하지만, 이 방법에는 치명적인 단점들이 생기게 됩니다.
- 반복되는 코드 증가 : 해당 기능을 적용해야 할 컨트롤러가 늘어날수록 중복되는 코드가 비례하게 늘어나게 되어 메모리 낭비와 서버의 부하 증가 및 유지보수가 힘들어 집니다.
- 코드 신뢰도 감소 : 같은 작업을 개발자가 일일이 해줘야 하다 보니, 실수가 있을 수 있으며, 특히 권한 관련 로직에 문제가 생긴다면 일반 사용자가 관리자 권한을 사용할 수도 있는 것이다.
이러한 문제점을 줄이기 위한 수단으로, 인터셉터를 도입해 볼 수 있고 인터셉터를 사용하게 된다면, 개발자는 핸들러의 수만큼 작성했던 권한 검증 로직을 인터셉터 클래스 하나로 관리할 수 있게 됩니다.
✔️ 예외 처리 차이
- Filter: 예외가 발생하면 웹 컨테이너(WAS)까지 나가서 에러 페이지를 보여줘야 합니다.
- Interceptor: 스프링 내부에 있으므로 @ControllerAdvice 같은 스프링의 예외 처리 기능을 그대로 사용할 수 있습니다.
📖 Reference
'코딩 공부 > web & Spring' 카테고리의 다른 글
| [Web] Web Server와 WAS (0) | 2026.01.01 |
|---|---|
| [Web / JWT / Spring] HttpOnly 쿠키와 보안 (0) | 2025.12.21 |
| [Spring] STOMP + Spring Security에서 principal이 null 값 뜨는 경우 (0) | 2025.12.14 |
| [Spring / JWT] RefreshToken과 적용 (0) | 2025.12.13 |
| [Spring] Pageable (0) | 2025.04.08 |