새소식

반응형
Java/Spring

HttpMessageConverter, DispatcherServlet 동작원리

  • -
반응형

HttpMessageConverter 란?

클라이언트(웹브라우저) 측에서 데이터를 HTTP Request Body 로 넘길때 서버측에서 DTO 같은 객체에

변환하기 위해 사용한다. 또한 반대로 서버측에서 HTTP Response Body 로 응답 데이터를 클라이언트로 전달할 때

사용한다.

 

보통 서버측에서 받을때 주로 사용하는 건 @RequestBody 어노테이션과 클라이언트로 응답 데이터를 넘길때

@ResponstBody 를 사용한다.

 

Spring MVC 요청/응답 과정

 

1. 클라이언트로부터 HTTP 요청이 들어오면 Front Controller 라고 불리우는 Dispatcher Servlet 이 받는다.

    * 클라이언트의 요청은 Front Controller 라고 하는 Dispatcher Servlet 이 모든 요청을 받아 처리한다.

2. Dispatcher Servlet 은 HandlerMapping 을 통해 요청에 적절한 HandlerAdapter 를 찾는다.

3. HandlerAdapter 는 클라이언트의 요청에 적절한 Controller 를 찾아 데이터를 넘겨주게 되는데 이때

    HttpMessageConverter 가 변환시켜 넘긴다.

  • HandlerAdapter는 해당 작업을 HandlerMethodArgumentResolver 에게 위임한다.
  • HandlerMethodArgumentResolver 는 HttpMessageConverter 에게 Http Request Body 의 데이터를
    특정 타입의 객체로 변환 요청한다.
  • HttpMessageConverter 는 Http Request Body 의 데이터를 특정 타입 객체로 변환한다.
  • HandlerMethodArgumentResolver 는 HttpMessageConverter 로 부터 변환된 객체를 전달받아
    HandlerAdapter 에게 전달한다.
  • HandlerAdapter 는 전달 받은 변환 객체를 핸들러 메서드에게 전달한다.

4. 클라이언트 요청에 맞게 Controller 는 데이터 처리 후 HandlerAdapter 에게 전달한다.

5. HandlerAdapter 는 DispatcherServlet 에게 Controller 전달 데이터와 View 이름을 전달한다.

6. DispatcherServlet 은 전달받은 View 이름을 ViewResolver 에게 넘겨 적절한 View 찾아 데이터와 함께
    화면을 보여준다.

 

HttpMessageConverter 구현체

HttpMessageConverter 는 기본적으로 아래의 구현체가 활성화 되어 있다.

  • ByteArrayHttpMessageConverter
  • StringHttpMessageConverter
  • ResourceHttpMessageConverter
  • SourceHttpMessageConverter
  • FormHttpMessageConverter
  • Jaxb2RootElementHttpMessageConverter
  • MappingJackson2HttpMessageConverter
  • MappingJacksonHttpMessageConverter
  • AtomFeedHttpMessageConverter
  • RssChannelHttpMessageConverter

 

Controller 에 @RequestBody 어노테이션을 사용했다고 가정해보자.

 

전달된 Http Request Body 데이터를 위 HttpMessageConverter 구현체 종류를 순서대로

체크해서 HttpMessageConverter 구현체 클래스 타입을 지원하는지와 Header 의 Content Type을

지원하는지 2가지를 모두 확인한다.

 

두가지 조건을 만족하는 경우 만족한 클래스의 객체로 변환시키고 만족하는 클래스가 없을 경우

예외가 발생한다.

 

 

DispatcherServlet 동작원리

출처 : https://yejun-the-developer.tistory.com/4

위 이미지를 보게 되면 DispatcherServlet 은 Servlet 인터페이스를 구현하여 아래와 같은 순서이다.

Servlet.class > GenericServlet.class > HttpServlet.class > FrameworkServlet.class > DispathcerServlet.class 의 doService() 메서드 실행

 

아래 내용을 보기전 알아두어야 할 점은 스프링 어플리케이션이 실행될 때 DispatcherServlet 을 자동으로 등록하고

