스프링 인터셉터(Interceptor)와 서블릿 필터(Filter)의 차이점 및 활용법

자바 기반의 웹 애플리케이션을 개발하다 보면 로그인 여부 체크, 권한 확인, XSS(크로스 사이트 스크립팅) 방어, 요청 로그 기록 등 모든 HTTP 요청에서 공통으로 처리해야 하는 전처리 작업이 발생합니다.

이때 비즈니스 로직이 포함된 컨트롤러(Controller)마다 동일한 코드를 중복해서 작성하는 것은 객체 지향 설계에 위배됩니다. 스프링 부트(Spring Boot) 웹 아키텍처에서는 이러한 공통 관심사를 일괄 처리하기 위해 서블릿 필터(Servlet Filter)와 스프링 인터셉터(Spring Interceptor)라는 두 가지 핵심 기술을 제공합니다.

두 기술은 공통 처리를 수행한다는 목적은 같지만, 동작하는 위치와 제어할 수 있는 자원에 명확한 차이가 있습니다. 이번 글에서는 실무 면접 단골 주제인 필터와 인터셉터의 근본적인 차이점과 올바른 활용 상황을 정리해 보겠습니다.

1. 서블릿 필터(Servlet Filter)란 무엇인가?

1-1. 필터의 정의와 위치

필터는 자바 서블릿(Servlet) 스펙에서 제공하는 기술로, 스프링 컨텍스트(스프링 프레임워크) 영역이 아닌 웹 애플리케이션(톰캣 같은 서블릿 컨테이너) 환경 내에서 동작합니다.

디스패처 서블릿(Dispatcher Servlet)에 HTTP 요청이 도달하기 전과, 웹 브라우저로 응답이 나가기 직전의 최전선에서 요청과 응답 데이터를 가로채고 변환할 수 있는 기능을 제공합니다.

1-2. 필터의 핵심 메서드

필터를 구현하려면 javax.servlet.Filter 인터페이스를 구현해야 하며, 다음 3가지 메서드를 오버라이딩합니다.

  • init(): 필터가 웹 컨테이너에 의해 생성될 때 최초 1번 실행되는 초기화 메서드입니다.
  • doFilter(): 필터의 핵심입니다. HTTP 요청이 들어올 때마다 실행되며, 이 안에서 공통 로직을 수행합니다. 다음 필터나 서블릿으로 요청을 넘기려면 반드시 chain.doFilter(request, response)를 호출해야 합니다.
  • destroy(): 필터 객체가 소멸할 때 실행되는 종료 메서드입니다.

2. 스프링 인터셉터(Spring Interceptor)란 무엇인가?

2-1. 인터셉터의 정의와 위치

인터셉터는 서블릿 스펙이 아닌 스프링 프레임워크가 자체적으로 제공하는 기술입니다. 따라서 디스패처 서블릿(Dispatcher Servlet)이 요청을 받은 후, 해당 요청을 처리할 실제 컨트롤러(Controller)에 도달하기 직전과 직후에 동작합니다.

스프링 컨텍스트 내부에서 실행되므로 스프링의 모든 빈(Bean) 객체에 쉽게 접근할 수 있으며, 컨트롤러의 핸들러(메서드) 정보나 리턴되는 ModelAndView 등의 풍부한 웹 정보를 다룰 수 있습니다.

2-2. 인터셉터의 핵심 메서드

인터셉터를 구현하려면 HandlerInterceptor 인터페이스를 구현하며, 총 3가지 타이밍의 메서드를 제공합니다.

  • preHandle(): 컨트롤러 메서드가 실행되기 전에 호출됩니다. 반환 타입이 boolean이며, false를 반환하면 요청이 중단되어 컨트롤러로 넘어가지 않습니다. (인증 체크에 주로 활용)
  • postHandle(): 컨트롤러 메서드가 정상적으로 실행을 마친 후, 뷰(View)가 렌더링 되기 전에 호출됩니다. 컨트롤러가 반환한 ModelAndView를 가공할 수 있습니다.
  • afterCompletion(): 뷰 렌더링을 포함한 모든 요청 처리가 완전히 완료된 후 호출됩니다. 프로그램 실행 중 예외(Exception)가 발생하더라도 무조건 실행되므로, 사용한 리소스를 정리하거나 실행 시간을 로그로 남길 때 유용합니다.

3. 필터와 인터셉터의 3가지 핵심 차이점

