7.9 KiB
Spring Boot 요청 처리 고급 기능: 필터, 인터셉터, AOP 활용
Spring Boot에서 클라이언트의 요청을 처리하는 과정은 단순히 컨트롤러에서 요청을 받고 응답을 반환하는 것 이상으로 확장될 수 있습니다.
특히 보안, 로깅, 성능 모니터링, 인증/인가와 같은 공통 기능을 처리하려면 필터(Filter), 인터셉터(Interceptor), AOP(Aspect-Oriented Programming) 등의 개념을 활용할 필요가 있습니다.
이번 글에서는 필터, 인터셉터, AOP를 활용하여 요청을 가로채고, 원하는 로직을 추가하는 방법을 실무 예제와 함께 설명하겠습니다.
1. 필터(Filter) - 요청 전/후 공통 처리
📌 필터란?
필터는 서블릿 수준에서 동작하며, 요청이 컨트롤러에 도달하기 전/후에 특정 로직을 실행할 수 있는 기능입니다.
Spring Boot에서는 javax.servlet.Filter 인터페이스를 구현하여 커스텀 필터를 만들 수 있습니다.
📌 필터의 주요 활용 사례
- CORS 처리
- 요청 및 응답 로깅
- JWT 인증 처리
- IP 차단 등 보안 정책 적용
📌 필터 구현 예제 - 요청 로깅
아래는 모든 요청의 URL과 실행 시간을 기록하는 필터입니다.
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component // 자동으로 필터 등록
public class LoggingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
long startTime = System.currentTimeMillis();
System.out.println("[LoggingFilter] 요청 URI: " + req.getRequestURI());
chain.doFilter(request, response); // 요청을 다음 필터 또는 컨트롤러로 전달
long duration = System.currentTimeMillis() - startTime;
System.out.println("[LoggingFilter] 요청 처리 시간: " + duration + "ms");
}
}
✔ doFilter() 메서드는 요청을 가로채서 원하는 작업을 수행한 후, 체인(chain)으로 넘겨줌
✔ 요청 전후로 실행할 로직을 자유롭게 추가 가능
2. 인터셉터(Interceptor) - 요청 흐름을 제어
📌 인터셉터란?
인터셉터는 Spring MVC에서 동작하며, 컨트롤러 실행 전후에 특정 로직을 추가할 수 있는 기능입니다.
필터보다 더 세부적인 요청 흐름을 제어할 수 있으며, 특정 컨트롤러 또는 요청 경로에만 적용 가능합니다.
📌 인터셉터의 주요 활용 사례
- 사용자 인증 및 권한 체크
- API 요청 제한 (Rate Limiting)
- 로그 및 성능 모니터링
- 특정 요청의 파라미터 검사
📌 인터셉터 구현 예제 - 인증 체크
아래는 특정 API에 접근할 때, 인증된 사용자만 허용하는 인터셉터입니다.
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.stereotype.Component;
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("Unauthorized");
return false; // 요청을 차단
}
// JWT 검증 로직 추가 가능 (예: Token 검증)
System.out.println("[AuthInterceptor] 인증 성공");
return true; // 요청 진행 허용
}
}
✔ preHandle() 메서드는 컨트롤러 실행 전에 요청을 가로채서 검사 가능
✔ 인증이 실패하면 false를 반환하여 요청을 차단할 수 있음
📌 인터셉터 등록 (WebMvcConfigurer)
인터셉터를 사용하려면 WebMvcConfigurer에 등록해야 합니다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**") // 특정 URL에만 적용
.excludePathPatterns("/api/public/**"); // 예외 URL 설정
}
}
3. AOP (Aspect-Oriented Programming) - 횡단 관심사 처리
📌 AOP란?
AOP는 비즈니스 로직과는 별개로 공통 기능(로깅, 트랜잭션, 보안 등)을 적용하는 프로그래밍 기법입니다.
Spring Boot에서는 @Aspect와 @Around를 활용하여 메서드 실행 전후에 특정 로직을 추가할 수 있습니다.
📌 AOP의 주요 활용 사례
- 로깅(Log Tracing)
- 트랜잭션 관리
- 메서드 실행 시간 측정
- 입출력 값 검증
📌 AOP 구현 예제 - 로깅 및 실행 시간 측정
아래는 모든 서비스 메서드의 실행 시간을 로깅하는 AOP입니다.
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))") // 모든 서비스 메서드에 적용
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed(); // 실제 메서드 실행
long duration = System.currentTimeMillis() - start;
System.out.println("[AOP] " + joinPoint.getSignature() + " 실행 시간: " + duration + "ms");
return result;
}
}
✔ @Aspect 선언으로 AOP 활성화
✔ @Around("execution(* com.example.service.*.*(..))")로 특정 패키지의 모든 메서드에 적용 가능
✔ joinPoint.proceed()를 호출하여 실제 메서드를 실행하고, 이후 로직을 추가할 수 있음
4. 필터, 인터셉터, AOP 비교
| 기능 | 동작 위치 | 주요 목적 | 적용 대상 | 실행 시점 |
|---|---|---|---|---|
| Filter | 서블릿 레벨 | 요청 전처리 및 후처리 (보안, 로깅) | 모든 요청 | 컨트롤러 실행 전후 |
| Interceptor | Spring MVC 레벨 | 인증, 권한 체크 | 특정 요청 (API) | 컨트롤러 실행 전후 |
| AOP | 메서드 레벨 | 로깅, 트랜잭션, 성능 측정 | 특정 패키지/클래스의 메서드 | 메서드 실행 전후 |
5. 정리
✔ 필터(Filter): 모든 요청에 대해 전역적인 로직 적용 (보안, CORS, 로깅)
✔ 인터셉터(Interceptor): 컨트롤러 실행 전후에 특정 요청을 가로채서 인증/인가 처리
✔ AOP(Aspect-Oriented Programming): 특정 메서드(비즈니스 로직)의 실행 전후에 로직 추가 (로깅, 성능 측정 등)
이러한 고급 기능을 활용하면 Spring Boot 애플리케이션을 더욱 강력하고 유지보수하기 쉽게 만들 수 있습니다!