HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📝
남득윤 학습 저장소
/
Spring Framework
Spring Framework
/
Web Servlet
Web Servlet
/
♻️
스프링 MVC 의 Request Flow
♻️

스프링 MVC 의 Request Flow

 
요 그림이 아주 좋다!
요 그림이 아주 좋다!
 
Spring MVC Request Lifecycle의 구조
핸들러 인터셉터의 위치가 잘못됨
핸들러 인터셉터의 위치가 잘못됨
 
Servlet Filter
  • ① 웹브라우저/ API Client에게 요청을 받음
  • ⑪ 응답을 웹브라우저/ API Client에게 전달함
 
DispatchServlet
  • ② 요청을 받아 아래의 처리를 함
    • ③HandlerMapping을 통해 요청에 대한 처리 Controller 클래스를 찾음
    • ④HandlerInterceptor에게 요청 정보와 Handler 정보를 함께 전달함 (postHandle)
      • + Argument Resolver 처리
      • + Message Converter 처리
    • ⑨ViewResolver에게 view resolving을 위임함
    • ⑩ Filter에게 응답
 
 
 
HandlerInterceptor
  • ⑤ 요청에 대한 추가적인 처리를 진행하여 DispatcherServlet에게 반환함 (preHandle)
  • ⑧ 응답에 대한 추가적인 처리를 진행하여 DispatcherServlet에게 반환함 (postHandle)
  • 9.5 뷰 리졸빙 이후에 추가적인 처리를 진행하여 DispatcherServlet 에게 반환함 (afterCompletion)
 
Controller
  • ⑥ Service Layer에 비즈니스 로직 처리를 위임함
  • ⑦ HandlerInterceptor 에 view의 path 혹은 Data를 반환함

DispatcherServlet.doDispatch 메소드

  • DispatcherServlet도 하나의 Servlet이다.
    • 부모 Servlet인 FrameworkServlet의 service 메소드를 시작으로 여러 메소드가 호출된다.
    • DispatcherServlet.doDispatch 요 메소드가 가장 중요하다.
 
 
  • 예외 처리 생략, 주요한 과정위주로 정리
  • localhost:8080 를 웹 브라우저에서 호출한 상황을 가정

③ 핸들러 매핑 과정 + 핸들러 어댑터 찾기

③ - 1 mappedHandler = this.getHandler(processedRequest);
🔻
@Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { Iterator var2 = this.handlerMappings.iterator(); while(var2.hasNext()) { HandlerMapping mapping = (HandlerMapping)var2.next(); HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
필드에 정의된 List<HandlerMapping> handlerMapping를 순회하며
notion image
요청 정보를 통해 핸들러를 찾음
WelcomPagehandlerMapping에서 ParameterizableViewController 라는 핸들러가 찾아짐
 
③ - 2 HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
🔻
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { Iterator var2 = this.handlerAdapters.iterator(); while(var2.hasNext()) { HandlerAdapter adapter = (HandlerAdapter)var2.next(); if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
비슷하게 handlerAdapters를 순회하며 핸들러 어댑터를 찾음
notion image
ParameterizableViewController를 support하는 어댑터인 SimpleControllerhandlerAdapter가 선택됨 해당 어댑터는 간단하계 핸들러가 Controller의 인스턴스라면 support함
public class SimpleControllerHandlerAdapter implements HandlerAdapter { ... public boolean supports(Object handler) { return handler instanceof Controller; } }

다음에는
mappedHandler.applyPreHandle(processedRequest, response)
HandlerInterceptor의 preHandle 호출

어댑터를 통한 핸들러 호출
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
ModelAndView 결과값
notion image

다음에는
mappedHandler.applyPostHandle(processedRequest, response, mv);
HandlerInterceptor의 postHandle호출

마지막으로 뷰 리졸빙
this.processDispatchResult(... )
🔻
this.render(mv, request, response)
🔻
view = this.resolveViewName( ... )

또 마지막으로
 
HandlerInterceptor의 afterCompletion 호출
 

 
Filter, Interceptor & AOP
인터셉터의 위치가 잘못됨
인터셉터의 위치가 잘못됨
 
웹과 관련된 공통관심사 - 서블릿 필터, 인터셉터
 
AOP는 Interceptor 보다 더 안쪽에서 동적 프록시를 활용하여 요청 및 응답에 대한 접근제어 및 기능추가를 담당함
 
notion image
 
@) 참고
damiano1027 - [Spring] Spring MVC Request Lifecycle - 그림이 이상함