[Spring] Interceptor

배창민·2025년 10월 20일
post-thumbnail

Spring MVC Interceptor

스프링 인터셉터는 컨트롤러 앞뒤의 공통 로직을 끼워 넣는 장치다. URL 패턴별로 적용할 수 있고, 스프링 빈 주입이 가능해 필터보다 애플리케이션 레벨의 협업이 쉽다.


1) Interceptor 한눈에 보기

  • 역할: 요청을 가로채 전처리, 후처리, 완료 콜백 수행

  • 장점

    • URL 패턴 매핑 가능
    • 스프링 컨텍스트 접근(DI 가능)
    • 컨트롤러 단의 공통 concern(인증, 로깅, 성능 측정 등)에 적합
  • 콜백

    • preHandle(req, res, handler): 컨트롤러 실행 전
    • postHandle(req, res, handler, mv): 컨트롤러 성공 후(예외 없을 때), 뷰 렌더 전
    • afterCompletion(req, res, handler, ex): 뷰 렌더 후(항상)

2) 수행 시간 측정 Interceptor 예시

2-1. 인터셉터 구현

@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("메소드 호출 확인"); }
}

2-2. 컨트롤러 & 뷰

@GetMapping("stopwatch")
public String handlerMethod() throws InterruptedException {
    Thread.sleep(1000); // 샘플 지연
    return "result";
}
<!-- templates/result.html -->
<h1 th:text="|메소드 호출 수행 시간 : ${interval} (ms)|"></h1>

2-3. 등록(WebMvcConfigurer)

@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");

3) 실전 팁

  • 순서 제어: addInterceptors 등록 순서 = 실행 순서
  • 예외 시나리오: 예외가 발생하면 postHandle은 생략되고 afterCompletion은 항상 호출
  • ModelAndView null 체크: @ResponseBody 등에서는 mv가 없을 수 있음
  • 상태 공유 범위: 요청 단위 값은 request.setAttribute 사용
  • 차단 로직: 인증 불가 등은 preHandle에서 false 반환 후 리다이렉트/에러 처리

4) Filter vs Interceptor vs AOP

구분FilterInterceptorAOP
적용 대상모든 서블릿 요청/응답(컨테이너 레벨)스프링 MVC 핸들러(컨트롤러 전후)스프링 빈 메소드 실행 전반
동작 시점DispatcherServlet 이전/이후DispatcherServlet 내부(pre/post/after)메소드 전/후/예외(프록시)
구성javax.servlet.FilterHandlerInterceptor@Aspect
DI제한적(스프링과 분리 가능)가능가능
주용도보안 헤더, 인코딩, 전역 로깅인증/인가, 로깅, 성능 측정트랜잭션, 로깅, 예외 처리, 리트라이

핵심 요약

  • 컨트롤러 공통 로직은 인터셉터로, 전역 HTTP 레벨은 필터로, 서비스 계층 횡단 관심사는 AOP로.
  • 인터셉터는 pre/post/after 3단계 훅으로 성능 측정·인증 체크에 적합.
  • 등록은 WebMvcConfigurer#addInterceptors, 패턴/제외 경로로 정밀 적용.
  • 예외 발생 시에도 afterCompletion은 호출되어 정리 로직을 보장.
profile
개발자 희망자

0개의 댓글