184 lines
7.9 KiB
Markdown
184 lines
7.9 KiB
Markdown
# **Spring Boot 요청 처리 고급 기능: 필터, 인터셉터, AOP 활용**
|
|
|
|
Spring Boot에서 클라이언트의 **요청을 처리하는 과정**은 단순히 컨트롤러에서 요청을 받고 응답을 반환하는 것 이상으로 확장될 수 있습니다.
|
|
특히 **보안, 로깅, 성능 모니터링, 인증/인가**와 같은 공통 기능을 처리하려면 **필터(Filter), 인터셉터(Interceptor), AOP(Aspect-Oriented Programming)** 등의 개념을 활용할 필요가 있습니다.
|
|
|
|
이번 글에서는 **필터, 인터셉터, AOP**를 활용하여 **요청을 가로채고, 원하는 로직을 추가하는 방법**을 실무 예제와 함께 설명하겠습니다.
|
|
|
|
---
|
|
|
|
# **1. 필터(Filter) - 요청 전/후 공통 처리**
|
|
|
|
### **📌 필터란?**
|
|
필터는 **서블릿 수준에서 동작하며, 요청이 컨트롤러에 도달하기 전/후에 특정 로직을 실행**할 수 있는 기능입니다.
|
|
Spring Boot에서는 `javax.servlet.Filter` 인터페이스를 구현하여 커스텀 필터를 만들 수 있습니다.
|
|
|
|
### **📌 필터의 주요 활용 사례**
|
|
- **CORS 처리**
|
|
- **요청 및 응답 로깅**
|
|
- **JWT 인증 처리**
|
|
- **IP 차단 등 보안 정책 적용**
|
|
|
|
### **📌 필터 구현 예제 - 요청 로깅**
|
|
아래는 **모든 요청의 URL과 실행 시간을 기록하는 필터**입니다.
|
|
|
|
```java
|
|
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에 접근할 때, 인증된 사용자만 허용하는 인터셉터**입니다.
|
|
|
|
```java
|
|
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**에 등록해야 합니다.
|
|
|
|
```java
|
|
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**입니다.
|
|
|
|
```java
|
|
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 애플리케이션을 더욱 강력하고 유지보수하기 쉽게 만들 수 있습니다!** |