스프링 부트 3에서 WebFilter를 구현하는 방법과 활용 사례
스프링 부트(Spring Boot)는 효율적이고 직관적인 웹 애플리케이션 개발을 지원하는 프레임워크로, WebFilter는 HTTP 요청 및 응답을 가로채고 처리하는 데 사용됩니다. 스프링 부트 3에서 WebFilter를 구현하면 요청 로깅, 인증 및 인가, 공통 응답 처리와 같은 다양한 기능을 쉽게 개발할 수 있습니다. 이번 글에서는 WebFilter의 기본 구현 방법과 실무에서 활용 가능한 예제를 3가지로 나누어 살펴보겠습니다.
1. WebFilter란 무엇인가?
WebFilter는 서블릿 필터(Servlet Filter)와 유사한 기능을 제공하는 인터페이스입니다. 하지만 Reactor 기반인 스프링 웹플럭스(WebFlux)와 함께 사용되며, 비동기 및 논블로킹 방식으로 요청과 응답을 처리할 수 있습니다.
스프링 부트 3는 WebFlux의 기능이 더욱 강화되었으며, WebFilter를 이용한 비동기 처리에서 성능 이점을 누릴 수 있습니다. WebFilter는 주로 다음과 같은 작업에 사용됩니다:
- 요청 및 응답 로깅
- 공통 헤더 추가
- 인증 및 권한 관리
- 오류 응답 처리
2. WebFilter 구현 기본 구조
WebFilter를 구현하려면 org.springframework.web.server.WebFilter 인터페이스를 구현해야 합니다. 아래는 기본적인 WebFilter 구현 예제입니다:
import org.springframework.stereotype.Component;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class LoggingFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
// 요청 URI 로깅
System.out.println("Request URI: " + exchange.getRequest().getURI());
// 필터 체인 실행
return chain.filter(exchange).doOnSuccess(unused -> {
// 응답 로깅
System.out.println("Response Status Code: " + exchange.getResponse().getStatusCode());
});
}
}
주요 구성 요소:
- ServerWebExchange: HTTP 요청 및 응답을 캡슐화한 객체로, 요청 헤더, 본문, 응답을 다룰 수 있습니다.
- WebFilterChain: 다음 필터를 실행하거나 실제 핸들러로 요청을 전달합니다.
- Mono: WebFilter는 비동기 작업을 Mono로 반환합니다.
3. 실무에서의 WebFilter 활용 사례
(1) 요청 로깅 필터
모든 HTTP 요청과 응답을 로깅하여 디버깅 및 모니터링에 활용할 수 있습니다.
@Component
public class RequestLoggingFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
String method = exchange.getRequest().getMethodValue();
String uri = exchange.getRequest().getURI().toString();
System.out.println("Request: Method = " + method + ", URI = " + uri);
return chain.filter(exchange).doOnSuccess(unused -> {
System.out.println("Response Status: " + exchange.getResponse().getStatusCode());
});
}
}
적용 사례:
- 모든 요청 및 응답 로그를 기록하여 트래픽 분석 및 디버깅에 활용합니다.
- 특정 조건에 따라 중요 요청만 로깅하도록 개선 가능합니다.
(2) 인증 및 권한 검사 필터
사용자의 인증 상태와 권한을 검사하여 적합하지 않은 요청을 차단합니다.
@Component
public class AuthFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 토큰 유효성 검사 (예: JWT)
String token = authHeader.substring(7);
if (!isValidToken(token)) {
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
private boolean isValidToken(String token) {
// 토큰 검증 로직
return "validToken123".equals(token); // 예제 토큰
}
}
적용 사례:
- JWT를 사용한 인증 처리.
- 역할(Role) 기반의 접근 제어 구현.
(3) 공통 응답 헤더 추가 필터
모든 응답에 공통 헤더를 추가하여 보안 및 브라우저 정책을 설정합니다.
@Component
public class ResponseHeaderFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange).doOnSuccess(unused -> {
exchange.getResponse().getHeaders().add("X-Custom-Header", "CustomValue");
exchange.getResponse().getHeaders().add("Cache-Control", "no-cache, no-store, must-revalidate");
});
}
}
적용 사례:
- 보안 헤더 추가(CORS 정책, CSP 설정 등).
- 캐싱 방지 헤더 추가로 최신 데이터를 보장.
4. WebFilter 등록 및 테스트
WebFilter는 기본적으로 @Component로 등록하면 자동으로 동작합니다. 하지만 특정 조건에서만 활성화하려면 @ConditionalOn... 등의 어노테이션과 결합하거나, 직접 FilterRegistrationBean으로 등록할 수도 있습니다.
테스트 방법:
- Postman이나 cURL을 사용하여 HTTP 요청을 보냅니다.
- 애플리케이션 로그와 응답 헤더를 확인합니다.
5. 결론
스프링 부트 3의 WebFilter는 비동기 처리 환경에서 요청과 응답을 효과적으로 제어할 수 있는 강력한 도구입니다. 요청 로깅, 인증 처리, 공통 헤더 추가 등 다양한 기능을 구현할 수 있으며, 필요에 따라 체인 구조를 활용해 다층적인 필터링도 가능합니다.
위에서 소개한 예제를 참고하여 프로젝트에 적합한 WebFilter를 구현해 보세요! WebFilter를 적절히 활용하면 더 안전하고 효율적인 웹 애플리케이션을 개발할 수 있습니다. 🚀
'스프링 부트3' 카테고리의 다른 글
스프링 부트 3에서 메일 발송 구현 (0) | 2024.12.06 |
---|---|
CSRF 보호와 스프링 부트 3: 웹 애플리케이션 보안의 필수 요소 (0) | 2024.12.06 |
스프링 부트 3에서 RestTemplate 대체하기 (0) | 2024.12.06 |
스프링 부트 3와 NoSQL 데이터베이스 (0) | 2024.12.06 |
스프링 부트 3에서 JMS 활용 (0) | 2024.12.06 |