본문 바로가기
Back-end/Spring MVC 개념

18. HTTP message converter

by devraphy 2022. 3. 18.

0. 개요

- 지금까지 Spring MVC에서 HTTP Request와 Reponse를 처리하는 방법에 대해서 알아보았다.

 

- HTTP Request로부터 URL parameter와 message body의 데이터를 읽는 방법과  view template을 이용하여 정적/동적으로 HTML을 처리하고, HTTP message body를 이용하여  String 또는 JSON 형태로 HTTP Response를 처리하는 방법에 대해서 알아보았다.

 

- 이처럼 Spring MVC는 HTTP Request와 Response를 쉽게 처리할 수 있었다.

- 그렇다면 Spring MVC 내부적으로 어떤 과정을 거치길래 이런 것들이 가능할까?

 

- 그 중심에는 HTTP message converter가 있다.


1. HTTP message converter란?

- 이전 포스팅에서 HTTP message body의 내용을 문자 또는 객체로 변환하는 방법을 배웠다.

- 이 과정에서 Spring 내부에 존재하는 HTTP message converter를 사용된다.

- Request와 Resposne가 처리되는 과정에서, 언제 HTTP message converter가 동작하는지 알아보자.


2. HTTP message converter의 발동조건

- HTTP message converter는 다음과 같은 조건에서 실행된다.

    → @RequestBody, HttpEntity를 사용하는 경우 (= HTTP request )

    → @ResponseBody, HttpEntity를 사용하는 경우 (= HTTP response) 

 

- 위의 두 가지 조건을 해석해보면 다음과 같은 상황에서 HTTP message converter가 동작한다는 것을 말한다.

    → Request body에 담긴 JSON 또는 String 데이터를 읽는 경우 

    → Response body에 JSON 또는 String 데이터를 담아 반환하는 경우 

 

- 즉, HTTP message converter는 HTTP message body를 사용한 요청과 응답을 처리할 때 사용된다. 

 

- Request, Response에 따라 HTTP message converter가 동작하는 시점은 다음과 같다. 

b) HTTP Reqeust - @RequestBody, HttpEntity(= RequestEntity) 

- Client로부터 들어온 request의 type이 application/json 형식인 경우, HTTP message converter가 호출된다.

- HTTP message converter가 request body의 내용(= JSON)을 읽는다.

- 읽어온 JSON을 HttpEntity 객체 또는 @RequestBody와 함께 사용된 Model 객체로 변환한다. 

c) HTTP Response - @ResponseBody, HttpEntity(= ResponseEntity)

- 메서드에서 @ResponseBody 또는 HttpEntity를 사용하거나 Model 객체를 반환하는 경우, message converter가 호출된다.

- 메서드의 반환 값이 HTTP message converter에게 전달된다.

- HTTP message converter는 해당 객체를 JSON 형식으로 변환하여 Client에게 전달한다.

d) HTTP message converter의 역할

- 이처럼 HTTP message converter는 JSON을 객체로, 객체를 JSON으로 변환하는 역할을 수행한다.

- 그렇다면 Spring MVC 구조에서 HTTP message converter는 어떻게 동작하는지 알아보자.


3. HTTP message converter의 동작원리 

- 아래의 그림은 Spring MVC 구조에서 HTTP message converter가 동작하는 과정을 그린 것이다.

- 위의 그림을 토대로 어떤 과정을 거치는지 단계별로 알아보자.

 

   1. HTTP request가 들어온다.

 

   2. Spring Container는 request URL이 매핑되어 있는 Controller(= Bean)와 메서드를 조회한다.</>

 

   3. HTTP message converter는 request body의 내용을 해당 메서드에서 사용하는 객체의 형태로 변환한다.

       ex) HttpServletRequest, @RequestBody, HttpEntity(= RequestEntity), Model 등</>

 

   4. 메서드에서 비즈니스 로직을 수행한다.

       ex) HttpServletResponse, @ResponseBody, HttpEntity(= ResponseEntity), Model 등

 

   5. 메서드의 반환 값의 형태 또는 메서드에서 사용하는 annotation에 따라 Spring MVC는 반환 값의 형태를 인식한다.

       ex) 메서드의 반환 값에 따라 view name으로 인식하여 viewResolver를 수행할 수도 있다.

 

   6. 메서드에서 객체를 반환하면, HTTP message converter의 JSON 컨버터가 동작한다.

       메서드에서 문자열을 반환하면, HTTP message converter의 String 컨버터가 동작한다.

 

   7. 메서드의 반환 값에 따라 변환된 값을 HTTP message body에 담아 Client에게 전달한다. 

