• 티스토리 홈
starryeye
  • 프로필사진
    starryeye
    • 분류 전체보기 (189)
      • C++ (17)
      • Java (24)
      • OOP (5)
      • Spring Reactive Stack (12)
        • Reactive Streams (3)
        • Netty (4)
        • Reactor (1)
        • Webflux (3)
        • DB, Cache 연동 (1)
      • Spring (90)
        • Core (17)
        • MVC (33)
        • Client (2)
        • Security (4)
        • DB, Cache 연동 (33)
      • DataBase (12)
        • RDBMS (2)
        • NoSQL (10)
      • Message Broker (6)
      • Web (4)
      • Network (4)
      • 대규모 시스템 설계 (15)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • Spring MVC 마스터하기 인터셉터 1
        2022년 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
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바