안녕하세요, 이번에 알아볼 주제는 Spring의 Filter입니다.
Spring에서는 WEB 요청을 위한 다양한 필터가 존재하는데요,
이번 시간에는 Spring에서 기본적으로 제공 해 주는 필터 종류와 필터들이 어떻게 호출 되는지, 그리고 필터의 올바른 사용에 대해서 알아보려 합니다.
Spring의 필터란?
Filter는 Java Servlet API에서 제공하는 기능으로, HTTP 요청/응답에 대한 사전 및 사후 처리를 수행할 수 있는 기능을 제공합니다. 이는 Java 웹 애플리케이션에서 가장 기본적인 필터링 메커니즘입니다.
필터는 다양하게 사용되는데요, 주로 인증 및 권한 검사, 로깅 및 모니터링, 요청/응답 데이터 변환, CORS 설정 등으로 다양하게 사용되고 있습니다.
Spring Filter는 Spring Framework에서 javax.servlet.Filter를 확장하여 제공하는 기능으로, Spring 애플리케이션의 요구사항에 맞춰진 필터 구현체를 제공합니다.
Spring에서 제공 해 주는 필터 종류
Spring에서는 다양한 필터를 제공해주는데요, 현재 Spring에서 제공 해 주는 필터는 다음과 같이 OncePerRequestFilter를 구현한 14 개의 필터가 존재하는 것을 볼 수 있습니다.
각 필터의 역할
HiddenHttpMethodFilter
- 역할: HTTP 요청에서 X-HTTP-Method-Override 헤더를 확인하여 숨겨진 HTTP 메서드(PUT, DELETE 등)를 사용할 수 있도록 지원합니다.
- 주로 HTML 폼에서 POST 요청을 통해 다른 HTTP 메서드를 에뮬레이션할 때 사용됩니다
CharacterEncodingFilter
- 역할: 요청 및 응답의 문자 인코딩 설정을 관리합니다.
- 예를 들어, UTF-8 인코딩을 강제하여 다국어 데이터 처리를 보장합니다
ServerHttpObservationFilter
- 역할: HTTP 요청 및 응답을 관찰(observation)하여 메트릭스 및 로깅에 활용됩니다.
- 주로 모니터링과 관련된 추가 데이터를 캡처하기 위해 사용됩니다
CorsFilter
- 역할: Cross-Origin Resource Sharing (CORS) 규칙을 처리합니다.
- 특정 도메인에서 오는 HTTP 요청을 허용하거나 거부하는 작업을 수행합니다
RequestContextFilter
- 역할: 현재 요청에 대한 컨텍스트 정보를 설정합니다.
- Spring의 RequestContextHolder를 통해 요청 스코프에서 데이터를 공유할 수 있도록 지원합니다
FormContentFilter
- 역할: HTTP PUT, PATCH 요청의 application/x-www-form-urlencoded 데이터를 파싱하여 사용할 수 있도록 처리합니다.
- 주로 폼 데이터를 처리할 때 사용됩니다
ShallowEtagHeaderFilter
- 역할: ETag를 기반으로 요청에 대한 응답을 캐싱하고 변경되지 않은 리소스에 대해 304 (Not Modified) 상태 코드를 반환합니다.
- 네트워크 대역폭을 줄이고 응답 속도를 높이는 데 기여합니다
ForwardedHeaderFilter
- 역할: 요청에 있는 X-Forwarded-* 헤더를 분석하여 클라이언트의 원본 IP 및 프로토콜 정보를 설정합니다.
- 프록시 서버나 로드 밸런서를 사용하는 경우 정확한 클라이언트 정보를 파악할 때 유용합니다.
RelativeRedirectFilter
- 역할: 상대적 리다이렉션 URL을 처리합니다.
- 응답 헤더의 Location 값을 절대 URL로 변환하여 클라이언트가 올바른 리다이렉션을 따르도록 보장합니다.
AbstractRequestLoggingFilter
- 역할: 요청 로그를 캡처하여 디버깅 및 추적에 활용합니다.
- 이를 확장한 필터들은 추가적인 로깅 기능을 구현할 수 있습니다
CommonsRequestLoggingFilter
- 역할: AbstractRequestLoggingFilter를 상속하여 HTTP 요청의 시작 및 끝에서 상세한 요청 데이터를 로깅합니다.
- 요청 URI, 헤더, 페이로드 등 디버깅에 필요한 정보를 캡처합니다
ServletRequestPathFilter
- 역할: 요청 경로를 필터링하고 경로 정보를 설정합니다.
- URL 매핑이나 경로 기반 처리를 위한 필터링 로직에 사용됩니다
CompositeFilter
- 역할: 여러 개의 필터를 조합하여 하나의 필터처럼 동작하도록 합니다.
- 내부적으로 Filter 목록을 관리하며, 순차적으로 각 필터를 실행합니다.
- 주로 필터 체인을 구성하거나 동적으로 필터를 조합할 때 사용됩니다
ServletContextRequestLoggingFilter
- 역할: AbstractRequestLoggingFilter를 상속하여 요청 로그를 기록합니다.
- 요청 컨텍스트의 정보를 기반으로 보다 세부적인 요청 데이터를 로깅합니다
CommonsRequestLoggingFilter
- 역할: Spring에서 제공하는 요청 로깅 필터 중 하나로, HTTP 요청의 시작과 끝에서 데이터를 로깅합니다.
- HTTP 헤더, 페이로드, URI 등을 디버깅 및 모니터링 목적으로 기록합니다.
- AbstractRequestLoggingFilter를 상속받아 세부 구현을 제공합니다
OncePerRequestfileter VS Filter 차이점
Spring에서는 기본적인 Filter 클래스가 존재합니다.
그런데, Filter를 사용하다 보면 다음과 같이 Filter를 상속하는 경우가 있고, OncePerRequestFilter를 사용하는 경우가 있는데요,
이 둘의 차이점을 간략하게 살펴보면 아래와 같습니다.
항목 | Java Filter | Spring Filter |
---|---|---|
정의 | javax.servlet.Filter |
GenericFilterBean , OncePerRequestFilter 등 |
라이프사이클 | 서블릿 컨테이너에 의해 관리 | Spring 컨텍스트에 의해 관리 |
의존성 주입(DI) 지원 | 지원하지 않음 | Spring의 DI를 통해 지원 |
주요 사용 예 | 인증, 로깅, 응답 압축 | Spring Security, CORS, Character Encoding |
관리 방식 | web.xml 또는 @WebFilter 로 등록 |
Spring Boot에서는 @Bean 으로 등록 가능 |
왜 OncePerRequestFilter를 사용하는걸까?
그러면, 왜 Filter를 구현해서 사용하지 않고 OncePerRequestFilter를 사용하는걸까요?
OncePerRequestFilter는 Filter를 구현한 GenericFilterBean를 상속하는 클래스입니다.
GenericFilterBean은 Spring이 제공하는 필터의 기본 구현체로, 다음과 같은 이점을 제공해주고 있습니다.
- Spring Bean 지원: GenericFilterBean은 Spring의 의존성 주입 및 애플리케이션 컨텍스트와 통합이 쉽습니다.
- 초기화 메서드 제공: GenericFilterBean은 init() 및 destroy() 메서드를 오버라이드하여 필터 초기화와 종료 처리를 간단히 수행할 수 있습니다.
- 간소화된 구현: 기본적으로 Filter 인터페이스의 반복적인 코드를 줄이고, 핵심 로직(doFilter) 구현에만 집중할 수 있습니다.
OncePerRequestFilter는 모든 요청(Request)에 대해 한 번만 필터 작업을 수행하도록 설계되었습니다. 동일 요청에서 필터 체인이 여러 번 호출될 수 있는 상황을 방지하기 위해 사용됩니다.
예를 들어, DispatcherServlet이나 다른 필터 체인과의 중복 호출을 방지해주는 특징을 가지고 있습니다.
또한, 기본적으로 Filter 클래스는 위 표에서 확인했던 것처럼 Spring 컨텍스트에서 관리되는 것이 아닌, 서블릿 컨테이너에서 관리된다는 점도 주로 OncePerRequestFilter를 사용하는 이유가 될듯 하네요!
일반 Filter를 사용하여 커스터마이징 하는 케이스
그러면, OncePerRequestFilter를 상속하지 않고 커스터마이징 하는 케이스는 어떤 것들이 있을까요?
OncePerRequestFilter의 특징이 한 번만 필터 작업을 수행하도록 동작하는 것과는 다른 동작 의도를 가질 경우 혹은 Spring Context 외부에서 동작할 필요성이 있는 경우 사용된다고 합니다.
대표적인 케이스로는 아래와 같은 케이스가 있습니다.
DelegatingFilterProxy
- GenericFilterBean을 상속하지 않고 Filter를 직접 구현합니다.
- 이유: Spring Bean으로 위임하는 역할에 집중하며, Spring 컨텍스트 외부에서도 동작할 수 있도록 설계되었습니다.
Spring Security 필터
- 일부 Spring Security 필터는 OncePerRequestFilter나 GenericFilterBean을 상속하지 않고 Filter 인터페이스를 직접 구현합니다.
- 이유: 특정 보안 요구 사항에 따라 커스터마이징이 필요한 경우가 있기 때문입니다
정리
이번에는 Spring에서 제공하는 필터에 대해서 알게된 것들을 정리해 봤습니다. 이전에 사용하면서 경험하고 의문을 가졌던 Filter와 OncePerRequestFilter에 대해 각인시켜 주는 좋은 시간이었던 것 같네요 ㅎㅎ
'Spring Framework > spring' 카테고리의 다른 글
[SpringBoot] Spring Transaction에 대하여 (0) | 2025.01.06 |
---|---|
[SpringBoot] ApplicationEvent를 활용한 이벤트 발행/구독 (0) | 2024.12.28 |
[SpringBoot] @ComponentScan 동작 원리 (0) | 2024.12.09 |
[SpringBoot] SpringBoot는 어떻게 실행될까? (0) | 2024.12.08 |
MSA 환경에서 Kotlin + Spring Rest Docs + Swagger UI 적용 (0) | 2023.09.14 |