Springboot기초 - interceptor

Hailey·2025년 3월 8일

SPRING

목록 보기
10/15
post-thumbnail

Interceptor

인터셉터란?

웹 요청(request)과 응답(response)의 흐름을 가로채서 특정 로직을 수행하는 역할을 한다.

사용 목적 :보통 로그인 체크, 권한 검사, 실행 시간 측정, 로깅, 공통 설정 등에 사용된다!

필터와 비슷해보이지만, 인터셉터는 bean을 다룰 수 있다.

동작원리..는 아래의 파일들이 유기적으로 연결되어 어떤 일을 하는지 참고해보자..

1.WebConfiguration 클래스 ( 웹 설정 담당 )

여기서는 어떤 인터셉터를 사용할지, 어떤 핸들러 메소드(컨트롤러 중..)를 대상으로 하거나
제외할지 등의 기본적인 웹 설정을 담당한다.

@Configuration
public class WebConfiguration implements WebMvcConfigurer {
    private StopwatchInterceptor stopwatchInterceptor;

    @Autowired
    public WebConfiguration(StopwatchInterceptor stopwatchInterceptor) {
        this.stopwatchInterceptor = stopwatchInterceptor;
    }

Spring의 WebMvcConfigurer 인터페이스를 구현하여 웹을 설정한다.

@Configuration : 이 클래스가 설정 파일임을 의미.
WebMvcConfigurer : Spring MVC 관련 설정을 제공하는 인터페이스.
StopwatchInterceptor라는 인터셉터 클래스를 @Autowired로 주입받아 사용

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(stopwatchInterceptor)
                .excludePathPatterns("/css/**");
    }

addInterceptors 메소드를 통해 아까 주입받은 인터셉터(stopwatchInterceptor)를 추가하고, excludePathPatterns를 통해 특정경로는 제외해준다.

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/css/**")
                .addResourceLocations("classpath:static/css/")
                .setCachePeriod(100);
    }
}

정적 리소스인 css파일의 위치를 classpath:static/css/로 설정하고 이를 setCachePeriod() 메소드를 이용하여 브라우저가 100초 동안 캐시를 유지하도록 설정.

2.InterceptorTestController 클래스 ( 컨트롤러 )

사용자의 요청을 처리하는 컨트롤러 클래스!

@Controller
public class InterceptorTestController {

    @GetMapping("stopwatch")
    public String handlerMethod() throws InterruptedException {
        System.out.println("핸들러 메소드 호출함...");

        Thread.sleep(1000);

        return "result";
    }
}

@Controller : Spring MVC의 컨트롤러로 사용.
@GetMapping("stopwatch") : stopwatch 경로로 GET 요청이 오면 핸들러 메서드가 실행되는데,
Thread.sleep(1000): 으로 1초 후에 result 뷰를 반환하게 된다.

하지만 스레드가 강제로 중단(interrupt)되면 InterruptedException이 발생할 수 있어.

따라서 throws InterruptedException을 선언하여 이 예외가 발생할 가능성이 있음을 컴파일러에 알려줌.

3.InterceptorTestService 클래스 (서비스)

비즈니스 로직을 처리하는 서비스 클래스!

@Service
public class InterceptorTestService {
    public void test() {
        System.out.println("서비스 bean 동작 확인");
    }
}

이 서비스 클래스는 뒤에 나올 인터셉터 클래스에서 의존성 주입받아서 호출될 용도로 만들어짐

4.StopwatchInterceptor 클래스 (인터셉터)

핸들러 실행 전후에 특정 로직을 실행하느 인터셉터 클래스!

@Component
public class StopwatchInterceptor implements HandlerInterceptor {
    InterceptorTestService testService;

    @Autowired
    public StopwatchInterceptor(InterceptorTestService testService) {
        this.testService = testService;
    }

@Component : 스프링 빈으로 등록.
HandlerInterceptor 인터페이스를 구현하여 인터셉터 역할 수행.
@Autowired : 자동으로 InterceptorTestService를 주입받음.

preHandle(핸들러 실행 전)

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle 호출함...(핸들러 메소드 이전)");

        /* 설명. Service bean에 있는 메소드 호출 */
        testService.test();

        /* 설명. requestHeader에서 지역 추출 */
        Locale locale = request.getLocale();
        System.out.println("locale = " + locale);
        if("ko_KR".equals(locale.toString())) System.out.println("한국인이시군요");

        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);

        return true;
    }

prehandle : 핸들러 실행 전에 동작.

testService.test() : 주입받은 서비스 클래스의 서비스 로직 호출.

request.getLocale() : 요청한 사용자의 지역(Locale) 확인
request.setAttribute("startTime", startTime) : 요청 시작 시간 저장.

postHandle(핸들러 실행 후, 뷰 렌더링 전)

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle 호출함...(핸들러 메소드 이후)");

        long startTime = (Long)request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();

        modelAndView.addObject("interval", endTime - startTime);
    }

핸들러 실행 후(뷰 렌더링 전에) 동작.

startTime을 가져와 요청 처리 시간을 계산 후 ModelAndView에 추가.

afterCompletion(뷰 렌더링 후)

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

뷰 렌더링까지 완료된 후 실행.

근데 인터셉터가 어떤 핸들러 메서드를 대상으로 작동하는지 어떻게 알까?

처음에 설정했던 WebConfiguration 클래스에서 이미 설정했다!!

WebConfiguration에서 설정된 인터셉터의 대상 경로를 보면 확인할 수 있다.

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(stopwatchInterceptor)
            .excludePathPatterns("/css/**"); // 정적 리소스(/css/)는 제외
}

stopwatchInterceptor는 모든 요청에 대해 인터셉트하지만,
컨트롤러말고 "/css/**" 경로는 제외됨.

따라서, 현재는 모든 컨트롤러가 기본적으로 인터셉트 대상이다!

특정 컨트롤러만 적용하려면 addPathPatterns()

특정 컨트롤러만 인터셉터 적용하려면 위

 .addPathPatterns("/stopwatch")  // "/stopwatch" 경로만 인터셉트

이렇게 하면 /stopwatch 요청을 처리하는 InterceptorTestController만 인터셉트됨

addPathPatterns()과 excludePathPatterns()를 사용하면 특정 컨트롤러만 인터셉트 가능.

profile
럭키헤일리

0개의 댓글