Servlet Filter, interceptor 차이

  • Servlet 실행 전, 후에 어떤 작업을 하고자 할 때 Servelt Filter를 사용한다.

서블릿 필터 정의 : Dispatcher Servlet에 요청이 전달되기 전, 후에 부가작업을 처리하는 객체

  1. @Component : 모든 url 패턴에 대해 적용되버림 .

  2. @WebFilter 어노테이션을 달면 특정 url 패턴에 대해서만 필터를 적용하게 할 수 있다. 다만 순서를 지정할 수가 없다.

  3. FilterRegistrationBean으로 적용

    1. setFitler, setOrder,addUrlPattern 등으로 부가 설정을 가장 많이 할 수 있다.

스프링 인터셉터 인터페이스

chevron-right핸들러 어댑터 종류?hashtag

## 1. 어노테이션 기반 컨트롤러 (Annotation-driven Controller)

오늘날 스프링 MVC의 표준이자 가장 널리 사용되는 방식입니다. @Controller 또는 @RestController 어노테이션을 클래스에 붙이고, @RequestMapping (또는 @GetMapping, @PostMapping 등)을 메서드에 붙여 요청을 처리합니다.

  • 특징: 매우 유연하고 직관적입니다. 파라미터나 반환 타입을 자유롭게 사용할 수 있습니다 (@RequestParam, @RequestBody, String, ResponseEntity 등).

  • 코드 예시:

    Java

  • 처리 어댑터: RequestMappingHandlerAdapter


## 2. Controller 인터페이스 구현체

스프링 초창기부터 사용된 가장 전통적인 방식입니다. org.springframework.web.servlet.mvc.Controller 인터페이스를 직접 구현해야 합니다.

  • 특징: handleRequest라는 단 하나의 메서드만 구현하면 되므로 구조가 매우 단순합니다. 다만, 반환 타입이 ModelAndView로 고정되어 있어 유연성이 떨어집니다.

  • 코드 예시:

    Java

  • 처리 어댑터: SimpleControllerHandlerAdapter


## 3. 함수형 핸들러 (Functional Handler)

Spring 5부터 도입된 방식으로, 람다식을 사용하여 요청과 응답을 함수(Function)로 정의합니다. 어노테이션 없이 코드로 직접 라우팅 규칙을 설정합니다.

  • 특징: 매우 간결하며, 컴파일 시점에 타입 체크가 가능합니다. 함수형 프로그래밍에 익숙하다면 강력한 방식입니다. 주로 RouterFunctionHandlerFunction을 조합하여 사용합니다.

  • 코드 예시:

    Java

  • 처리 어댑터: HandlerFunctionAdapter

모든 인터셉터 성공적으로 실행 완료 되면?

postHandle에 등록된 역순으로 인터셉터가 실행된다.

view 관련 로직까지 완료가 된 후에

이제 스프링 인터셉터 AfterCompletion 메서드가 실행된다.

## 1. @ControllerAdvice: 컨트롤러를 위한 전역 보좌관 👨‍⚕️

@ControllerAdvice는 모든 @Controller 또는 특정 패키지의 컨트롤러에 대해 전역적으로 적용되는 로직을 정의할 때 사용합니다. 주로 다음과 같은 세 가지 목적으로 쓰입니다.

  1. 전역 예외 처리 (@ExceptionHandler): 여러 컨트롤러에서 발생할 수 있는 특정 예외(e.g., IllegalArgumentException)를 한 곳에서 잡아 공통된 에러 응답(JSON 또는 에러 페이지)을 보내줍니다. 이것이 가장 핵심적인 용도입니다.

    Java

  2. 공통 모델 데이터 추가 (@ModelAttribute): 모든 뷰(View)에 공통으로 필요한 모델 데이터(e.g., 현재 로그인 사용자 정보)를 자동으로 추가해 줍니다.

  3. 데이터 바인딩 설정 (@InitBinder): 모든 컨트롤러에 적용될 커스텀 데이터 바인딩 규칙을 정의합니다.

@ControllerAdviceDispatcherServlet이 컨트롤러를 실행하는 과정에서 발생하는 특정 상황(예외 등)에 개입하는 특수 부대와 같습니다.


