본문 바로가기

Spring/MVC

스프링 인터셉터

스프링 인터셉터는 웹과 관련된 공통 관심사를 처리를 할 때 사용한다. AOP도 공통 관심사에 대한 처리를 하지만 AOP는 주로 메서드를 중심으로 처리하는 반면 인터셉터는 주로 HTTP 헤더 정보나 URL 정보, 세션 정보, 쿠키 정보, 핸들러 정보 등을 이용해서 웹 요청 자체에 초점을 맞춰서 처리한다.

HandlerInterceptor

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 {
	}
}

 

인터셉터를 사용하기 위해서는 HandlerInterceptor를 상속 받고 preHandle(), postHandle(), afterCompletion()를 구현해주면 된다. 다만 interface의 메서드가 default로 되어있어 필수로 구현할 필요는 없고 상황에 맞춰 구현해주면 된다. 

 

preHandle()

preHandle 메서드는 컨트롤러가 호출되기 전에 호출된다. 인터셉터의 경우 handler의 정보를 받아 호출할 컨트롤러 메서드의 모든 정보를 알 수 있다. 주로 컨트롤러 이전에 처리해야 하는 전처리 작업이나 요청 정보를 가공하거나 추가하는 경우에 사용하게 되므로, 해당 메서드의 애너테이션이나 파라미터 정보를 가지고 요청을 제한을 하거나 특별한 로직을 추가할 수 있다.

그리고 preHandle 메서드의 경우 리턴값이 true 이면 다음으로 진행하고, false 이면 더는 진행하지 않는다. false 인 경우 나머지 인터셉터는 물론이고핸들러 어댑터도 호출되지 않은 채 바로 리턴을 한다.

 

postHandle()

postHandle 메서드는 컨트롤러가 호출된 후에 호출된다. ModelAndView 객체를 받아 내용을 변경할 수도 있으며, Rstful API를 만들 경우 null 값을 줘도 상관없다. 가장 큰 특징은 예외가 발생되면 실행되지 않는다.

 

afterCompletion()

afterCompletion 메서드는 모든 작업이 완료된 후에 실행된다. postHandle 메서드의 경우 요청이 정상적으로 완료가 되어야 호출되지만, afterCompletion 메서드는 예외가 발생해도 호출된다. 예외가 발생되면 Exception 정보를 얻을 수 있어 Exception에 맞춰 응답을 처리할 수도 있다.

스프링 인터셉터 흐름

정상 흐름

  • preHandle : 컨트롤러 호출 전에 호출된다. (더 정확히는 핸들러 어댑터 호출 전에 호출된다.)
  • postHandle : 컨트롤러 호출 후에 호출된다. (더 정확히는 핸들러 어댑터 호출 후에 호출된다.) 
  • afterCompletion : 뷰가 렌더링 된 이후에 호출된다.

 

예외 발생 흐름

  • preHandle : 컨트롤러 호출 전에 호출된다.
  • postHandle : 컨트롤러에서 예외가 발생하면 postHandle 은 호출되지 않는다.
  • afterCompletion : afterCompletion 은 항상 호출된다. 이 경우 예외( ex )를 파라미터로 받아서 어떤 예외가 발생했는지 로그로 출력할 수 있다.

서블릿 필터와 차이점

서블릿 필터와 스프링 인터셉터의 요청 시 호출되는 위치

필터 : HTTP 요청  →  WAS  →  서블릿 필터(doFilter)  →  서블릿  → ...

인터셉터  : HTTP 요청  →  ...  →  디스패처 서블릿  →  스프링 인터셉터(preHandle)  →  컨트롤러  →  ...

 

서블릿 필터와 스프링 인터셉터는 둘 다 웹 관련 공통 관심사를 처리하는 일을 한다. 둘 다 ServletRequest를 통해 헤더 정보, URL 정보 등 요청 정보를 분석하고 이를 이용할 수도 있다. 하지만 서블릿 필터와 인터셉터는 호출되는 위치부터 제공되는 기능, 사용 방법이 다르다.

 

첫 번째. 필터는 Servlet API 스펙이며, 인터셉터는 Spring 스펙이다.

  

두 번째. 필터의 경우 단순하게 doFilter 메서드 하나만 제공된다. 인터셉터는 컨트롤러 호출 전( preHandle ), 호출 후( postHandle ), 요청 완료 이후( afterCompletion )와 같이 단계적으로 잘 세분화 되어 있다. 서블릿 필터의 경우 단순히 request , response 만 제공했지만, 인터셉터는 어떤 컨트롤러( handler )가 호출되는지 호출 정보도 받을 수 있고, 어떤 modelAndView 가 반환되는지 응답 정보도 받을 수 있다.

 

인터셉터의 경우 권한 확인이나 컨트롤러를 조작해야 하는 경우 주로 사용되며, 필터의 경우 로깅 요청, 인증, 이미지 처리, zip 압축 등에 사용된다고 한다.

 


참고 자료

https://inf.run/Dvu9

 

https://www.linkedin.com/pulse/filter-vs-interceptor-spring-boot-omar-ismail#:~:text=Filters%20vs%20HandlerInterceptors,(authorization%20checks%2C%20etc.)