Spring : DispatcherServlet

DispatcherServlet

  • 프론트 컨트롤러 (Front Controller)
  • 클라이언트의 모든 요청을 받은 후 이를 처리할 핸들러에게 넘기고 핸들러가 처리한 결과를 받아 사용자에게 응답 결과를 보여줍니다.
  • DispathcerServlet은 여러 컴포넌트를 이용해 작업을 처리합니다.

DispatcherServlet 내부 동작흐름

img

요청이 들어오면 요청에 대한 선처리 작업을 합니다. 선처리 작업이 끝나면 HandlerExecutionChain을 결정 후 실행합니다. 실행 과정 중에 예외가 발생하면 예외처리를 하게 되고 예외가 발생하지 않았다면 뷰를 렌더링하고 요청처리를 종료합니다.

DispatcherServlet 내부 동작흐름 상세 - 요청 선처리 작업

img

Locale결정

Spring MVC지역화라는 것을 지원합니다. 지역화는 브라우저가 보내는 헤더 정보에서 언어 설정의 값들을 이용해서 그림에 나오는 Locale을 결정하게 되고 이 Locale에 설정한 값을 한국어, 일본어, 중국어, 영어 등 다양하게 보내지면서 그 부분에 따라 각각 다른 언어로 된 화면을 보여주게 처리하는 것을 말합니다.

RequestContextHolder

스레드 로컬 객체로 요청을 받아서 응답할 때까지 HttpServletRequest, HttpServletResponse 등을 Spring이 관리하는 객체 안에서 사용할 수 있도록 해줍니다.

예를 들어, 만약 나중에 Spring MVC를 사용하다가 컨트롤러가 가진 메서드 안에서 Request 객체가 필요해서 인자에다 HttpServletRequest request 를 선언해서 메서드 내에서 Request를 자유롭게 사용할 수 있습니다. 하지만 이런 방식은 Spring이 웹 기술에 종속되는 문제점을 가지고 있기 때문에 권장하는 방법은 아닙니다. (Spring이 그에 해당하는 것들을 제공하는데, 이런 것들을 가져다 쓰는게 좋습니다.)

FlashMap 복원

Spring 3에서 추가된 기능입니다. redirect로 값을 전달할 때 ?뒤에 파라미터를 입력하는 것들을 이용하게 되는데, 이렇게 사용 하다 보면 URL의 길이에 대한 제한도 있고 복잡해지게 됩니다. 이 때, FlashMap을 사용하면 redirect 될 때 딱 한 번 값을 유지시킬 수 있게 해줍니다. 즉, FlashMap을 복원은 현재 실행이 redirect 되었을 때를 위해 제공해준다고 보면 됩니다.

멀티 파트 요청

파일 업로드를 했을 경우에는 파일 정보를 읽어들이는 특수한 형태의 Request객체가 필요합니다. 이런 객체를 요청하는 것이 멀티 파트 요청이라고 볼 수 있습니다.

MultipartResolver가 멀티파트를 결정, 핸들러 결정과 실행

멀티 파트 요청이 들어오면 MultipartResolver가 파일 업로드를 처리 하기 위한 멀티 파트를 결정해줍니다. 그리고 나서 실제 요청을 처리하는 핸들러를 결정하고 실행하게 됩니다.

요청 선처리 작업시 사용된 컴포넌트

org.springframework.web.servlet.LocaleResolver

  • 지역 정보를 결정해주는 전략 오브젝트입니다.
  • 디폴트인 AcceptHeaderLocalResolverHTTP 헤더의 정보를 보고 지역정보를 설정해줍니다.

org.springframework.web.servlet.FlashMapManager

  • FlashMap객체를 조회(retrieve) & 저장을 위한 인터페이스
  • RedirectAttributesaddFlashAttribute메소드를 이용해서 저장합니다.
  • Redirect 후 조회를 하면 바로 정보는 삭제됩니다.

org.springframework.web.context.request.RequestContextHolder

  • 일반 빈에서 HttpServletRequest, HttpServletResponse, HttpSession 등을 사용할 수 있도록 합니다.
  • 해당 객체를 일반 빈에서 사용하게 되면, Web에 종속적이 될 수 있습니다.

org.springframework.web.multipart.MultipartResolver

  • 멀티파트 파일 업로드를 처리하는 전략

DispatcherServlet 내부 동작흐름 상세 - 요청 전달

img

HandlerMapping으로 HandlerExecutionChain이 결정됩니다. 그 때, HandlerExecutionChain을 발견하지 못하면 페이지가 없다는 것이기 때문에 Http 404를 전달하게 되고, 발견했다면 HandlerAdpter가 결정됩니다. 결정된 HandlerAdapter가 없다면 서버가 잘못되었다는 것이기 때문에 ServletException이 발생되고 발견했다면 문제없이 요청이 처리됩니다.

요청 전달시 사용된 컴포넌트

org.springframework.web.servlet.HandlerMapping

  • HandlerMapping구현체는 어떤 핸들러가 요청을 처리할지에 대한 정보를 알고 있습니다.
  • 디폴트로 설정되는 있는 핸들러매핑은 BeanNameHandlerMappingDefaultAnnotationHandlerMapping 2가지가 설정되어 있습니다.

