
스프링 인터셉터는 컨트롤러 앞뒤의 공통 로직을 끼워 넣는 장치다. URL 패턴별로 적용할 수 있고, 스프링 빈 주입이 가능해 필터보다 애플리케이션 레벨의 협업이 쉽다.
역할: 요청을 가로채 전처리, 후처리, 완료 콜백 수행
장점
콜백
preHandle(req, res, handler): 컨트롤러 실행 전postHandle(req, res, handler, mv): 컨트롤러 성공 후(예외 없을 때), 뷰 렌더 전afterCompletion(req, res, handler, ex): 뷰 렌더 후(항상)@Component
public class StopWatchInterceptor implements HandlerInterceptor {
private final MenuService menuService; // DI 가능
public StopWatchInterceptor(MenuService menuService) {
this.menuService = menuService;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
request.setAttribute("startTime", System.currentTimeMillis());
return true; // false면 컨트롤러로 진행되지 않음
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, @Nullable ModelAndView mv) {
Long start = (Long) request.getAttribute("startTime");
if (start != null && mv != null) {
mv.addObject("interval", System.currentTimeMillis() - start);
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, @Nullable Exception ex) {
menuService.method(); // 리소스 정리/추가 로깅 등
}
}
@Service
public class MenuService {
public void method() { System.out.println("메소드 호출 확인"); }
}
@GetMapping("stopwatch")
public String handlerMethod() throws InterruptedException {
Thread.sleep(1000); // 샘플 지연
return "result";
}
<!-- templates/result.html -->
<h1 th:text="|메소드 호출 수행 시간 : ${interval} (ms)|"></h1>
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
private final StopWatchInterceptor stopWatchInterceptor;
public WebConfiguration(StopWatchInterceptor stopWatchInterceptor) {
this.stopWatchInterceptor = stopWatchInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(stopWatchInterceptor)
.addPathPatterns("/stopwatch");
}
}
registry.addInterceptor(stopWatchInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/css/**", "/js/**", "/images/**", "/error");
addInterceptors 등록 순서 = 실행 순서postHandle은 생략되고 afterCompletion은 항상 호출ModelAndView null 체크: @ResponseBody 등에서는 mv가 없을 수 있음request.setAttribute 사용preHandle에서 false 반환 후 리다이렉트/에러 처리| 구분 | Filter | Interceptor | AOP |
|---|---|---|---|
| 적용 대상 | 모든 서블릿 요청/응답(컨테이너 레벨) | 스프링 MVC 핸들러(컨트롤러 전후) | 스프링 빈 메소드 실행 전반 |
| 동작 시점 | DispatcherServlet 이전/이후 | DispatcherServlet 내부(pre/post/after) | 메소드 전/후/예외(프록시) |
| 구성 | javax.servlet.Filter | HandlerInterceptor | @Aspect |
| DI | 제한적(스프링과 분리 가능) | 가능 | 가능 |
| 주용도 | 보안 헤더, 인코딩, 전역 로깅 | 인증/인가, 로깅, 성능 측정 | 트랜잭션, 로깅, 예외 처리, 리트라이 |
WebMvcConfigurer#addInterceptors, 패턴/제외 경로로 정밀 적용.