Springboot

[Springboot] Interceptor?

아몬드맛빼빼로 2024. 12. 15. 17:44
반응형

가끔 요구사항을 따라 Controller에서 반환된 값에 어떠한 공통된 데이터를 삽입해야하거나 로깅을 해야할 수도 있다.이를 위해서 다양한 방법이 있겠지만 그중에서 Interceptor를 사용할 수 있다.

Interceptor...?

Spring MVC 프레임워크에서 HTTP 요청을 가로채어 처리하는 컴포넌트의미한다. 클라이언트의 요청이 Controller에 도달하기 또는 처리된 추가적인 작업을 처리할 수 있다.

서버에 들어온 Request를 Controller의 Handler로 넘겨주기 전, 후에 낚아채어 개발자가 원하는 작업을 수행할 수 있도록 하는 것이 Interceptor이다.

특징

전역적 처리

  • 여러 컨트롤러에서 나눠서 처리되어야 하는 작업을 중앙에서 관리할 수 있으며 인증, 권한 검사, 로깅 등 전역적인 작업을 Interceptor에 위임할 수 있다.
  • 코드의 중복을 줄이고 유지보수성을 향상할 수 있다.

요청 처리 제어

  • Controller에 요청이 도달하기 전, 처리가 완료된 후 작동하여 Request의 전처리또는 후처리를 제어할 수 있다.

설정의 유연함

  • XML, Annotation 등의 설정 방식을 이용하여 Interceptor를 등록하고 관리할 수 있다.
  • 개발자의 선호나 프로젝트의 요구사항에 맞추어 자유롭게 설정할 수 있다.

다중 Interceptor

  • 여러 개의 Interceptor를 배치하여 일종의 Interceptor Chain을 구성할 수 있다.
  • 이를 활용하여 각각의 Interceptor가 처리한 결과를 조합하여 최종 처리 결과를 도출할 수 있다.

동작과정

  1. HandlerMapping 검색 - HandlerMapping 컴포넌트가 요청 URL과 관련된 적절한 Controller를 탐색한다.
  2. Interceptor Chain 생성 - 해당 Controller와 연결된 여러 Interceptor 객체들로 구성된 Chain를 구성한다.
  3. PreHandler 메서드 호출 - Interceptor Chain의 각 Interceptor은 PreHandler 메서드를 호출하여 요청을 가로채어 요청을 처리하기 전 전처리를 수행할 수 있다.
  4. Controller 호출 - PreHandler 실행 후 HandlerMapping가 적절한 Controller를 선택하여 호출한다.
  5. PostHandler 메서드 호출 - Controller의 실행이 완료된 후 각 Interceptor의 PostHandler 메서드가 호출되며 Controller의 반환값을 가로채고 후처리를 수행할 수 있다.
  6. View 렌더링과 응답 - PostHandler 메서드 실행 후 적절한 View를 렌더링 하여 클라이언트에 반환한다.
  7. AfterCompletion 메서드 호출 - 응답 이후 각 Interception의 AfterCompletion 메서드가 실행되며 주로 리소스 정리로깅을 실행할 수 있다.
더보기

비동기 요청에선 postHandler가 실행되지 않을 수 있다

Filter와 AOP

특징 Interceptor Filter AOP
동작 위치 Spring MVC 레벨 (DispatcherServlet 이후) Servlet 레벨 (DispatcherServlet 이전) Spring Bean 메서드 호출 전후
목적 컨트롤러 호출 전후의 작업 (인증, 로깅, 전처리 등) HTTP 요청 및 응답 처리 (헤더 조작, 필터링 등) 메서드 실행 전후 또는 특정 지점에서의 부가 작업
적용 대상 Spring MVC 요청 흐름에 한정 웹 애플리케이션의 모든 HTTP 요청/응답 모든 Spring Bean (특정 메서드, 클래스 등)
등록 방식 WebMvcConfigureraddInterceptors로 등록 @Bean으로 Filter 등록 또는 web.xml 설정 @Aspect와 Pointcut 표현식으로 정의
Spring 의존성 Spring MVC에 의존 Spring 없이도 사용 가능 (Servlet 스펙 기반) Spring AOP에 의존
주요 메서드 preHandle, postHandle, afterCompletion doFilter @Before, @After, @Around
적용 범위 컨트롤러 메서드 호출 전/후, View 렌더링 전후 HTTP 요청/응답의 원시 데이터를 조작 특정 메서드나 클래스에서 공통 로직 실행
요청 흐름 관여 정도 요청 흐름을 가로채거나, 추가 작업을 삽입 요청 흐름의 전반적 제어 가능 (헤더, 바디, 응답 등) 메서드 수준에서만 동작
사용 사례 인증, 인가, 로깅, 요청 전처리/후처리 CORS 처리, 응답 압축, 인증 토큰 검증 트랜잭션 관리, 로깅, 예외 처리
View와의 연관성 View 렌더링 전/후에 추가 작업 가능 View와 직접 연관되지 않음 View와 직접 연관되지 않음
활용 예시 공통 데이터 삽입,로깅,API 호출 제한  CORS 처리,인증 토큰 검증  공통 관심사(로깅, 트랜젝션 관리 등)를 처리
  • 특히나 Filter는 HTTP 요청/응답 레벨에서 동작하고, Interceptor는 컨트롤러 전후로 동작한다.

구현

HandlerInterceptor 인터페이스를 구현하여 사용한다 .

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class CustomInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("[preHandle] 컨트롤러 실행 전");
        return true; // false 반환 시 작동 중단
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("[postHandle] 컨트롤러 실행 후");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("[afterCompletion] View 렌더링 후");
    }
}

WebMvcConfigurer 인터페이스를 구현한 설정 클래스를 이용하여 Spring MVC에 등록한다.

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 WebConfig implements WebMvcConfigurer {

    private final CustomInterceptor customInterceptor;

    public WebConfig(CustomInterceptor customInterceptor) {
        this.customInterceptor = customInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(customInterceptor)
                .addPathPatterns("/api/**") // 적용할 경로
                .excludePathPatterns("/api/login", "/api/register"); // 제외할 경로
    }
}

 

'Springboot' 카테고리의 다른 글

Whitelabel Error Page와 Tomcat Error Page  (0) 2025.04.26
[Spring] Spring Batch  (0) 2025.03.05
[Spring] Spring Cloud  (1) 2025.02.05
[Spring] Thread Pool과 Spring Scheduler  (1) 2024.12.30