[Spring] Interceptor란?

Interceptor(인터셉터)란?

Interceptor는 

Controller가 요청을 처리하기 전/후 처리를 위한 것으로, Spring MVC에서 HTTP 요청을 가로채 처리하는 컴포넌트

입니다.

 

 클라이언트의 요청이 Controller로 전달되기 전에 사전 작업을 수행하거나, Controller의 실행 이후 사후 작업을 수행할 수 있습니다. 즉, 서버에 들어온 Request 객체가 Controller의 Handler로 도달하기 전에 확인해 개발자가 원하는 추가적인 작업을 수행한 뒤, Handler로 보낼 수 있도록 해주는 것이 Interceptor 입니다. 

 

Interceptor를 사용하면 공통 코드 사용으로 코드의 재사용성이 증가합니다. 또한, 로깅, 모니터링 정보 수집, 접근 제어 처리 등의 실제 비즈니스 로직과는 분리되어 처리해야 하는 기능들을 넣고 싶을 때 유용하게 사용할 수 있습니다. 

사용 예시

  • Logic Session 검증
  • Header 검증
  • (JWT) token 검증

Interceptor의 호출 흐름

Spring Interceptor의 동작은 크게 'Controller 실행 전', 'Controller 실행 후, View 실행 전', 'View 실행 후', 이 3단계로 구분됩니다. 

Spring Interceptor를 만들기 위해서는 `HandlerInterceptor` 인터페이스를 구현해야 하는데 해당 인터페이스가 제공하는 메서드는 다음과 같습니다. 

 

이때, 각 메서드의 반환값이 `true` 이면 핸들러의 다음 동작이 실행되고, `false` 이면 중단되어 남은 Interceptor와 Controller가 실행되지 않습니다. 

preHandle() 

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
Controller method가 실행되기 전에 호출
  • `false`를 반환하면 request를 바로 종료합니다. 
  • 전처리 작업이나 요청 정보를 가공하는 작업 등에 유용하게 사용됩니다. 
  • 인증 처리 등에 사용

postHandle()

void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav)
Controller method 실행 직후 View 페이지가 렌더링 되기 전에 호출

만약, Controller에서 예외가 발생한다면, `postHandle()` 메서드는 실행되지 않습니다. 

afterCompletion()

void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
View 페이지가 렌더링 된 후 호출

Controller 실행 과정에서 예외가 발생한 경우, 해당 예외가 `afterCompletion()` 메서드의 4번 째 파라미터로 전달되어, 로그로 남기는 등 후처리를 위해 사용될 수 있습니다. 

 

위의 3가지 메서드의 호출 흐름을 그림으로 표현하면 아래와 같습니다.

 

추가적으로, Interceptor를 여러 개 설정할 수 있습니다. 이때 Interceptor를 설정(등록)하는 순서에 따라, 동작하는 순서가 달라져 유의해야 합니다.

Interceptor 구현

Interceptor는 `HandlerInterceptor` 인터페이스를 구현해 만들 수 있습니다. 

Interceptor 작성

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("Pre Handle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        System.out.println("Post Handle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("After Completion");
    }
}

Interceptor 등록

`WebMvcConfigurer` 인터페이스를 구현하면 Spring MVC의 설정을 할 수 있습니다. 이를 통해 Interceptor 등록이 가능합니다. 

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/users/*")
                .excludePathPatterns("/items/*");
    }
}

위 `InterceptorRegistry`는 `addInterceptor()` 메서드를 통해 `InterceptorRegistration()` 타입의 객체를 반환합니다. 이 객체는 `addPathPatterns()`와 `excludePathPatterns()`라는 메서드를 제공합니다. 

addPathPatterns() 

해당 경로에 대해 인터셉터를 추가한다.

excludePathPatterns()

해당 경로에 대해 인터셉트를 제외시킨다.