## 2. 요청/응답(Request/Response)을 바꾸는 경우

요청과 응답을 중간에 변경하는 작업은 주로 **필터(Filter)**의 역할입니다. 필터는 DispatcherServlet에 요청이 전달되기 전, 가장 바깥단에서 동작하여 원본 요청과 응답에 직접 관여하기 때문입니다.

  • Request를 바꾸는 경우

    • 문자 인코딩 설정: 모든 요청의 인코딩을 UTF-8로 강제하는 CharacterEncodingFilter.

    • 요청 본문 재사용: 로깅 등의 목적으로 요청 본문을 여러 번 읽을 수 있도록 ContentCachingRequestWrapper로 감싸는 경우.

    • 인증 정보 추가: 커스텀 헤더에 담긴 인증 정보를 파싱하여 HttpServletRequest에 속성으로 추가하는 경우.

  • Response를 바꾸는 경우

    • 공통 헤더 추가: 모든 응답에 CORS 관련 헤더나 보안 관련 헤더(X-XSS-Protection 등)를 추가하는 경우.

    • 응답 데이터 압축: 응답 본문을 Gzip으로 압축하여 전송량을 줄이는 경우.


## 3. 필터(Filter) vs 인터셉터(Interceptor) 핵심 차이

이것이 질문의 핵심입니다. 둘 다 요청을 가로채지만, 실행되는 위치와 권한이 다릅니다.

### 비유: 건물 출입 🏢

  • 필터 (Filter): 건물 정문에 있는 1차 보안요원.

    • 위치: 건물(웹 컨테이너)의 가장 바깥쪽.

    • 역할: 건물에 들어오는 모든 방문객(모든 요청)을 가장 먼저 확인. 인코딩, 보안 등 애플리케이션과 무관한 저수준의 처리를 담당.

    • 특징: 회사 내부 사정(스프링 컨테이너)은 모름. Service 같은 스프링 Bean을 주입받을 수 없음.

  • 인터셉터 (Interceptor): 특정 사무실(스프링 MVC) 입구의 2차 안내데스크 직원.

    • 위치: 정문을 통과한 후, 실제 사무실(컨트롤러)로 들어가기 직전.

    • 역할: 해당 사무실의 규칙에 따라 방문객의 출입을 제어. 로그인 여부, 관리자 권한 확인 등 비즈니스 로직과 관련된 처리를 담당.

    • 특징: 회사 내부 사정(스프링 컨테이너)을 잘 앎. @Service 등 필요한 Bean을 주입받아 복잡한 로직 수행 가능.

### 비교표

구분
필터 (Filter)
인터셉터 (Interceptor)

실행 시점

DispatcherServlet 전/후

DispatcherServlet 후, Controller 전/후

관리 주체

서블릿 컨테이너 (Tomcat)

스프링 컨테이너 (IoC)

접근 정보

ServletRequest, ServletResponse (원본 요청)

HttpServletRequest, HttpServletResponse, 컨트롤러 정보(HandlerMethod), ModelAndView

DI 가능 여부

원칙적으론 불가 (단, DelegatingFilterProxy로 우회)

가능 (@Autowired 등)

주요 사용처

인코딩, 보안 초기화(Spring Security), CORS, 로깅

로그인/권한 체크, 로깅(사용자 정보 포함), 공통 데이터 추가

### 실행 흐름도

Request[Filter][DispatcherServlet][Interceptor (preHandle)][Controller][Interceptor (postHandle)][View][Interceptor (afterCompletion)][DispatcherServlet][Filter]Response

관심사 분리라고 생각.

스프링 시큐리티 활용해서 로그인 구현해도 사실 인터셉터처럼 스프링 컨테이너의 빈들을 활용할 수 있기 때문에

스프링 시큐리티는 필터의 강력한 요청 가로채기 능력과 인터셉터의 유연한 스프링 Bean 활용 능력이라는 두 가지 장점을 모두 취한 매우 영리한 설계를 가지고 있습니다. 따라서 로그인이나 인가 처리를 할 때 DB 접근, 다른 서비스 로직 호출 등 정교한 작업이 모두 가능한 것입니다.

Last updated