Interceptor 란?

정식 명칭은 Handler Intercpetor(핸들러 인터셉터) 이다. 이 Interceptor 는 URL 기반으로 일부 혹은 전체의 클라이언트 요청을 가로채서 공통된 비즈니스 로직을 실행하는 역할을 한다.

설정에 따라 클라이언트의 요청이 컨트롤러에 가기 전과, 응답이 클라이언트에 가기 전에 실행된다. 즉, Intercpetor 는 DispatcherServlet 이 컨트롤러를 요청하기 전, 후에 요청과 응답을 가로채서 비즈니스 로직을 통해 데이터를 검증, 가공할 수 있도록 해 준다.


Spring Boot 에서 Interceptor 구현

Spring Boot 에서는 어노테이션, Java Code 기반으로 손쉽게 Intercpetor 를 구현할 수 있다.

  • CommonInterceptor.java
package com.nexon.quicksample.core.interceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
 
@Component
public class CommonInterceptor implements HandlerInterceptor {
     
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
         
        System.out.println("CommonInterceptor::preHandle");
         
        return true;       
    }
     
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
 
        System.out.println("CommonInterceptor::postHandle");
    }
     
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
 
        System.out.println("CommonInterceptor::afterCompletion");
    }

}

우선 Interceptor 의 기본 골격인 interface HandlerInterceptor 를 구현하는 것으로 Interceptor 를 생성한다.

  • ContextConfig.java
package com.nexon.quicksample.core.config;
 
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;
 
import com.nexon.quicksample.core.interceptor.CommonInterceptor;
 
@Configuration
public class ContextConfig implements WebMvcConfigurer {
     
    @Autowired
    private CommonInterceptor commonInterceptor;
     
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(commonInterceptor);
    }
     
}

interface WebMvcConfigurer 를 상속받은 Configuration 구현체에서 addInterceptors() 메서드를 Override 하여 interceptorRegistery 에 앞서 생성한 interceptor 를 추가하는 것으로, Spring Boot 에 Interceptor 추가가 가능하다.


테스트

간단한 비즈니스 로직과 함께 로그를 확인하여, Intercpetor 의 실행 여부와 프로세스 흐름을 확인하자.

  • HomeController.java
package com.nexon.quicksample.home;
 
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
 
@RestController
@RequestMapping({"/", "/home"})
public class HomeController {
     
    @RequestMapping("/hello")
    public String hello() {
         
        System.out.println("HomeController:hello");
         
        return "Hello World!";
    }
     
}

결과는 다음과 같은 순서로 출력될 것이다.

CommonInterceptor::preHandle
HomeController::hello
CommonInterceptor::postHandle
CommonInterceptor::afterCompletion

postHandle 과 afterCompletion 의 차이(추가)

postHandle 과 afterCompletion 은 Response(응답)이 클라이언트로 전송되기 전에 실행된다는 점은 같지만 차이가 존재한다.

순서 : postHandle -> afterCompletion 의 순으로 실행된다.
에러 여부(중요*) : 만약 비즈니스 로직 처리 중에 에러가 발생된다면 afterCompletion 은 실행되지만 postHandle 은 실행되지 않는다.
(afterCompletion 은 어떠한 상황에서도 실행된다고 생각할 수 있다.)