본문 바로가기
SpringBoot/Common

인터셉터(Interceptor)

by BAYABA 2021. 9. 22.
  1. 개인 공부 목적으로 작성한 글입니다.
  2. 아래 출처를 참고하여 작성하였습니다.

1. 인터셉터란?

  1. Spring이 제공하는 기술로써, 디스패처 서블릿(Dispatcher Servlet)이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공합니다.
  2. 즉, 웹 컨테이너에서 동작하는 필터와 달리 인터셉터는 스프링 컨텍스트에서 동작을 하는 것입니다.
  3. 디스패처 서블릿은 핸들러 매핑을 통해 적절한 컨트롤러를 찾도록 요청하는데, 그 결과로 실행 체인(HandlerExecutionChain)을 돌려줍니다. 그래서 이 실행 체인은 1개 이상의 인터셉터가 등록되어 있다면 순차적으로 인터셉터들을 거쳐 컨트롤러가 실행되도록 하고, 인터셉터가 없다면 바로 컨트롤러를 실행합니다.
  4. 인터셉터는 스프링 컨테이너 내에서 동작하므로 필터를 거쳐 프론트 컨트롤러인 디스패처 서블릿이 요청을 받은 이후에 동작하게 되는데, 이러한 과정을 그림으로 표현하면 아래와 같습니다.


2. 인터셉터 동작 위치 및 순서

  1. 사용자는 서버에 자신이 원하는 작업을 요청하기 위해 url을 통해서 Request 객체를 보냅니다.
  2. 디스패처 서블릿(Dispatcher Servlet)은 해당 Request 객체를 받아서 분석한 뒤 '핸들러 맵핑(HandlerMapping)'에게 사용자의 요청을 처리할 핸들러를 찾도록 요청합니다.
  3. 그 결과로 핸들러 실행 체인(HandlerExecutionChain)이 동작하게 되는데, 이 핸들러 실행 체인은 하나 이상의 핸들러 인터셉터를 거쳐서 컨트롤러가 실행될 수 있도록 구성되어 있습니다.
  4. 핸들러 인터셉터를 등록하지 않았다면 곧바로 컨트롤러가 실행됩니다. 반대로 하나 이상의 인터셉터가 지정되어 있다면 지정된 순서에 따라서 인터셉터를 거친 후에 컨트롤러가 실행됩니다.


3. 인터셉터의 메소드

  1. 인터셉터를 추가하기 위해서는 org.springframework.web.servlet의 HandlerInterceptor 인터페이스를 구현 혹은 HandlerInterceptorAdater 클래스를 상속받아야 하며 이는 다음의 3가지 메소드를 가지고 있습니다.
  • preHandle
  • postHandle
  • afterCompletion
public interface HandlerInterceptor { 

  default boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
    Object handler) throws Exception { 

    return true; 
  } 

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

  } 

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

  }
}

3-1. preHandle 메소드

  1. preHandle 메소드는 컨트롤러가 호출되기 전에 실행됩니다. 그렇기 때문에 컨트롤러 실행 이전에 처리해야 하는 전처리 작업이나 요청 정보를 가공하거나 추가하는 경우에 사용할 수 있습니다.
  2. 실행되어야 할 '핸들러'에 대한 정보를 인자 값으로 받기 때문에 '서블릿 필터'에 비해 보다 세밀하게 로직을 구성할 수 있습니다.
  3. preHandle의 반환 타입은 boolean인데, 반환값이 true이면 preHandle()을 실행 후 컨트롤러에 접근을 합니다. false라면 작업을 중단하여 이후의 작업(다음 인터셉터 또는 컨트롤러)은 진행되지 않습니다.

3-2. postHandle 메소드

  1. postHandle 메소드는 컨트롤러의 실행은 완료되었지만 아직 View가 생성되기 이전에 호출됩니다. 그렇기 때문에 컨트롤러 이후에 처리해야하는 후처리 작업이 있을 때 사용할 수 있습니다.
  2. ModelAndView 타입의 정보를 인자 값으로 받습니다. 따라서 Controller에서 View에 정보를 전달하기 위해 작업한 Model 객체의 정보를 참조하거나 조작할 수 있습니다.
  • 이 메소드에는 컨트롤러가 반환하는 ModelAndView 타입의 정보가 제공되는데, 최근에는 Json 형태로 데이터를 제공하는 RestAPI 기반의 컨트롤러(@RestController)를 만들면서 자주 사용되지는 않습니다.
  1. preHandle()에서 리턴 값이 false인 경우 실행되지 않습니다.
  2. 적용 중인 Interceptor가 여러 개인 경우 preHandle()은 역순으로 호출됩니다.
  3. 비동기 요청 처리 시에는 처리되지 않습니다.