@ComponentScan 어노테이션에 의해 @RequestMapping 어노테이션이 존재하는 Handler 들을 모두 매핑시킨다.

 

이러한 Handler 들을 매핑시킨게 DispatcherServlet 에 의해 적절한 Controller 를 찾는 HandlerMapping 이다.

스프링에서 따로 설정하지 않는 이상 기본 HandlerMapping 클래스는

RequestMappingHandlerMapping 클래스 이다.

실제로 아래 이미지는 RequestMappingHandlerMapping 클래스가 아래와 같이 Map 형식의

RequestMapping 어노테이션의URL을 매핑시킨 내용이다.

HashMap<Key, Value>(Key : 요청정보, Value : 처리할 대상)

 

Spring Boot 의 @ComponentScan 어노테이션은 main 메소드가 존재하는 클래스의

@SpringBootApplication 어노테이션에 존재한다.

 

Servlet.class(인터페이스)

 

GenericServlet.class(추상클래스)

 

HttpServlet.class

 

FrameworkServlet.class

 

DispatcherServlet.class

클라이언트 요청에 의해 Servlet 의 doService() 가 호출되는데 doService() 메서드는 아래 내용과 같이 doDispatcher에게

위임한다고 설명되어 있다.

"Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}"

 

 

 

doDispatch() 메서드에서는 getHandler(HttpServletRequest) 메서드를 통해 적절한 Handler 를 찾는다.

적절한 Handler 는 @ComponentScan 어노테이션에 의해 매핑된 @RequestMapping 의 HanlderMapping 에서 찾습니다.

 

알맞는 HandlerMapping 을 이용해 적절한 HandlerAdapter 를 찾는다.

 

적절한 HandlerAdapter 의 handler() 메서드를 호출하면 실제 Controller를 통한 비즈니스 로직이 수행된다.

수행된 비즈니스 로직은 ModelAndView 객체를 반환하는데 View 이름과 가공된 데이터가 들어있다.

 

ModelAndView 객체인 가공된 데이터와 View 이름을 가지고 ViewResolver 에게 넘겨 실제 View 를 리턴받는다.

ModelAndView mv 에 대한 내용 처리 후 render() 메서드를 통해 실제 View 를 처리한다.

 

 

View 클래스의 render() 메서드를 통해 View 생성 및 클라이언트에게 반환한다.

 

요약

 

1. Dispatcher Servlet(Front Controller) 클래스가 클라이언트의 요청을 받는다.

 

2. getHandler() 메서드를 통해 HandlerMapping 리스트 중 요청에 맞는 Handler 를 가져온다.

HandlerMapping 이란?
@Controller 의 @RequestMapping 이 존재하는 모든 URL 값을 HashMap<요청정보, 처리할 대상> 으로
Handler 를 만들어 매핑 시켜놓은 값이다.
각각의 @RequestMapping 값들이 Handler 가 되며, 이러한 Handler 를 매핑 시켜놓은게 Handler Mapping 이다.

 

3. Handler 를 찾아 로직을 실행시킬 HandlerAdapter 를 찾기 위해 getHandlerAdapter() 메서드를 호출한다.

 

4. HandlerAdapter 는 handler() 메서드를 호출하여 Controller 의 요청 처리를 수행한다.

 

5. 반환된 ModelAndView 객체를 받는다.

반환된 ModelAndView 객체에서 Controller 의 View Name 을 applyDefaultViewName() 메서드를 통해

설정한다.

 

6~8. processDispatcherResult(), render() 메서드를 호출하여 View 객체 생성 후 HTML 반환한다.

 

processDispatcherResult() 메서드에서 render() 메서드를 호출한다.

ViewResolver 의 resolverViewName() 메서드를 호출하여 Handler(Controller) 객체에서

반환된 View 이름에 해당하는 View Object 를 가져온다.

 

View 객체를 설정 후 View 객체의 render() 메서드를 통해 HTML 을 반환한다.

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.