Spring
Filter vs Interceptor vs AOP — 요청을 가로채는 3가지 방법의 차이를 설명해주세요
Servlet Filter, HandlerInterceptor, Spring AOP의 실행 시점과 적용 범위, 실제 사용 사례를 인터랙티브 시각화로 완전 정복합니다.
2026년 3월 21일 · 약 12분 읽기
Q. "Servlet Filter, HandlerInterceptor, Spring AOP의 차이를 설명하고, 각각 어떤 상황에서 사용하는지 말씀해주세요."
예상 꼬리질문
답변 가이드
"Filter는 Servlet Container 레벨에서 동작하여 DispatcherServlet 진입 전에 요청을 처리합니다.HttpServletRequest/Response를 직접 래핑(wrapping)할 수 있어 인코딩 설정, CORS 헤더 추가 같은 저수준 HTTP 조작에 적합합니다. Spring Context 외부에서 동작하므로 필터에서 발생한 예외는 @ControllerAdvice로 처리할 수 없습니다."
"HandlerInterceptor는 DispatcherServlet 내부에서 동작하여컨트롤러 실행 전(preHandle), 실행 후(postHandle), 뷰 렌더링 완료 후(afterCompletion) 세 시점에 개입할 수 있습니다. Spring Bean에 접근 가능하고 HandlerMethod를 통해 컨트롤러 어노테이션을 읽을 수 있어@LoginRequired 같은 커스텀 어노테이션 기반 인증 처리에 적합합니다."
"Spring AOP는 프록시 기반으로 동작하며 컨트롤러를 포함한모든 Spring Bean의 메서드 호출에 적용할 수 있습니다. Pointcut 표현식으로 정밀하게 적용 대상을 지정할 수 있어 트랜잭션, 캐싱 같은서비스 레이어 횡단 관심사 처리에 가장 적합합니다. 단, 같은 클래스 내부 메서드 호출(Self-Invocation)에는 동작하지 않는 한계가 있습니다."
@Transactional 하나로 트랜잭션이 자동 관리되고, JWT 토큰은 컨트롤러에 도달하기도 전에 검증됩니다. Spring은 요청 처리 흐름의 여러 지점에서 공통 로직을 끼워 넣을 수 있는 세 가지 메커니즘을 제공합니다.
어디서, 어떻게 동작하는지를 이해하면 인증 처리 하나도 최적의 위치에 배치할 수 있게 됩니다. 인터랙티브 시각화로 직접 실행 흐름을 확인해 보겠습니다.
1. 세 메커니즘의 실행 흐름
꼬리질문: "Filter에서 발생한 예외가 @ControllerAdvice에서 처리되지 않는 이유는 무엇인가요?"
HTTP 요청은 Filter → DispatcherServlet → Interceptor → AOP → Controller 순서로 흐릅니다. 각 메커니즘은 이 흐름의 서로 다른 위치에서 요청을 가로채기 때문에, 접근 가능한 객체와 처리 범위가 달라집니다.
각 단계 카드를 클릭하거나 시뮬레이션을 실행해보세요.
HTTP 요청 처리 흐름
각 단계 카드를 클릭하거나 시뮬레이션을 실행해보세요.
Servlet Container 영역
Spring MVC 영역
2. 세 메커니즘 핵심 비교
꼬리질문: "Interceptor의 preHandle, postHandle, afterCompletion은 각각 어떤 시점에 호출되나요?"
세 메커니즘은 동작 범위, Spring Bean 접근 여부, 예외 처리 방식이 모두 다릅니다. 특히 적용 범위의 차이가 핵심입니다. Filter는 static 파일 요청까지 포함한 모든 요청을 처리하지만, Interceptor는 DispatcherServlet이 처리하는 요청만, AOP는 Spring Bean 메서드 호출만 대상으로 합니다.
열 헤더를 클릭하면 해당 메커니즘을 강조합니다. 셀을 클릭하면 상세 설명이 표시됩니다.
3가지 메커니즘 비교
열 헤더를 클릭하면 해당 메커니즘을 강조합니다. 각 셀을 클릭하면 상세 설명이 표시됩니다.
| 비교 항목 | Filter | Interceptor | AOP |
|---|---|---|---|
| 실행 위치 | Servlet Container | Spring MVC | Spring Proxy |
| 동작 범위 | 모든 요청 (static 포함) | DS 처리 요청만 | Spring Bean 메서드 |
| Spring Bean 접근 | 제한적 | 가능 | 가능 |
| @ControllerAdvice 예외 | 미적용 | 적용 | 적용 |
| 요청/응답 래핑 | 가능 | 불가 | 불가 |
| 적용 기준 | URL 패턴 | URL + 어노테이션 | 포인트컷(Pointcut) 표현식 |
| 대표 사용 사례 | 인코딩, CORS, XSS | 인증, 로그인 체크 | 트랜잭션, 캐싱 |
3. 사용 사례 — 무엇을 어디에 구현할까
꼬리질문: "JWT 인증 처리를 Filter와 Interceptor 중 어디에 구현하는 것이 더 적합한가요?"
"JWT 인증은 어디에 구현해야 하나요?"는 실무에서 자주 논의되는 주제입니다.Spring Security는 Filter 체인에서 JWT를 처리하고, 커스텀 인증 어노테이션은 Interceptor에서 처리하는 방식이 일반적입니다.
기능을 선택하면 어느 메커니즘에 구현하는 것이 적합한지 확인할 수 있습니다.
사용 사례별 구현 위치
기능을 선택하면 어느 메커니즘에 구현하는 것이 적합한지 확인할 수 있습니다.
Preflight(OPTIONS) 요청도 처리 필요. Filter가 DispatcherServlet 이전에 위치하여 모든 요청을 커버합니다.
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req,
ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
chain.doFilter(req, response);
}
}4. Self-Invocation — AOP의 가장 흔한 함정
꼬리질문: "Spring AOP의 Self-Invocation 문제란 무엇이고, 어떻게 해결하나요?"
Spring AOP의 가장 큰 함정은 같은 클래스 내부 메서드 호출에 AOP가 동작하지 않는다는 것입니다. 외부에서 호출할 때는 프록시를 거치지만, this.method() 형태의 내부 호출은 프록시를 우회합니다.
시뮬레이션을 실행하면 프록시 통과 여부를 시각적으로 확인할 수 있습니다.
Self-Invocation 시뮬레이션
같은 클래스 내부 메서드 호출에서 AOP가 동작하지 않는 이유를 시각화합니다.
@Service
public class OrderService {
@Transactional
public void createOrder(Order order) {
orderRepository.save(order);
// ❌ this 호출 = 프록시 우회
this.sendEmail(order);
}
// REQUIRES_NEW이지만 적용 안 됨!
@Transactional(propagation = REQUIRES_NEW)
public void sendEmail(Order order) {
notificationRepository.save(
new Notification(order));
}
}자주 발생하는 문제
퀴즈로 확인하기
개념을 제대로 이해했는지 확인해 보세요.
다음 코드에서 JwtFilter 안에서 TokenExpiredException이 발생했을 때,
GlobalExceptionHandler의 @ExceptionHandler가 이 예외를 처리할 수 있을까요?
@Component
public class JwtFilter extends OncePerRequestFilter {
protected void doFilterInternal(...) {
jwtService.validate(token); // 여기서 예외 발생
filterChain.doFilter(request, response);
}
}
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(TokenExpiredException.class)
public ResponseEntity<String> handle(TokenExpiredException e) {
return ResponseEntity.status(401).body("토큰 만료");
}
}면접 체크리스트
이 항목들을 자신 있게 설명할 수 있다면 준비 완료입니다.
- - 실행 순서: Filter → Interceptor(preHandle) → AOP → Controller → AOP → Interceptor(postHandle/afterCompletion) → Filter
- - Filter: Servlet Container, HTTP 수준 조작, @ControllerAdvice 예외 미적용
- - Interceptor: Spring MVC, HandlerMethod 어노테이션 접근, 예외 발생 시 postHandle 미호출
- - AOP: 프록시 기반, 모든 Spring Bean 메서드, Self-Invocation 주의
- - Self-Invocation 해결: 내부 호출 메서드를 별도 빈으로 분리
참고 자료
- 인파의 블로그 — Filter vs Interceptor vs AOP 완벽 정리 — 그림과 함께 세 메커니즘의 차이를 쉽게 설명한 한국어 블로그
- 망나니 개발자 블로그 — 필터(Filter)와 인터셉터(Interceptor)의 차이 — 코드 예제와 함께 실무 사용 차이를 명확히 설명
- Baeldung — Spring MVC HandlerInterceptor — HandlerInterceptor의 세 메서드를 예제 코드로 설명
- Baeldung — Intro to Spring AOP — Spring AOP 핵심 개념을 단계별로 설명하는 입문 튜토리얼
의견을 들려주세요
서비스 개선에 큰 도움이 됩니다. 익명으로 자유롭게 남겨주세요.