인터셉터

Lilac-_-P·2023년 4월 18일
0

스프링 MVC

목록 보기
11/15
post-thumbnail

스프링 인터셉터도 서블릿 필터와 같이 웹과 관련된 공통 관심사를 효과적으로 해결할 수 있는 기술이다.
서블릿 필터가 서블릿이 제공하는 기술이라면, 스프링 인터셉터는 스프링 MVC가 제공하는 기술이다. 둘다 웹과 관련된 공통 관심사를 처리하지만, 적용되는 순서와 범위, 그리고 사용방법이 다르다.

스프링 인터셉터 흐름

스프링 인터셉터의 흐름은 아래와 같다.

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 스프링 인터셉터 ->컨트롤러

스프링 인터셉터는 DispatcherServlet과 컨트롤러 사이에서 컨트롤러 호출 직전에 호출된다.

어찌보면 당연하다. 스프링 MVC의 시작점이 DispatcherServlet이고, 스프링 인터셉터는 스프링 MVC가 제공하는 기능이기 때문에 결국 DispatcherServlet 이후에 등장하는게 맞다.

스프링 인터셉터도 서블릿 필터처럼 URL 패턴을 적용해서 WAS로 들어오는 특정 URL로의 요청중 원하는 요청만 골라서 공통 관심사 처리를 수행할 수 있다. 다만, 스프링 인터셉터의 URL 패턴은 서블릿 필터의 URL 패턴과 다르고, 매우 정밀하게 설정할 수 있다.

스프링 인터셉터도 아래와 같은 제한을 둘 수 있다. (편의상 흐름을 살짝 생략하겠다)

[적절한 요청] : 서블릿 -> 스프링 인터셉터 -> 컨트롤러

[부적절한 요청] : 서블릿 -> 스프링 인터셉터(적절하지 않은 요청이라 판단, 컨트롤러 호출 X) -> 컨트롤러

인터셉터도 적절하지 않은 요청이라고 판단하면, 컨트롤러를 호출하지 않고 거기에서 끝낼 수 있다.
필터와 동일하게, 체인으로 구성되어 있으므로 중간에 인터셉터를 자유롭게 추가할 수 있다.

지금까지 내용을 보면 서블릿 필터와 호출되는 순서만 다르고, 제공하는 기능을 비슷해보인다.
스프링 인터셉터가 서블릿 필터와 다른 점은 스프링 MVC에서 제공하는 기능이기 때문에 스프링을 이용하는 개발자에게 서블릿 필터보다 편리하고, 더 정교하고 다양한 기능을 지원한다는 것이다.

스프링 MVC가 제공하는 스프링 인터셉터 인터페이스를 보자.

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

}

서블릿 필터 인터페이스에서는 필터의 역할을 하는 실질적인 함수가 doFilter() 하나였다면, 인터셉터는 호출 전(preHandle), 호출 후(postHandle), 요청 완료 이후(afterCompletion) 와 같이 단계적으로 세분화 되어 있다. 또, 인터셉터는 어떤 컨트롤러(함수에서는 Handler로 받고있음)가 호출되는지 호출정보도 받을 수 있고, 어떤 ModelAndView가 반환되는지 응답정보도 받을 수 있다.

스프링 인터셉터 호출 흐름

스프링 인터셉터 호출은 위의 그림과 같다.

정상적인 흐름일 경우,

  • preHandle은 컨트롤러 호출 전에 호출된다.(정확히는 핸들러 어댑터가 호출되기 전에 호출된다)
    preHandle의 응답값이 true이면 다음 인터셉터 혹은 남은 인터셉터가 없다면 핸들러 어댑터를 호출한다.
    응답값이 false라면 나머지 인터셉터는 물론이고, 핸들러 어댑터도 호출되지 않는다.
    서블릿 필터의 doFilter()에서 필터체인을 이용해서 다음 필터나 서블릿을 호출하는 방식과 유사하다.
  • postHandle은 컨트롤러 호출 후에 호출된다.(정확히는 핸들러 어댑터가 MAV를 반환한 뒤에 호출 된다)
  • afterCompletion은 뷰가 렌더링 된 이후에 호출된다.

만약에 Handler(Controller)에서 예외가 발생하면 어떻게 될까?

Controllerd에서 예외가 발생하는 비정상적인 흐름일 경우,

  • preHandle은 정상적인 흐름과 동일하게 컨트롤러 호출 전에 호출된다.
  • postHandle은 컨트롤러에서 예외가 발생하면 호출되지 않는다.
  • afterCompletion은 항상 호출된다.
    추가적으로 컨트롤러에서 발생한 예외를 파라미터로 받아서 어떤 예외가 발생했는지 알수 있다.

주의.
HandlerInterceptor를 구현한 스프링 인터셉터는 스프링에 의해서 싱글톤으로 관리되기 때문에, 인터셉터 내부에서 공유될 수 있는 멤버변수를 사용할 수 없다.

참고. 스프링 부트에서는 인터셉터를 손쉽게 등록하는 방법을 제공한다. @Configuration을 이용한 설정 파일에서 WebMvcConfigurer 인터페이스를 implements하여 addInterceptor() 함수를 오버라이딩 하면된다. 자세한 것은 필요할 때 찾아볼 것.

서블릿 필터와 비교해보면 상대적으로 스프링 인터셉터가 제공하는 기능이 더 편리하고, 정밀하다.
서블릿 필터와 스프링 인터셉터 둘다 웹과 관련된 공통 관심사를 해결하기 위한 기술이다. 상황에 맞게 둘 중 하나를 골라서 사용하면 된다.

profile
열심히 하자

0개의 댓글