- Spring MVC 마스터하기 인터셉터 12022년 06월 04일
- starryeye
- 작성자
- 2022.06.04.:08
전 포스팅에서는 서블릿에서 제공하는 필터에 대해 알아봤다..
이번엔 Spring MVC에서 제공하는 인터셉터에 대해 알아보자..
스프링 인터셉터도 서블릿 필터와 같이 웹과 관련된 공통 관심 사항을 효과적으로 해결할 수 있는 기술이다.
요청/응답 순서도를 다시 한번 알아보자..
요청이 들어오면..
요청 -> WAS -> 필터 -> DispatcherServlet -> 인터셉터 -> 각 메서드 컨트롤러의 AOP(Proxy패턴) -> 컨트롤러
응답으로 나갈때는 요청 호출의 역행으로 return 된다.
컨트롤러 -> 각 메서드 컨트롤러의 AOP(Proxy패턴) -> 인터셉터 -> DispatcherServlet -> 필터 -> WAS -> 요청
스프링 인터셉터
순서도에서 볼 수 있듯이..
DispatcherServlet 과 컨트롤러 사이에서 위치한다.
(Spring MVC가 제공하는 기능이라 DispatcherServlet 이후에 등장!)
(Spring MVC 시작점이 DispatcherServlet이라 생각하자)
서블릿 필터와 동일하게 체인으로 동작한다.
여러개의 인터셉터를 등록해놓으면 여러 인터셉터를 거친 다음에 컨트롤러가 호출 된다.
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 { } }
위 코드는 인터셉터의 인터페이스이다.
셋다 모두 default 키워드로 구현할 필요가 없는 메서드는 구현 할 필요 없다.
preHandle : 컨트롤러 요청전에 수행되는 메서드 (핸들러 어댑터 호출 직전)
-> return 값이 boolean이며 false로 리턴 될 시, 다음 인터셉터 또는 컨트롤러 호출이 되지 않는다.
postHandle : 컨트롤러 요청후 수행되는 메서드 (핸들러 어댑터 호출 직후)
afterCompletion : Http 요청이 완전히 끝날때 수행되는 메서드 (뷰가 렌더링 된 이후)
<참고>
서블릿 필터는 doFilter 메서드 하나만 제공되는데에 비해, 인터셉터는 3단계의 메서드로 세분화 되어 구성되어있다.
또한, 필터는 파라미터가 request, response 두개인데에 비해, 어떤 컨트롤러가 호출되는지에 대한 파라미터 handler가 제공되며, 파라미터 modelAndView로 컨트롤러의 응답도 알아볼 수 있다.
위 그림은 예외 발생 없이 정상 흐름에서의 순서를 나타낸다.
preHandle, postHandle, afterCompletion 메서드의 순서를 잘 보자..
<참고>
컨트롤러에서 예외가 발생된다면..
postHandle 메서드가 호출이 되지 않는다.
하지만, afterCompletion은 호출 된다.
-> 이점을 이용하여 예외와 무관한 공통 처리를 하려면 afterCompletion에서 처리해주자..
-> 예외 정보도 파라미터 ex 로 알 수 있다.
요청/응답 로그용 인터셉터를 구현해보자
HandlerInterceptor 를 상속받아 구현하였다.
하나의 요청/응답에 하나의 임의의 값으로 구분 할 수 있는 로그를 출력하기 위하여..
UUID.randomUUID().toString() 메서드를 활용하여 임의의 값을 생성한다.
싱글톤이기 때문에 맴버변수를 사용하면 안되며 임의의 값을 지역변수로 받았다.
응답에도 동일하게 출력해야 하므로, request에 setAttribute/getAttribute 메서드를 사용한다.
preHandle에서 생성하고 넣어주고, 예외 발생시에도 호출 되는 afterCompletion에서 빼서 사용한다.
if(handler instanceof HandlerMethod) 는
해당 컨트롤러가 메서드 컨트롤러(@Controller & @RequestMapping)인지에 대한 조건문이다.
(정적 리소스 요청의 경우 ResourceHttpRequestHandler 이다.)
preHandle의 return 값을 true로 하여 다음 인터셉터와 Controller 호출이 될 수 있도록 한다.
Controller가 정상 흐름에 따라 종료 되고 어댑터가 호출 종료 되면 반환 값인 modelAndView를 파라미터로 하여
postHandle이 호출된다.
afterCompletion는 예외 발생시에도 호출이 되기 때문에 컨트롤러에서 발생된 예외가 파라미터로 넘어온다.
HandlerMethod
위 코드는 HandlerMethod의 맴버변수이다. (이외 관련 메서드들도 많다.)
구현한 인터셉터를 등록해보자.
@Configuration 을 사용한 클래스에서 WebMvcConfigurer를 상속받아서
addInterceptors를 오버라이딩 하여 등록할 수 있다.
addInterceptor : 구현한 인터셉터(LogInterceptor 클래스)를 등록한다.
order : 인터셉터 체인 개념에서 몇번째로 수행될 인터셉터인지 정해준다.
addPathPatterns : 인터셉터를 적용할 URL 패턴을 정한다.
excludePathPatterns : 인터셉터를 적용하지 않을 URL 패턴을 정한다.
-> 보통 addPathPatterns로 전체를 적용하고, excludePathPatterns 로 예외로 제외할 URL 패턴을 정한다.
-> 서블릿 필터의 whitelist 로직을 뺄 수 있게 되었다!
로그인 인증에 대한.. 구현 (생략)
로그인 인증을 할지 말지에 대한 인터셉터를 구현하는 것은
preHandle만 구현하면된다.
또한, 인증이 필요한 페이지에서 로그인 인증이 되지 않은 경우 return false를 하며,
서블릿 필터와 동일하게 redirect를 해준다.
(response.sendRedirect("/login?redirectURL=" + requestURI)
'Spring > MVC' 카테고리의 다른 글
Spring MVC 마스터하기 예외처리 1 (0) 2022.06.11 Spring MVC 마스터하기 5 (0) 2022.06.04 Spring MVC 마스터하기 필터 1 (0) 2022.06.03 Spring MVC 마스터하기 쿠키, 세션 4 (0) 2022.06.03 Spring MVC 마스터하기 쿠키, 세션 3 (0) 2022.05.29 다음글이전글이전 글이 없습니다.댓글