DispatcherServlet 이란 Presentation Layer 전면에서 모든 HTTP 요청을 중앙집중식으로 처리하는 Front Controller 패턴을 적용한 Servlet 이다.
ServletContainer 가 받은 클라이언트 요청의 공통적인 작업은 DispatcherServlet 이 처리하고 그 외 작업은 적절한 Controller 에게 위임한다.
즉, Controller 로 향하는 모든 웹 요청의 진입점으로써 요청을 처리하고 결과를 클라이언트에게 응답한다.
Front Controller 패턴
Front Controller 패턴은 모든 요청을 처리하는 하나의 대표 Controller 를 배치하는 패턴을 의미한다.
Front Controller 는 모든 요청의 진입점이 되어 요청을 일괄적으로 처리할 수 있다. Spring 에서는 DispatcherServlet 이 Front Controller 역할을 한다.
Dispatcher Servlet 동작 과정
ServletContainer 가 받은 요청이 HttpServletRequest 로 가공되어DispatcherServlet 에게 전달된다. 이때 MultipartResolverLocaleResolverThemeResolver 인터페이스의 구현체가 요청을 분석한다.
요청을 HandlerMapping 에게 위임하여 요청을 처리할 Handler(Controller) 를 탐색한다.
HandlerAdapter 에서 Handler 를 처리할 수 있는 HandlerAdapter 를 탐색한다.
HandlerAdapter 에 정의된 Handler 메서드를 호출하여 비즈니스 로직을 수행한다.
Handler 가 viewName 혹은 ModelAndView 를 반환한다.
ViewResolver 에게 viewName 혹은 ModelAndView 를 전달하여 해당하는 View 반환한다.
DispatcherServlet 은 View 에게 Model 을 제공하여 클라이언트에게 응답할 화면을 생성한다.
DispatcherServlet 은 View 의 결과를 HttpServletResponse 객체를 통해 클라이언트에게 응답한다.
코드 상에서 살펴보기
ServletContainer 가 HttpServletRequest 와 HttpServletResponse 를 생성하여 DispatcherServlet 에게 전달할 때 doService() 메서드가 호출된다.
이는 Handler 를 찾고 요청을 위임하는 등의 역할을 하는 doDispatch() 메서드로 연결된다.
먼저 요청을 처리할 수 있는 Handler 를 찾기 위해 getHandler() 메서드를 호출한다.
찾은 Handler 를 실행하기 위한 HandlerAdapter 를 찾기 위한 getHandlerAdapter() 메서드가 호출된다.
Handler 를 실행하기 전 applyPrehandle() 메서드를 통해 Interceptor 의 preHandle() 메서드를 실행한다. 이때 HandlerInterceptor 를 구현한 빈이 호출된다. 주로 인증을 위해 많이 사용한다.
Interceptor 를 통과한 후 Handler 의 메서드를 실행하기 위해 HandlerAdapter 의 handle() 메서드가 호출된다.
Handler 가 실행된 이후 Interceptor 의 postHandle() 이 실행된다. 이때 Handler 가 반환한 ModelAndView 에 대한 후처리를 applyPostHandle() 메서드가 수행하는데, @Controller 의 경우 ModelAndView 를 반환하고 @RestController 의 경우 null 을 반환하여 View 가 렌더링되는 과정을 생략하게 된다.
처리된 ModelAndView 는 processDispatchResult() 라는 메서드를 통해 렌더링된다.
해당 메서드 내부에서 render() 메서드를 호출하는데 이때 viewName 을 View 객체로 변환하는 resolveViewName() 메서드가 호출된다.
이후 반환받은 View 객체의 render() 메서드 호출을 통해 View 에 Model 을 렌더링하는 과정을 거치게된다.
마지막으로 Interceptor 의 triggerAfterCompletion() 메서드를 실행하면 요청에 대한 처리가 전부 마무리된다.
정리
DispatcherServlet 을 간단히 알아보고 실제 내부 동작 과정을 살펴봤다. 전체적인 흐름을 정리하면 위 그림과 같다.