본문으로 바로가기

목차

    1. 인터셉터를 왜 쓰나요?

    결론부터 말하면 공통부분을 따로 작성하여 중복 소스를 줄이고 소스 관리도 쉬워져 유지보수에 좋습니다.

     

    Spring (자바) 개발을 하다 보면공통적으로 처리해야 할 부분들이 많습니다.

    예를 들으면 인코딩, CORS, XSS, LOG, 인증, 권한, 로그인(인증) 체크, 권한(인가) 체크 등과 같은 작업들이 있는데, 이러한 작업 코드를 소스마다 작성한다면 중복된 코드도 많아지고 프로젝트가 클 경우 부하를 줄 수도 있고 유지보수도 힘들게 됩니다.

    인터셉터는 이러한 공통부분을 따로 작성할 수 있게 도와주는 역할을 합니다.

    인터셉터 외에도 필터나 AOP가 있습니다.

    2. 구조

    구조

    DispatcherServlet:

    가장 앞단에서 HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프런트 컨트롤러(Front Controller)라고 할 수 있습니다.

    3. 인터셉터 특징

    • 가로채기(요청에 대한 작업 전/후로 가로챈다)
    • DispatcherServlet와 Controller(Handler) 사이에서 동작합니다.
    • Interceptor는 Spring의 Context(ApplicationContext)에 등록합니다.
    • Spring Context(영역)의 기능이며 일종의 빈입니다.
    • Spring Context(영역)에 있으므로 다른 빈을 활용 가능하기에 때문에 주로 비즈니스 로직과 관련 있는 공통 작업을 처리합니다.
    • 로그인(인증) 체크, 권한(인가) 체크 등에 주로 사용합니다.
    • 인터셉터는 여러 개를 사용할 수 있습니다.

    4. 인터셉터 주요 메서드

    ㆍpreHandler() - 컨트롤러 메서드가 실행되기 전에 실행됩니다.
    ㆍpostHanler() - 컨트롤러 메서드 실행직 후 view페이지 렌더링 되기 전에 실행됩니다.
    ㆍafterCompletion() - view페이지가 렌더링 되고 난 후에 실행됩니다.

    5. 인터셉터 작성

    • HandlerInterceptor를 implements 하여 구현합니다.
    • 각 메서드 설명은 주석으로 첨부했습니다.
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @Slf4j
    @Component
    public class ApiInterceptor implements HandlerInterceptor {
    
        /*
         [PreHandle(HttpServletRequest request, HttpServletResponse response, Object handler)]
         - Controller로 보내기 전 이벤트 작동
         - false일 경우 실행 종료(Controller 진입 X)
         - Object handler는 HandlerMapping이 찾은 Controller Class 객체
      */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            log.info("pre");
            return true;
        }
    
        /*
            [PostHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)]
            - Controller 진입 후 View가 Rendering 되기 전 수행
            - ModelAndView modelAndView를 통해 화면 단에 들어가는 Data 등의 조작이 가능
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("post");
        }
    
        /*
            [afterComplete(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)]
            - Controller 진입 후 View가 정상적으로 Rendering 된 후 수행
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("after");
        }
    }

    6. 인터셉터 설정

    • 인터셉터를 사용하기 위해서는 WebMvcConfigurer에 설정해야 합니다.
    • 주석을 보고 인터셉터에 제외되거나 포함될 경로를 지정하면 됩니다.
    import com.test.api.interceptor.ApiInterceptor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class WebMvcConfiguration implements WebMvcConfigurer {
    
        @Autowired
        ApiInterceptor apiInterceptor;
    
        // Interceptor에서 제외되는 URL 주소
        private static final String[] EXCLUDE_PATHS = {
                "/",
                "/api/auth/tokens"
        };
    
        @Override
        public void addInterceptors (InterceptorRegistry registry) {
            registry.addInterceptor(apiInterceptor)
                    .excludePathPatterns(EXCLUDE_PATHS) //인터셉터에 포함되지 않음
                    .addPathPatterns("/test/**") //인터셉터에 포함됨
            ;
        }
    }