a) HTTP의 Accpet Header

- HTTP 요청에 Accept 헤더가 포함되어 있는 경우, Accept에 명시된 형태로 Client에게 응답을 전달해야 한다.

- Spring 내부에서는 이를 자동으로 인식하여, Accept 헤더에 명시되어있는 형태로 메서드의 반환 값을 변환한다.

 

* Accept Header란?

   - Client가 HTTP response를 받을 때, 특정 형식의 데이터로 변환해 달라고 server에게 요청 및 명시하는 것이다.

   - Accept 헤더가 존재하지 않는다면, 백엔드에서 처리하는 형식대로 응답이 전달된다.

b) HTTP message converter의 종류

- 대표적으로 Jackson과 구글에서 만든 GSON이라는 JSON converter 라이브러리가 있다.

- Spring은 Jackson을 기본으로 사용하며, 개발자의 설정에 따라 다른 라이브러리로 교체가 가능하다. 

c) 결론

- HTTP message converter 내부에는 다양한 converter를 보유하고 있다.

- 그러므로 요청 또는 응답에서 사용되는 값에 따라 다양한 형태로 변환할 수 있다. 

- 이처럼 HTTP message converter 내부에서 상황에 따라 다양한 converter를 선택할 수 있다.

- 이는 HTTP message converter가 interface이기 때문에 가능한 것이다. (= 다형성) 


4. HTTP message converter는 interface다. 

- HTTP message converter는 인터페이스로 되어있다.

- 그러므로 데이터의 형식에 따라 다양한 converter(= 구현체)를 선택하여 사용할 수 있다.

- 대표적인 HTTP message converter의 구현체는 다음과 같다.

    → StringHttpMessageConverter (= String 변환)

    → MappingJackson2HttpMessageConverter (= JSON 변환)

 

- 그렇다면 HTTP message converter의 구현체는 어떤 원리로 선택되는 것일까? 

a) HTTP message converter가 구현체를 선택하는 과정

- 우선, request 헤더의 content-type을 기준으로 데이터 타입을 검증한다.

    → request의 경우,  content-type을 읽어 데이터 타입을 검증한다.

    → response의 경우, 전달되는 데이터에 의해 content-type이 작성된다. 

* request의 경우 accept 헤더를 반드시 확인해야 한다.

 

- 그렇다면 언제 request 또는 response 헤더의 content-type을 확인할까? 

- HTTP message converter 내부에는 데이터 타입을 검증하는 로직이 존재한다.

b) Request message body를 읽는 과정 

   1. HTTP 요청이 들어온다.

 

   2. 해당 요청을 처리하는 메서드에서 @RequestBody 또는 HttpEntity를 사용하는 경우, 

      HTTP message converter의 canRead() 메서드를 호출하여 request message body의 데이터를 검증한다.

      → 이때 request의 content-type을 조회한다.

 

   3. 검증이 통과되면 read() 메서드를 호출하여 request body의 내용을 읽는다.

 

   4. 읽어온 데이터를 이용하여 메서드에서 사용하는 객체로 생성 및 반환한다.

c) Response message body를 작성하는 과정 

   1. Controller에서 @ResponseBody를 사용하거나 메서드에서 HttpEntity를 사용하는 경우, 

       HTTP message converter의 canWrite() 메서드를 호출하여 반환 값을 검증한다.

 

   2. 검증이 통과되면 write() 메서드를 호출하여 반환 값을 response message body에 담길 형태로 변환한다.

 

   3. request header의 accept 헤더와 response의 content-type을 비교하여 client가 해석 가능한지 확인한다.


5. Spring MVC에서 HTTP message converter의 위치 

- 지금까지 HTTP message converter의 동작원리와 기능에 대해서 배웠다.

- 그렇다면 Spring MVC(= Front Controller)에서 HTTP message converter는 어떻게 동작하는 것일까?

