개발 기록
> [Spring] Spring 은 요청을 어떻게 처리 해주고 있는 걸까? (5) HttpMessageConvert 본문

■
1. Http Message Convert 개념
Http Message Converter 를 사용하여 JSON 및 XML과 Java 개체를 마샬링 및 마샬링 해제 한다.
즉 JSON 데이터를 HTTP 메시지 바디에서 직접 읽거나 쓸 때 사용한다.
스프링은 다음의 경우에 HTTP 메시지 컨버터를 사용한다.
☞ HTTP 요청 -> @RequestBody, HttpEntity / RequestEntity
☞ HTTP 응답 -> @ResponseBody, HttpEntity / ResponseEntity
※ 기본적인 문자는 StringHttpMessageConverter, 객체는 MappingJackson2HttpMessageConverter가 동작
(1) HttpMessageConverter method 알아보기

| 메서드명 | 설명 |
| canRead(Class<?> clazz, MediaType mediaType) | Converter 가 지정된 클래스를 읽을 수 있는지 여부 |
| canRead(Class<?> clazz, MediaType mediaType) | Converter 가 지정된 클래스를 작성할 수 있는지 여부 |
| getSupportedMediaTypes() | 지원하는 미디어 유형리턴. |
| read(Class<? extends T> clazz, HttpInputMessage inputMessage) | 입력 메시지에서 주어진 유형의 객체를 읽고 반환. |
| write(T t, MediaType contentType, HttpOutputMessage outputMessage) | 출력 메시지에서 주어진 객체 작성 |
(2) 동작원리
▶ Http 요청이 들어왔을 때
1. @RequestBody or HttpEntity를 파라미터로 사용하고 있는 핸들러 메서드에 요청이 들어옴.
2. canRead()를 호출하여 대상 클래스 타입(Object 타입)을 지원하는지 확인한다.
3. Http 요청의 Content-type을 확인하여 해당 미디어 타입을 지원하는지 확인.
4. 통과했다면 read()를 통해서 객체 생성 및 반환 작업 진행
▶ Http 응답을 생성할 때
1. 핸들러 메서드에서 @ResponseBody나 HttpEntity로 값이 반환된다.
2. canWrite()를 호출하여 메시지를 쓸 수 있는지 확인한다.
3. 대상 클래스 타입을 지원하는지 확인한다.
4. Http 요청의 Accept을 확인하여 해당 미디어 타입을 지원하는지 확인. (혹은 @RequestMapping의 produces 부분 확인)
5. 통과했다면 write()를 통해서 HTTP 응답 메시지 바디에 데이터 생성
■
2. Http Message Converter 수행처
ArgumentResolver 가 핸들러 메서드의 인자값을 바인딩 할 때 Converter 를 사용한다.
@RequestBody 의 경우는 RequestResponseBodyMethodProcessor (ArgumentResolver) 에서 HttpEntity 경우에는 HttpEntityMethodProcessor (ArgumentResolver) 에서 HTTP 메시지 컨버터를 사용해서 필요한 객체를 생성한다!
아래는 RequestResponseBodyMethodProcessor 흐름만 작성했다.

(1) readWithMesageConverters 메서드
readWithMesaageConverters 메서드의 return 값인 Object 을 넘겨받는 것을 볼 수 있다.

이 Object 가 어떤 객체 인지 아래 코드를 확인해보자.
(2) AbstractMessageConverterMethodArgumentResolver.readWithMesageConverters
- HandlerMethodArgumentResolver 구현체
- Http Message Converter 를 사용해서 핸들러 메서드에 필요한 객체를 생성해준다
@Nullable
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
...
try {
....
HttpMessageConverter converter;
Class converterType;
GenericHttpMessageConverter genericConverter;
// 반복문을 통해 메시지 컨버터 반복문을 돈다.
while(true) {
...
converter = (HttpMessageConverter)var11.next();
converterType = converter.getClass();
...
genericConverter = var28;
if (genericConverter != null) {
...
// canRead()를 통해 해당 converter 가 데이터를 읽을수 있는지 검사한다.
} else if (targetClass != null && converter.canRead(targetClass, contentType)) {
// 데이터를 읽을 수 있으면 반복문을 빠져나온다.
break;
}
}
...
if (message.hasBody()) {
HttpInputMessage msgToUse = this.getAdvice().beforeBodyRead(message, parameter, targetType, converterType);
// 해당 Convert 로 read 메서드로 데이터를 읽는다.
body = genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) : converter.read(targetClass, msgToUse);
body = this.getAdvice().afterBodyRead(body, msgToUse, parameter, targetType, converterType);
} else {
body = this.getAdvice().handleEmptyBody((Object)null, message, parameter, targetType, converterType);
}
}
...
}
※ HTTP 응답 생성 시
RequestResponseBodyMethodProcessor Class 의 handleReturnValue 메서드에서 messageConverter를 호출해서 응답 결과를 만듬
■
3. Spring 에서 제공하는 Message Convert 유형
1. ByteArrayHttpMessageConverter – 바이트 배열을 변환
- @RequestBody byte[] paramter
- ex. 파일 업로드
- Response Media Type : application/octet-stream
2. StringHttpMessageConverter – 문자열을 변환.
- @RequestBody String param
- Response content-type : text/plain
3. FormHttpMessageConverter – 양식 데이터를 MultiValueMap<String, String> 으로/에서 변환
- @RequestBody MultiValueMap<String, String>
- Media Type : application/x-www-form-urlencoded
- Form-data 를 주고받을 때 사용한다.( @ModelAttribute 주로 사용)
4. MappingJacksonHttpMessageConverter – JSON을 변환
- Jackson의 ObjectMapper를 활용해서 Json과 오브젝트 사이의 변환을 지원해준다.
- content-type: application/json
5. Jaxb2RootElementHttpMessageConverter – Java 객체를 XML로/에서 변환
6. MappingJackson2HttpMessageConverter – JSON을 변환
7. ResourceHttpMessageConverter – 모든 유형의 옥텟 스트림에 대해 org.springframework.core.io.Resource를 변환
8. SourceHttpMessageConverter – javax.xml.transform.Source를 변환
9. AtomFeedHttpMessageConverter – Atom 피드를 변환
10. RssChannelHttpMessageConverter – RSS 피드를 변환
참고
'DIVE' 카테고리의 다른 글
| >함수형 프로그래밍은 무엇인가? (0) | 2024.02.26 |
|---|---|
| > 캐싱에 대해 알아보자! 캐시는 언제 써야 할까? (0) | 2024.01.05 |
| > [Spring] Spring 은 요청을 어떻게 처리 해주고 있는 걸까? (4) Convert (0) | 2023.12.08 |
| > [Spring] Spring 은 요청을 어떻게 처리 해주고 있는 걸까? (3) Request, Response Log (0) | 2023.12.08 |
| > [Spring] Spring 은 요청을 어떻게 처리 해주고 있는 걸까? (2) HandlerMethodArgumentResolver : Request Value Binding (0) | 2023.12.07 |