https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-config/interceptors.html
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 (0) | 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 |