두 기술의 동작 타이밍이 다르다는 것은 알았지만, 실무 성능과 기능 아키텍처 측면에서 어떤 차이가 발생하는지 구체적으로 비교해 보겠습니다.

3-1. 예외 처리(Exception Handling)의 범위

  • 필터(Filter): 스프링 프레임워크 바깥에서 동작하므로, 컨트롤러나 서비스에서 발생한 예외가 스프링 내부의 @RestControllerAdvice로 처리되지 못하고 서블릿 컨테이너까지 튕겨져 나갔을 때만 예외를 감지할 수 있습니다. 즉, 필터 내부에서 발생한 에러는 스프링의 예외 처리 기술을 타지 못합니다.
  • 인터셉터(Interceptor): 스프링 내부에서 동작하므로 컨트롤러에서 예외가 발생하면 인터셉터의 afterCompletion() 메서드에서 해당 예외(Exception ex)를 파라미터로 그대로 전달받아 로그를 남기거나 제어할 수 있습니다.

3-2. Request/Response 객체 조작 가능 여부

  • 필터(Filter): 필터는 chain.doFilter(request, response)를 호출할 때 내가 커스텀하게 가공한 가짜 요청(ServletRequestWrapper)이나 가짜 응답 객체를 다음 단계로 넘겨줄 수 있습니다. 즉, HTTP 요청의 본문(Body) 내용을 변경하거나 암호화하는 등의 작업이 가능합니다.
  • 인터셉터(Interceptor): 인터셉터는 디스패처 서블릿이 이미 구체적인 컨트롤러 매핑을 마친 뒤 요청을 전달받기 때문에, 파라미터로 넘어온 HttpServletRequest 내부의 데이터를 읽을 수는 있어도 객체 자체를 다른 객체로 바꿔치기할 수는 없습니다.

3-3. 컨트롤러(Handler) 정보 참조 여부

  • 필터(Filter): 어떤 컨트롤러의 어떤 메서드로 요청이 들어가는지 전혀 알지 못합니다. 오직 URL 경로(주소) 기반으로만 필터링을 수행합니다.
  • 인터셉터(Interceptor): preHandle()의 파라미터로 Object handler를 받습니다. 이를 통해 현재 요청을 처리할 컨트롤러 객체와 메서드의 자바 반환 타입, 적용된 어노테이션 정보(@LoginCheck 등)까지 세부적으로 파악하여 동적인 권한 제어가 가능합니다.

4. 실무에서는 각각 언제 사용해야 할까?

비슷해 보이는 기술이지만 특징이 명확하므로 실무에서는 다음과 같은 기준으로 분리하여 구현합니다.

🛠 서블릿 필터를 사용하는 경우 (웹 전반의 공통 관심사)

  • 보안 관련 공통 필터링 (XSS 방어, CORS 설정, SQL 인젝션 방지)
  • HTTP 요청 데이터의 로깅 및 인코딩 변환 (UTF-8 설정 등)
  • 웹 애플리케이션 전반에 적용되어야 하는 대규모 이미지/파일 압축 및 암호화

🛠 스프링 인터셉터를 사용하는 경우 (비즈니스 로그인/권한 관심사)

  • 세션 또는 JWT 토큰을 활용한 세부 로그인 인증/인가 체크
  • 컨트롤러로 들어오는 파라미터 데이터의 세부 검증 가공
  • 특정 마케팅 URL의 실행 시간(성능) 측정 및 통계 로그 수집

5. 결론 및 요약

구분서블릿 필터 (Filter)스프링 인터셉터 (Interceptor)
관리 컨테이너서블릿 컨테이너 (Tomcat 등)스프링 컨테이너 (ApplicationContext)
작동 위치웹 요청의 최전선 (디스패처 서블릿 전/후)스프링 MVC 영역 내부 (컨트롤러 전/후)
인터페이스javax.servlet.Filterorg.springframework.web.servlet.HandlerInterceptor
주요 매개변수ServletRequest, ServletResponseHttpServletRequest, HttpServletResponse, Object handler
객체 변환 가능 여부O (Wrapper 클래스 이용 가능)X (참조 및 읽기만 가능)

필터와 인터셉터는 자바 백엔드 아키텍처의 유연성을 극대화해 주는 고마운 도구입니다. 웹 서버의 인프라적 제어가 필요할 때는 필터를, 스프링 빈을 적극적으로 활용하며 세부 컨트롤러 권한을 쪼개야 할 때는 인터셉터를 선택하는 혜안이 필요합니다.