쌓고 쌓다

HTTP 메시지 컨버터? 본문

프로그래밍/spring

HTTP 메시지 컨버터?

승민아 2023. 8. 13. 14:17

HTTP 메시지 바디를 읽거나 쓰는경우 "HTTP 메시지 컨버터"가 동작한다.

 

예를 들어 @ResponseBody를 사용하여 "hello"를 리턴했다고 하자.

출처: 인프런 - 김영한

이 어노테이션은 메시지 바디에 "hello"를 그대로 넣을 수 있는 어노테이션이다.

이때 뷰 리졸버는 동작하지 않고 "HTTP 메시지 컨버터"가 동작한다.

 

언제 "HTTP 메시지 컨버터"가 동작할까? (Spring MVC에서)

  • 요청 : @RequestBody, HttpEntity(또는 RequestEntity)
  • 응답 : @ResponseBody, HttpEntity(또는 ResponseEntity)

 

어떤 "HTTP 메시지 컨버터"가 동작할까?

위의 그림에서 정확히는 "StringHttpMessageConverter"가 사용된다.

이렇게 다양한 메시지 컨버터가 존재하는데

어떤 메시지 컨버터를 사용할지는 대상 클래스 타입과 미디어 타입을 체크하여 결정한다.

public interface HttpMessageConverter<T> {
    boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
    boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
    ...
}

 

주요 기본 HTTP 메시지 컨버터

0 순위 = ByteArrayHttpMessageConverter
1 순위 = StringHttpMessageConverter
2 순위 = MappingJackson2HttpMessageConverter

메시지 컨버터 순위에 따라 돌며 클래스 타입, 미디어 타입을 체크한다.

 

1. ByteArrayHttpMessageConverter

byte[] 데이터를 처리하는 컨버터이다.

  • 클래스 타입 : byte[]
  • 미디어 타입 : */*

 

2. StringHttpMessageConverter

String 문자로 데이터를 처리한다.

  • 클래스 타입 : String
  • 미디어 타입 : */*

 

요청과 응답 예를 보고 감을 잡아보자.

@ResponseBody
@PostMapping("/request-body-string-v5")
public String requestBodyStringV4(@RequestBody String messageBody) throws IOException {
    log.info("messageBody = {}", messageBody);
    return "ok";
}

문자열 데이터가 들어오면 StringHttpMessageConverter가 동작하여

변수 messageBody에 데이터가 String으로 담기게된다.

응답으로 문자열 "ok"가 그대로 바디에 담겨 온다.

 

 

3. MappingJackson2HttpMessageConverter

JSON 데이터를 처리한다.

  • 클래스 타입 : 객체 또는 HashMap
  • 미디어 타입 : application/json 관련
@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData data){ // 요청: 메시지 컨버터를 통해 JSON -> HelloData
    return data; // 응답: HelloData 객체가 http메시지 컨버터를 통해 JSON으로 바뀌고 이 JSON이 응답으로 나간다.
    // 요청부터 응답 사이클 : JSON -> 객체 -> JSON
}

JSON으로 {"username":"LSM", "age":7}을 요청으로 보내고

응답으로 JSON을 받아보자.

 

 

이제 메시지 컨버터 감이 잡힌다.

메시지 body를 이용하는 요청과 응답시에 변환해주는 과정을 "HTTP 메시지 컨버터"가 해주는것이다.

 

요약해서 HTTP 요청과 응답에서 어떻게 동작하는지 이해하자.

HTTP 요청 데이터 읽기

  • HTTP 요청이 오고, 컨트롤러에서 @RequestBody, HttpEntity 파라미터를 사용한다.
  • 메시지 컨버터가 메시지를 읽을 수 있는지 확인차 canRead()를 호출한다.
    • 이때 대상 클래스 타입과 미디어 타입을 따진다.
  • canRead()를 만족하면 read()를 호출하여 객체를 생성하고 반환해준다.

 

HTTP 응답 데이터 생성

  • 컨트롤러에서 @ResponseBody, HttpEntity로 값을 반환한다.
  • 메시지 컨버터가 메시지를 쓸 수 있는지 확인차 canWrite()를 호출한다.
    • 이때 대상 클래스 타입과 HTTP 요청의 Accept 미디어 타입을 지원하는가 따진다.
    • @RequestMapping의 produces와 일치하는가?
  • canWrite()를 만족하면 write()를 호출해서 HTTP 응답 메시지 바디에 데이터를 넣는다.

 

 

어디서 "HTTP 메시지 컨버터"가 동작할까?

출처: 인프런 - 김영한

먼저 Argument Resolver가 뭔지 알자.

어노테이션 기반의 컨트롤러는 다양한 파라미터를 사용할 수 있었다.

유연한 파라미터 처리가 가능한 이유가 Argument Resolver 덕분이다.

 

RequestMapping 핸들러 어댑터는 Argument Resolver를 이용해 컨트롤러에서 필요로하는 파라미터의 값을 생성한다.

이 생성된 파라미터 값들을 가지고 컨트롤러를 호출하여 실행하는 것이다.

 

응답의 경우도 마찬가지이다.

@ResponseBody, HttpEntity를 처리하는 ReturnValueHandler가 있는데 이곳에서 

HTTP 메시지 컨버터를 호출해 응답 결과를 만든다.

Comments