디스패처 서블릿(DispatcherServlet)이 어떻게 동작하는지 알아보려면, 인터셉터(Interceptor)를 활용하여 요청이 디스패처 서블릿을 통해 처리되는 과정을 추적할 수 있습니다. HandlerInterceptor는 스프링에서 제공하는 인터페이스로, 특정 요청이 디스패처 서블릿에 도달하기 전과 후의 과정을 가로채서 로깅하거나, 요청 흐름을 수정하는 등의 작업을 수행할 수 있습니다.
이를 통해 디스패처 서블릿이 실행되기 전후의 로직 흐름을 모니터링하고 확인할 수 있습니다.
1. HandlerInterceptor 인터페이스
HandlerInterceptor는 세 가지 메서드를 제공합니다:
- preHandle(): 컨트롤러가 호출되기 전에 실행됩니다. 디스패처 서블릿이 요청을 컨트롤러로 전달하기 전에 이 메서드가 호출됩니다.
- postHandle(): 컨트롤러가 호출된 후, 뷰를 렌더링하기 전에 호출됩니다. 이때는 요청이 컨트롤러를 거친 후 결과를 처리하기 전에 디스패처 서블릿을 통해 호출됩니다.
- afterCompletion(): 뷰 렌더링 후, 요청 처리가 완전히 완료된 후 호출됩니다. 즉, 모든 처리가 끝난 뒤에 실행됩니다.
2. 인터셉터 등록 방법
스프링에서 인터셉터를 사용하려면 WebMvcConfigurer에서 인터셉터를 등록해야 합니다.
3. 구현 예시
아래 예시는 디스패처 서블릿의 요청 흐름을 추적하는 간단한 로그 인터셉터를 구현한 것입니다.
1) 인터셉터 구현
package com.taehun.interceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class DispatcherLoggingInterceptor implements HandlerInterceptor {
// 컨트롤러가 실행되기 전에 호출 (전처리)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Interceptor: preHandle - Request URI: " + request.getRequestURI());
return true; // true를 반환하면 요청이 계속 진행됩니다.
}
// 컨트롤러가 실행된 후, 뷰가 렌더링되기 전에 호출 (후처리)
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor: postHandle - Handler executed, preparing view");
}
// 뷰가 렌더링된 후 호출 (응답 완료 후 처리)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("Interceptor: afterCompletion - Request completed");
}
}
2) 인터셉터 등록
WebMvcConfigurer를 구현하여 인터셉터를 등록해야 합니다. 아래는 WebConfig
클래스에 인터셉터를 등록하는 방법입니다.
package com.taehun.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.taehun.interceptor.DispatcherLoggingInterceptor;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private DispatcherLoggingInterceptor dispatcherLoggingInterceptor;
// 인터셉터 등록
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(dispatcherLoggingInterceptor)
.addPathPatterns("/**"); // 모든 경로에 대해 인터셉터 적용
}
}
3) 로그를 통한 흐름 확인
이제 인터셉터가 등록되었으므로, 특정 요청을 보낼 때마다 콘솔에 로그가 출력됩니다. 예를 들어, http://localhost:8080/myhello
로 요청이 들어올 경우 다음과 같은 순서로 로그가 출력됩니다:
- preHandle():
- 디스패처 서블릿이 요청을 컨트롤러로 보내기 전에 호출.
- 로그:
Interceptor: preHandle - Request URI: /myhello
- postHandle():
- 컨트롤러가 실행되고 뷰가 렌더링되기 전에 호출.
- 로그:
Interceptor: postHandle - Handler executed, preparing view
- afterCompletion():
- 뷰가 클라이언트에게 렌더링된 후, 모든 요청 처리가 완료된 후 호출.
- 로그:
Interceptor: afterCompletion - Request completed
4. DispatcherServlet의 요청 처리 흐름
- 클라이언트 요청 → 디스패처 서블릿 → preHandle() → 컨트롤러 → postHandle() → 뷰 렌더링 → afterCompletion()
이를 통해 디스패처 서블릿이 요청을 처리하는 과정을 추적할 수 있으며, 각 메서드에서 필요한 로깅이나 요청 수정 작업을 수행할 수 있습니다.
5. 인터셉터를 활용한 추가 작업
인터셉터는 단순한 로깅뿐만 아니라 다양한 기능을 구현할 수 있습니다:
- 인증 및 인가: 사용자가 로그인했는지 확인하고, 로그인하지 않았다면 요청을 중단하고 로그인 페이지로 리다이렉트.
- 요청 데이터 검증: 요청에 포함된 데이터를 검증하고 잘못된 요청을 차단.
- API 로깅: 모든 API 요청을 로깅하여 추후 분석에 활용.
요약
- 인터셉터는 디스패처 서블릿이 요청을 처리하기 전과 후, 그리고 뷰가 렌더링된 후에 요청 흐름을 가로채고 작업을 수행할 수 있는 도구입니다.
- 이를 통해 디스패처 서블릿의 동작 과정을 추적하고, 로깅이나 요청 처리를 제어할 수 있습니다.
- preHandle(): 컨트롤러 실행 전에 실행되며, 요청을 중단하거나 계속 진행할지 결정.
- postHandle(): 컨트롤러 실행 후, 뷰가 렌더링되기 전 실행.
- afterCompletion(): 모든 요청 처리 완료 후 실행, 주로 리소스 해제 등에 사용.
1. preHandle() - 핸들러 어댑터 호출 전
- 설명:
- preHandle 메서드는 디스패처 서블릿이 핸들러 어댑터를 호출하기 전에 실행됩니다.
- 여기서 핸들러는 주로 컨트롤러 메서드를 가리킵니다.
- 이 단계에서 요청을 가로채어 처리할 수 있으며, 요청을 계속 진행할지 멈출지를 결정할 수 있습니다.
preHandle()
에서true
를 반환하면 요청 처리가 계속 진행되고,false
를 반환하면 요청 처리가 중단됩니다.
- 호출 시점: 컨트롤러 메서드가 실행되기 전에 호출됩니다.
- 예시:
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle: 핸들러 어댑터 호출 전에 실행"); return true; // 계속 진행 }
2. postHandle() - 뷰 리졸버 호출 전
- 설명:
- postHandle 메서드는 컨트롤러 메서드가 실행된 후에 호출됩니다.
- 하지만 아직 뷰가 렌더링되기 전, 즉 뷰 리졸버가 호출되기 전에 실행됩니다.
- 이 단계에서는 컨트롤러에서 반환된 ModelAndView 객체에 접근하여 추가적으로 모델 데이터를 수정하거나 뷰를 변경할 수 있습니다.
- 호출 시점: 컨트롤러가 실행된 후, 뷰 리졸버가 호출되기 전에 실행됩니다.
- 예시:
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle: 컨트롤러 실행 후, 뷰 리졸버 호출 전 실행"); }
3. afterCompletion() - 뷰가 렌더링된 후
- 설명:
- afterCompletion 메서드는 뷰가 클라이언트에게 렌더링된 후에 호출됩니다.
- 이 메서드는 요청이 완전히 끝난 후 호출되므로, 요청 처리 과정에서 사용된 리소스 해제, 로깅, 에러 처리 등의 작업을 수행할 수 있습니다.
- 호출 시점: 뷰가 렌더링된 후, 즉 요청이 완전히 완료된 후 호출됩니다.
- 예시:
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion: 뷰가 렌더링된 후 실행"); }
전체 흐름 정리:
- preHandle(): 핸들러 어댑터 호출 전에 실행.
- 컨트롤러 호출을 가로채기 전의 작업 (인증, 권한 체크 등).
- postHandle(): 뷰 리졸버 호출 전에 실행.
- 컨트롤러가 실행된 후, 결과를 가공하거나 뷰를 변경하는 작업.
- afterCompletion(): 뷰가 렌더링된 후 실행.
- 요청 완료 후의 마무리 작업 (리소스 해제, 로깅, 에러 처리 등).
이를 통해 디스패처 서블릿의 동작을 구체적으로 추적하고, 요청 처리 중 원하는 타이밍에 추가 작업을 할 수 있습니다.
'Spring Framework' 카테고리의 다른 글
Enable MVC Configuration (0) | 2024.10.16 |
---|---|
리졸버(Resolver) (0) | 2024.10.16 |
콘텐츠 협상(Content Negotiation) (0) | 2024.10.15 |
디폴트 서블릿(Default Servlet) (0) | 2024.10.15 |
ResponseEntity (1) | 2024.10.14 |