org.springframework.web.servlet.HandlerExecutionChain

  • HandlerExecutionChain구현체는 실제로 호출된 핸들러에 대한 참조를 가지고 있습니다.
  • 즉, 무엇이 실행되어야 될지 알고 있는 객체라고 말할 수 있으며, 핸들러 실행전과 실행후에 수행될 HandlerInterceptor도 참조하고 있습니다.

org.springframework.web.servlet.HandlerAdapter

  • 실제 핸들러를 실행하는 역할을 담당합니다.
  • 핸들러 어댑터는 선택된 핸들러를 실행하는 방법과 응답을 ModelAndView로 변화하는 방법에 대해 알고 있습니다.
  • 디폴트로 설정되어 있는 핸들러어댑터는 HttpRequestHandlerAdapter, SimpleControllerHandlerAdapter, AnnotationMethodHanlderAdapter 3가지입니다.
  • @RequestMapping@Controller 어노테이션을 통해 정의되는 컨트롤러의 경우 DefaultAnnotationHandlerMapping에 의해 핸들러가 결정되고 그에 대응되는 AnnotationMethodHandlerAdapter에 의해 호출이 일어납니다.

DispatcherServlet 내부 동작흐름 상세 - 요청 처리

img

HandlerExecutionChain이 결정되었다면 사용 가능한 인터셉터가 있는지 찾아봅니다.

인터셉터를 간단하게 설명하자면, 일종의 필터라고 생각하면 됩니다. 필터처럼 뭔가 처리하기 전에 한번 거쳐서 지나가게 해주는 것이라고 생각하면 되겠습니다.

사용 가능한 인터셉터가 존재한다면 인터셉터preHandle을 호출해서 요청을 처리하고 핸들러가 실행됩니다. 핸들러가 실행된 후에 값을 리턴하게 되는데, 리턴하는 결과가 ModelAndView 객체이고 ModelAndView 객체가 뷰를 갖고 있지 않다면 RequestToViewNameTranslator가 동작을 하게 됩니다. 그 이외에는 인터셉터postHandle을 호출해서 요청을 처리하고 뷰 렌더링을 해서 결과를 보여주게 됩니다.

요청 처리시 사용된 컴포넌트

org.springframework.web.servlet.ModelAndView

  • ModelAndViewController의 처리 결과를 보여줄 viewview에서 사용할 값을 전달하는 클래스입니다.
  • 서블릿에서 모델을 얻고 그 모델을 JSP로 넘길 때 Request 객체를 사용했지만 Spring에서는 종속되지 않게 하기 위해 ModelAndView 객체를 제공합니다.

org.springframework.web.servlet.RequestToViewNameTranslator

  • 컨트롤러에서 뷰 이름이나 뷰 오브젝트를 제공해주지 않았을 경우 URL과 같은 요청정보를 참고해서 자동으로 뷰 이름을 생성해주는 전략 오브젝트입니다. 디폴트는 DefaultRequestToViewNameTranslator이다.

DispatcherServlet 내부 동작흐름 상세 - 예외처리

img

예외가 발생하면 HandlerExceptionResolver에 문의를 한 후, ModelAndView가 있다면 요청처리를 재개하고 그렇지 않으면 다시 예외를 던지게 됩니다.

예외 처리시 사용된 컴포넌트

org.springframework.web.servlet.handlerexceptionresolver

  • 기본적으로 DispatcherServletDefaultHandlerExceptionResolver를 등록합니다.
  • HandlerExceptionResolver는 예외가 던져졌을 때 어떤 핸들러를 실행할 것인지에 대한 정보를 제공합니다.

DispatcherServlet 내부 동작흐름 상세 - 뷰 렌더링 과정

img

뷰 렌더링 요청이 왔을 때 뷰가 String이고 ViewResolver의 구현체를 찾지 못했다면 ServletException을 발생시키게 됩니다. 뷰의 구현체를 찾았다면 렌더링을 하고 요청처리를 계속 진행합니다.

뷰 렌더링 과정시 사용된 컴포넌트

org.springframework.web.servlet.ViewResolver

  • 컨트롤러가 리턴한 뷰 이름을 참고해서 적절한 뷰 오브젝트를 찾아주는 로직을 가진 전략 오프젝트입니다.
  • 뷰의 종류에 따라 적절한 뷰 리졸버를 추가로 설정해줄 수 있습니다.

내부 동작흐름 상세 - 요청 처리 종료

img

HandlerExecutionChain이 존재한다면 인터셉터의 afterCompletion 메소드를 실행하게 됩니다. 그리고 나서 RequestHandleEvent를 발생시키고 요청이 처리됩니다. 만약 HandlerExecutionChain이 존재하지 않는다면 바로 RequestHandleEvent를 발생시키고 요청이 처리됩니다.


참고 : https://www.boostcourse.org/web326/lecture/258533/?isDesc=false

댓글남기기