오늘은 handler interceptor 에 대한 이야기를 조금 해보고자 한다.

Filter 는 자바 servlet 에서 제공하는 기술이지만 interceptor는 spring에서 제공하는 기술로써

세션 인증과 관련된 부분을 공부하다가 적어본다.

 

▶ 그래서 interceptor 가 뭔가요?

spring MVC 에서 인터셉터란 결국

지정된 URI에 관한 호출을 가로채는 역할을 하는 기능입니다.

이러한 호출을 가로채서 뭐하냐 싶지만

우리는 로그인을 한다거나 어떠한 게시물에 조회수를 올린다거나 하는 작업을 할 때 와 같은

공통된 관심사를 컨트롤 하기 위해서 사용하는 것 이다.

 

이는 이전 게시글인 Filter 와 같은데 두개의 차이점은 확실히 존재한다.

  Filter 와 Interceptor의 차이점

Filter와 Interceptor는 그 기능이 매우 흡사하여 나와같은 초보들이 가장 많이 헷갈려하는게

두 기능은 확연한 차이가 존재한다.

 

spring MVC request LifeCycle

위 사진을 보면 해당 차이를 조금 더 확실하게 알 수 있는데

Filter는 요청을 보내면 Tomcat과 같은 WAS 서버에 들어오자마자 작동되는 것으로

Spring의 영역에 접근하여 사용하기가 어렵습니다.

 

반면에 interceptor는 Spring 내에서 관리되는 기능이기에 Spring의 영역 내에서 사용되고 있는 것을 볼 수 있습니다.

 

이것으로 인해서 알 수 있는 차이는 생성된 Bean에 접근이 용이한가로 볼 수 있습니다.

 

◆ 차이점 정리

▶ Interceptor와 Filter는 호출 시점의 차이

  • Filter는 Dispatcher Servlet 호출 전(WAS의 단계)
  • Interceptor은 Dispatcher Servlet 호출 후 실행 됨

 

▶ Interceptor 의 용도

  • 인증 인가 등과 같은 공통 작업
  • Controller로 넘어가는 정보의 가공
  • API 호출에 대한 로깅 또는 감사

▶ Filter의 용도

  • 보안 관련 공통 작업
  • 모든 요청에 대한 로깅 
  • 이미지, 데이터 압축 및 문자열 인코딩

이제 이어지는 사용법을 알아보자

 

Handler Interceptor는 Interface 이므로 class 에 implements 하여 사용하면 된다.

public interface HandlerInterceptor {
    // controller 호출 전에 실행 (핸들러 어댑터 실행 전)
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

	// controller 호출 후에 실행 (핸들러 어댑터 호출 후)
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

	// view의 랜더링 이후 실행
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

위 코드가 HandlerInterceptor의 기본 모습이며 사용처는 내부에 적어두었다.

 

이를 사용하여 만든 간단한 예문을 적고 마무리 이 글을 마무리 하고자 한다.

 

▶ 예문

LOG 를 찍어 흐름 확인하기

@Slf4j
public class LogInterceptor implements HandlerInterceptor {

    public static final String LOG_ID = "logId";

    @Override // controller 호출 전에 실행 (핸들러 어댑터 실행 전)
    public boolean preHandle(HttpServletRequest request,
    			HttpServletResponse response,
                Object handler) throws Exception {

        String reqURI = request.getRequestURI();

        String uuid = UUID.randomUUID().toString();
        request.setAttribute(LOG_ID, uuid);


        //@RequestMapping : HandlerMethod
        // 정적 리소스 : ResourceHttpRequestHandler
        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler;
            // 호출할 컨트롤러의 메서드의 모든 정보
        }

        log.info("REQ [{}][{}][{}]",uuid, reqURI,handler);


        return true;
    }

    @Override // controller 호출 후에 실행 (핸들러 어댑터 호출 후)
    public void postHandle(HttpServletRequest request, 
    			HttpServletResponse response, 
                Object handler,
                ModelAndView modelAndView) throws Exception {
                
        log.info("postHandle [{}]", modelAndView);
        
    }

    @Override // view의 랜더링 이후 실행
    public void afterCompletion(HttpServletRequest request,
                HttpServletResponse response, 
                Object handler, 
                Exception ex) throws Exception {
                
        String reqURI = request.getRequestURI();
        String logId = (String) request.getAttribute(LOG_ID);
        log.info("RES [{}][{}]", logId, reqURI);
        if (ex != null) {
            log.error("afterCompletion error!", ex);
        }
        
    }
}

 

※ Interceptor를 정의한 클레스

 

@Configuration
public class WebConfig implements WebMvcConfigurer {
	
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // logInterceptor register
        registry.addInterceptor(new LogInterceptor()) // 인터셉터 등록
                .order(1) // 인터셉터의호출 순서를 지정, 낮을수록 먼저 호출
                .addPathPatterns("/**") // 인터셉터를 적용할 URL패턴 지정
                .excludePathPatterns("/css/**", "/*.ico", "/error"); //인터셉터에서 제외할 패턴 지정


}

 

※ Interceptor 등록

 

 

 

♣ 참고 및 강의

인터페이스 차이점과 정의 관련 참고 블로그

 

https://inf.run/GMo43 - 김영한의 스프링MVC2 

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 강의 - 인프런

웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있

www.inflearn.com

 

'Web > spring' 카테고리의 다른 글

servlet filter  (0) 2024.01.19

+ Recent posts