3-3. afterCompletion 메소드

  1. 모든 View에서 최종 결과를 생성하는 일을 포함한 모든 작업이 완료된 후에 실행됩니다.
  2. 요청 처리 중에 사용한 리소스를 반환할 때 사용하기에 적합합니다.
  3. preHandle()에서 리턴 값이 false인 경우 실행되지 않습니다.

4. 필터 vs 인터셉터


4-1. 필터와 인터셉터의 차이

  1. 필터와 인터셉터는 각각이 관리되는 컨테이너Request/Response의 조작가능 여부가 다릅니다.
  2. 그에 따라 용도도 달라지게 됩니다.


4-2. 필터의 사용 예시

  1. 보안 관련 공통 작업
  2. 모든 요청에 대한 로깅 또는 감사
  3. 이미지/데이터 압축 및 문자열 인코딩

  1. 필터에서는 스프링과 무관하게 전역적으로 처리해야 하는 작업들을 처리할 수 있습니다.
  2. 대표적인 예시로 보안과 관련된 공통 작업이 있습니다. 필터는 인터셉터보다 앞단에서 동작하기 때문에 전역적으로 해야하는 보안검사(XSS 방어 등)를 하여 올바른 요청이 아닐 경우 차단을 할 수 있습니다. 그러면 스프링 컨테이너까지 요청이 전달되지 못하고 차단되므로 안전성을 높일 수 있습니다.
  3. 또한 필터는 이미지나 데이터의 압축이나 문자열 인코딩과 같이 웹 애플리케이션에 전반적으로 사용되는 기능을 구현하기에 적합합니다. Filter는 다음 체인으로 넘기는 ServletRequest/ServletResponse 객체를 조작할 수 있다는 점에서 Interceptor보다 강력한 기술입니다.

4-3. 인터셉터의 사용 예시

  1. 인증/인가 등의 공통 작업
  2. API 호출에 대한 로깅 또는 감사
  3. Controller로 넘겨주는 정보(데이터)의 가공

  1. 인터셉터에서는 클라이언트의 요청과 관련되어 전역적으로 처리해야 하는 작업들을 처리할 수 있습니다. 대표적으로 인증이나 인가와 같이 클라이언트 요청과 관련된 작업 등이 있습니다. 이러한 작업들은 컨트롤러로 넘어가기 전에 검사해야 하므로 인터셉터가 처리하기에 적합합니다.
  2. 또한 인터셉터는 필터와 다르게 HttpServletRequest나 HttpServletResponse 등과 같은 객체를 제공받으므로 객체 자체를 조작할 수는 없습니다. 대신 해당 객체가 내부적으로 갖는 값은 조작할 수 있으므로 컨트롤러로 넘겨주기 위한 정보를 가공하기에 용이합니다. 예를 들어 JWT 토큰 정보를 파싱해서 컨트롤러에게 사용자의 정보를 제공하도록 가공할 수 있는 것입니다.
  3. 그 외에도 다양한 목적으로 API 호출에 대한 정보들을 기록해야하는 경우도 있습니다. 이러한 경우에 HttpServletRequest나 HttpServletResponse를 제공해주는 인터셉터는 클라이언트의 IP나 요청 정보들을 포함해 기록하기에 용이합니다.

출처

  1. [Spring] 필터(Filter) vs 인터셉터(Interceptor) 차이 및 용도
  2. [spring] Spring Interceptor 란?(HandlerInterceptor, HandlerInterceptorAdapter)

'SpringBoot > Common' 카테고리의 다른 글

Spring Multi profile 설정(YML)  (0) 2021.09.26
필터(Filter)  (0) 2021.09.22
Spring Profiles 설정 방법  (0) 2021.09.13