나만보는페이지

[Spring MVC] DispatcherServlet 요청 처리 과정 본문

spring

[Spring MVC] DispatcherServlet 요청 처리 과정

pplenty 2020. 4. 10. 00:00

[Spring MVC] DispatcherServlet

boot-2.2.6(spring-5.2.5) 기준으로 작성하였다.

스프링 웹 어플리케이션을 개발하면서 항상 나의 시작점은 @Controller 였다.
쿼리 스트링으로 id=pplenty 작성하여 호출하면 당연하게 메서드에 매개변수 String id 를 추가하여 전달 받는다.
Http 요청을 파싱하고 전달인자를 만들어 메서드를 호출해주는 것은 어떤 방식으로 이루어질지가 궁금하다.
브라우저를 통한 HTTP 요청이 내가 작성한 Controller 의 특정 메서드까지 도달하기 까지의 과정을 분석해보자.

DispatcherServlet

스프링은 모든 요청을 하나의 서블릿(DispatcherServlet)으로 받아서, 처리할 수 있는 핸들러에게 요청을 전달해준다. 이러한 방식을 Front Controller 패턴 이라 부른다. 또한 핸들러로부터 반환된 값을 기반으로 HTTP 응답을 만드는 View 를 찾아 데이터를 전달한다.

스프링 MVC 의 핵심 프로세스를 담고 있는 DispatcherServlet 에 대해 정리해보기로 한다.
클래스다이어그램

용어 정리

스프링은 네이밍이 잘 되어 있어 이름만으로도 어느 정도 역할을 유추해낼 수 있다. HTTP 요청을 처리하는 과정에서 자주 등장하는 인터페이스에 대해 먼저 정리해보았다.

  • HandlerMapping : HTTP 요청과 핸들러를 매핑 해주는 역할을 한다. getHandler 메서드를 통해 HTTP 요청에 매핑된 핸들러를 가져올 수 있다.
    대표적인 구현체로는 RequestMappingHandlerMapping 가 있다. ApplicationContext 가 refresh 되는 과정에서 생성 및 초기화된다.

  • Handler : HTTP 요청을 핸들링하는 역할을 한다. @Controller 클래스의 @RequestMapping 이 붙은 메서드가 여기에 포함된다.

  • HandlerAdapter : Handler method 를 실행(invoke)해주는 역할을 한다. ModelAndView 객체를 반환한다.

  • HandlerMethodArgumentResolver : HandlerMethod 의 파라미터와 HTTP 요청 객체를 분석하여, Handler 가 실행될 때 전달되어질 Argument 를 찾는다.

  • HandlerMethodReturnValueHandler : HandlerAdapter 내부에서 Handler 가 반환하는 값을 처리하는 역할을 한다.
    ModelAndView 객체를 만들거나, 경우에 따라서는 HTTP 응답을 직접 응답하기도 한다.

  • Model : 핸들러에서 처리/가공되어 View 로 전달되는 데이터를 담은 객체이다.

  • View : model 의 값을 인자로 받아, HTTP 응답을 만들어 응답한다.(render)

  • ModelAndView : LinkedHashMap 를 상속받은 ModelMap 과 View(또는 view name) 의 정보를 담고 있다.

  • ViewResolver : view name 을 해석해 어떤 View 로 응답을 만들지 결정한다.

HTTP 요청 처리 과정

doDispatch
당연한 얘기지만 DispatcherServlet 도 서블릿 구현체이기 때문에 doService 를 @Override 하고 있고, 요청/응답 객체를 전달 인자로 doDispatch 함수를 호출한다.
doDispatch 함수에 HTTP 요청을 처리하여 응답하는 모든 과정이 담겨 있다. 처리하는 과정 아래와 같이 주요한 부분을 순서대로 정리해보았다.
실제 코드는 스프링 깃헙 에서 볼 수 있다.(물론 스프링 프로젝트에서 직접 열어봐도 된다.)

  1. HandlerExecutionChain getHandler(HttpServletRequest request)
    HTTP 요청을 핸들링할 핸들러를 HandlerMapping 을 통해 조회한다. HandlerMapping 구현체 중 하나가 RequestMappingHandlerMapping 이다.
    요청된 URL 에 매칭되는 핸들러(Handler)와 인터셉터 정보(HandlerInterceptor[])로 HandlerExecutionChain 을 생성하여 반환한다.
    핸들러

  2. HandlerAdapter getHandlerAdapter(Object handler)
    핸들러를 실행시켜줄 적절한 어댑터를 가져온다.
    핸들러어댑터

  3. boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response)
    핸들러 체인에 등록된 인터셉터들의 preHandle 함수를 실행한 뒤, false 가 나오면 바로 함수를 반환한다.
    인터셉터 전처리

  4. ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
    어댑터를 통해 핸들러를 실행한고 ModelAndView 를 반환한다. 경우에 따라서는 이 부분에서 응답이 완료 되는 경우도 있다.
    예를 들면 @ResponseBody 를 포함한 컨트롤러의 경우, RequestResponseBodyMethodProcessor(HandlerMethodReturnValueHandler 의 구현체) 에 의해 OutputStream 으로 직접 응답하고 null 을 반환한다.
    핸들러 실행

  5. void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv)
    핸들러 체인에 등록된 인터셉터들의 postHandle 함수를 실행한다. 핸들러 실행후 반환된 ModelAndView 도 함께 인자로 받는다.
    인터셉터 후처리

  6. void processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException)
    결과를 처리하는 부분이다. 핸들러 실행으로 반환된 view 가 존재할 경우, 이 부분에서 뷰 종류를 판별하고 뷰를 이용해 응답(render)한다.
    결과 처리

Comments