Interception :: Spring Framework
All HandlerMapping implementations support handler interception which is useful when you want to apply functionality across requests. A HandlerInterceptor can implement the following:
docs.spring.io
https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-config/interceptors.html
Interceptors :: Spring Framework
The XML config declares interceptors as MappedInterceptor beans, and those are in turn detected by any HandlerMapping bean, including those from other frameworks. By contrast, the Java config passes interceptors only to the HandlerMapping beans it manages.
docs.spring.io
HandlerInterceptor (Spring Framework 6.2.1 API)
postHandle Interception point after successful execution of a handler. Called after HandlerAdapter actually invoked the handler, but before the DispatcherServlet renders the view. Can expose additional model objects to the view via the given ModelAndView.
docs.spring.io
1. HandlerInterceptor란?
- HandlerInterceptor는 Spring MVC에서 제공하는 인터페이스로, HTTP 요청을 처리하기 전후에 추가 로직을 실행할 수 있도록 지원합니다.
- 컨트롤러 메서드 실행 전, 실행 후, 뷰 렌더링 후에 작업을 삽입할 수 있습니다.
- 일반적으로 인증, 권한 검사, 로깅, 성능 측정과 같은 작업에 사용됩니다.
2. HandlerInterceptor의 주요 메서드
HandlerInterceptor는 세 가지 메서드를 제공합니다.
필요한 메서드만 선택적으로 구현하면 됩니다.
메서드 | 역할 |
preHandle | 컨트롤러의 메서드가 실행되기 전에 실행. 요청을 가로채 필요한 전처리 작업 수행. |
postHandle | 컨트롤러의 메서드가 실행된 후, 뷰가 렌더링되기 전에 실행. 컨트롤러가 반환한 데이터를 수정하거나 추가 작업 수행. |
afterCompletion | 뷰 렌더링이 완료된 후 실행. 요청 처리 중 발생한 예외를 처리하거나 정리 작업 수행. |
3. HandlerInterceptor 구현 방법
3.1 기본 구현
- 인터셉터 클래스 작성
- HandlerInterceptor 인터페이스를 구현하거나 HandlerInterceptorAdapter를 상속받아 구현.
코드 예제
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.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; // 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: 뷰 렌더링 후");
}
}
3.2 인터셉터 등록
인터셉터는 Spring MVC의 WebMvcConfigurer에 등록해야 동작합니다.
Spring Web MVC - WebMvcConfigurer
코드 예제
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 {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CustomInterceptor())
.addPathPatterns("/api/**") // 적용할 경로
.excludePathPatterns("/api/login"); // 제외할 경로
}
}
3.3 컨트롤러
예제 컨트롤러를 생성함.
package com.example.handlerinterceptor.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ExampleController {
@GetMapping("/api/test")
public String testEndpoint() {
return "This is a test endpoint.";
}
@GetMapping("/api/login")
public String loginEndpoint() {
return "This is the login endpoint.";
}
}
3.4 실행
- HTTP 요청 :
- 브라우저에서 http://localhost:8080/api/test URL에 GET 요청을 보낸다.
- 인터셉터 작동 :
- preHandle : 요청이 컨트롤러에 도달하기 전에 실행된다. 이 경우 “PreHandle : 요청 처리 전”이라는 메시지가 콘솔에 출력된다.
- 컨트롤러 메서드 실행 : ExampleController의 testEndpoint() 메서드가 호출되고, “This is a test endpint.”라는 문자열이 반환된다.
- postHandle : 컨트롤러 메서드 실행이 완료된 후, 뷰 렌더링 전에 실행된다. “PostHandle : 컨트롤러 실행 후 뷰 렌더링 전”이라는 메시지가 콘솔에 출력된다.
- afterCompletion : 뷰 렌더링 후에 실행된다. “AfteCompletion : 뷰 렌더링 후” 라는 메시지가 출력된다.
- 로그인 엔드포인트 테스트
- /api/login URL 로 GET 요청을 보내며 인터셉터가 적용되지 않아야 한다.
- WebConfig에서 경로를 제외했기 때문.
- 콘솔에 인터셉터의 로그가 출력되지 않았다.
- /api/login URL 로 GET 요청을 보내며 인터셉터가 적용되지 않아야 한다.
4. HandlerInterceptor 동작 순서
- 클라이언트 요청 → preHandle 실행
- 컨트롤러 메서드 실행 → postHandle 실행
- 뷰 렌더링 완료 → afterCompletion 실행
5. HandlerInterceptor의 주요 사용 사례
5.1 인증 및 권한 검사
- 사용자가 요청한 리소스에 접근할 수 있는 권한이 있는지 확인.
- 예: 로그인 상태 확인.
코드 예제
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String authToken = request.getHeader("Authorization");
if (authToken == null || !isValid(authToken)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
return false; // 요청 중단
}
return true; // 요청 진행
}
private boolean isValid(String authToken) {
// 토큰 검증 로직
return "validToken".equals(authToken);
}
}
5.2 로깅 및 성능 측정
- 요청의 시작 시간과 종료 시간을 기록하여 처리 시간을 계산.
- 요청/응답 로그를 기록.
코드 예제
@Component
public class LoggingInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
request.setAttribute("startTime", System.currentTimeMillis());
logger.info("Request URL: " + request.getRequestURI());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
long startTime = (long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
logger.info("Request URL: " + request.getRequestURI() + " completed in " + (endTime - startTime) + "ms");
}
}
5.3 데이터 변환
- 요청 데이터나 응답 데이터를 동적으로 수정.
- 예: 헤더 추가, 요청 데이터를 가공.
코드 예제
@Component
public class HeaderModifierInterceptor implements HandlerInterceptor {
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
response.addHeader("X-Custom-Header", "CustomValue");
}
}
6. HandlerInterceptor vs Filter
특징 HandlerInterceptor Filter
특징 | HandlerInterceptor | Filter |
Spring 의존성 | Spring MVC에서 제공, Spring 컨텍스트에 통합. | Servlet 스펙에 정의, Spring과 독립적. |
적용 범위 | 컨트롤러(핸들러) 수준에서 동작. | 요청 전후 전체적인 작업(컨트롤러와 무관) 수행 가능. |
사용 목적 | Spring MVC의 컨트롤러 전후 작업에 적합. | 보안, 요청/응답 처리 필터링에 적합. |
데이터 접근 | 컨트롤러의 핸들러 메서드와 관련된 작업 수행 가능. | 낮은 수준의 HTTP 요청/응답 처리 가능. |
'Spring' 카테고리의 다른 글
HttpServletRequest 객체에서 Parameter와 Attribute의 차이 (0) | 2024.12.23 |
---|---|
Spring Web MVC - WebMvcConfigurer (1) | 2024.12.23 |
리다이렉트(Redirect)와 포워드(Forward) (0) | 2024.12.23 |
Spring Web MVC - 모델(Model) 폼 데이터 처리 (0) | 2024.12.20 |
Spring Web MVC - 세션(Session) (1) | 2024.12.20 |