- 이에 대해서 알아보자.

 

- 우선 Spring MVC의 구조는 다음과 같다.

- 위의 Spring MVC 구조에서, HTTP message converter는 어디에 위치할까?

- HTTP message converter가 무엇에 의해 작동되는지 생각해보면 간단하다.

- 그 답은 Annoataion이다. 

 

- HTTP message converter가 작동되는 이유는 annotation 때문이다.

- annotation에 따라 반환 값을 String, 객체(JSON), view name 중 하나로 처리한다.

a) RMHA란?

- Annotation기반의 Spring MVC에서 Controller의 핵심 @RequestMapping이다.

- HTTP 메시지 컨버터는 @RequestMapping을 처리하는 Handler Adapter 내부에 위치한다.

- 그 Handler Adapter가 RequestMappingHandlerAdapter(= RMHA)다.

b) RMHA의 구조와 동작 방식

- 위의 구조에서 가장 핵심이 되는 부분은 Argument Resolver이다.

 

- 지금까지 배운 내용을 잘 생각해보자. 

- Annoatation 기반의 Controller는 메소드에서 다양한 매개변수를 사용할 수 있게 했다.

   ex) HttpServlet, Model, ModelAndView, HttpEntity, etc.

   ex) @RequestParam, @ModelAttribute, @RequestBody, etc.

 

- 이처럼 다양한 annotation을 사용하여 다양한 매개변수를 처리할 수 있는 이유가 바로 Argument Resolver 덕분이다.

- RMHA는 Argument Resolver를 호출하여 Handler(= controller)가 필요로 하는 매개변수(= 객체)를 생성하기 때문이다.

c) Request - HTTP 메시지 컨버터의 호출 과정 

- HTTP 메시지 컨버터를 사용하여 HTTP Request를 처리하기 위해 다음 과정을 거친다.

 

   1. RMHA에서 Argument Resolver를 호출한다. 

   2. Argument Resolver는 Handler가 필요로 하는 객체를 생성한 후, HTTP message converter를 호출한다. 

   3. HTTP message converter는 Request body의 데이터를 Argument Resolver가 생성한 객체에 바인딩한다.

   4. HTTP message converter는 바인딩된 객체를 Argument Resolver에게 반환한다.

   5. Argument Resolver는 반환된 객체를 최종적으로 Handler에게 전달한다.

d) Response - HTTP 메시지 컨버터의 호출 과정

- HTTP Response는 ReturnValueHandler(= RVH)에 의해 작성된다. 

- RVH는 메서드의 반환 값을 응답 데이터(= 객체)의 형식에 맞게 변환하는 역할을 수행한다.

- RVH를 통해 response message가 작성되기까지 다음과 같은 과정을 거친다.

 

    1. Handler에서 비즈니스 로직을 완료하고 결과 값을 반환한다.

    2. 반환된 결과 값은 RVH에게 전달된다.

    3. RVH는 Handler의 annotation 정보 또는 사용하는 매개변수(= 객체)에 따라 결과 값을 변환한다. 

    4. HTTP message converter를 호출하여 변환된 결과 값을 전달한다.

    5. HTTP message converter는 Response 메시지를 생성하고, 변환된 결과 값을 Response body에 담는다. 


6. 요약정리 - HTTP 메시지 컨버터의 역할과 기능

- HTTP message converter는 message body를 사용하는 request와 response를 처리한다.

 

- HTTP message converter는 개발자가 비즈니스 로직 작성에만 집중할 수 있도록, Request body를 객체로

  또는 객체를 Response body로 변환하는 역할을 수행한다.

 

- 그러므로 개발자는 Request body를 읽거나 Response body를 작성하는 로직에 관여하지 않는다.

 

- 여기까지 HTTP 메시지 컨버터에 대해 알아보았다.

'Back-end > Spring MVC 개념' 카테고리의 다른 글

Spring MVC를 마치며  (0) 2022.03.21
17. Response 처리방법  (0) 2022.03.17
16. Request - JSON 조회방법  (0) 2022.03.16
15. Request - message Body 조회방법  (0) 2022.03.15
14. Request - URL parameter 조회방법  (0) 2022.03.14

댓글