인터셉터란?

 

Interceptor(인터셉터)는 컨트롤러로 가는 요청과 응답을 가로채서 원하는 기능을 추가하는 역할을 한다. 

주로 여러 컨트롤러에서 공통적으로 사용되는 기능을 정의하여 사용한다.

 

예를 들어, 컨트롤러에 있는 대부분의 메서드에서 일일이 사용자의 로그인 여부를 체크하는 코드를 넣는 대신에

인터셉터에 로그인 체크 로직을 추가한다면 보다 효율적으로 로그인 코드를 관리하고 활용할 수 있다.

 

인터셉터는 Servlet의 앞, 뒤에서 HttpRequest, HttpResponse을 가로채는 Filter와 그 역할이 유사한데,

Filter와 Interceptor의 차이점에 대해 살펴본다.

 

 

 

Filter와 Interceptor의 차이

 

1. 호출 시점

Filter는 DispatcherServlet이 실행되기 전 , Interceptor는 DispatcherServlet이 실행된 후에 호출된다.

 

Filter는 DispatcherServlet 처리 전 · 후에 동작하여 사용자의 요청이나 응답의 최전방에 존재한다.

필터는 스프링의 독자적인 기능이 아닌 자바 서블릿에서 제공한다.

 

2. 설정 위치

Filter는 web.xml에서 설정을 하지만,

Interceptor는 spring-servlet.xml에서 설정하거나 WebMvcConfigurer의 addInterceptors 메서드를 재정의해서

InterceptorRegistry에 인터셉터와 인터셉터가 동작하기 위한 경로를 설정한다.

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Bean
    public PerformanceInterceptor requestHandler() {
        return new PerformanceInterceptor();
    }

    @Override
    public void addInterceptors(final InterceptorRegistry registry) {
        registry.addInterceptor(requestHandler())
            .addPathPatterns("/**")
            .excludePathPatterns("/**/*.css", "/**/*.js");
    }
}

(.css나 .js가 아닌 모든 요청에 대해 인터셉터가 적용된다)

 

적용할 경로를 추가할 때는 addPathPatterns, 제외할 경로를 추가할 때는 excludePathPatterns를 적용한다.

경로는 Ant 표현식을 따른다.

 

? : 1개의 문자를 뜻한다

/test/product??.info  :  /test 아래 product로 시작하고 두 개의 임의의 문자가 나온 후 .info로 끝나는 경로를 의미

 

*  :  0개 이상의 문자

/test/?*.info  :  /test 아래 한 글자 이상의 문자가 무조건 있고 .info로 끝나는 경로를 의미

 

**  :  0개 이상의 디렉토리

/test/**/info:  /test의 하위 디렉토리에 depth 상관없이 /info로 끝나는 모든 경로를 의미

ex) /test/product/info,  /test/product/detail/info 

 

 

3. 구현 방식

Filter는 web.xml에서 설정을 하면 구현이 가능하지만, Interceptor는 메서드를 직접 구현해야 한다.

 

public class TestInterceptor implements HandlerInterceptor {    
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        // 컨트롤러가 호출되기 전에 실행될 코드 추가
        System.out.println("Interceptor - preHandle");

        // 매개변수의 handler를 활용하여 실행되는 컨트롤러, 메서드에 대한 정보를 파악 가능
        HandlerMethod handlerMethod = (HandlerMethod) handler; // HandlerMethod 타입으로 형변환

        String controllerName = handlerMethod.getBean().getClass().getSimpleName(); // 컨트롤러명
        String packageName = handlerMethod.getBean().getClass().getCanonicalName(); // 패키지경로
        String actionName = handlerMethod.getMethod().getName(); // 메서드명

        // true를 반환하면 controller로 요청을 보내고 false면 요청을 보내지 않음
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {

        // 컨트롤러가 실행된 후에 호출되는 코드 추가
        System.out.println("Interceptor - postHandle");

        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

        // View까지 처리가 끝난 후에 실행될 코드 추가
        System.out.println("Interceptor - afterCompletion");

        return true;
    }
    
 }

1.  preHandle() 메서드는  컨트롤러가 호출되기 전에 실행된다.

매개변수 handler는 DispatcherServlet의 HandlerMapping이 찾아준 컨트롤러의 메서드를 참조할 수 있는 HandlerMethod 객체이다.

handler를 HandlerMethod 타입으로 형변환 한 후 실행될 컨트롤러와 메서드에 관한 정보를 얻을 수 있다.

 

2.  postHandle() 메서드는 컨트롤러가 실행된 후에 호출된다.

Spring MVC의 Front Controller인 DispatcherServlet이 화면을 처리하기 전에 동작한다.

예를 들면, 메서드의 실행 결과를 session에 담아야 하는 경우를 생각해 볼 수 있다.

 

3.  afterComplete() 은 뷰에서 최종 결과가 생성하는 일을 포함한 모든 일이 완료 되었을 때 실행된다.

 

* 각 메서드의 반환값이 true이면 핸들러의 다음 체인이 실행되지만 false이면 중단하고 남은 인터셉터와 컨트롤러가 실행되지 않는다.

+ Recent posts