스프링/3. 스프링 MVC

48. HTTP 메시지 컨버터

sdafdq 2023. 8. 13. 15:53

@ResponseBody를 사용하면

viewResolve로 view의 물리 이름을 반환하는게 아니라,

HttpMassageConverter가 작동한다.

이건 여러 종류의 컨버터가 있다.

String 같은 문자도 있고, 객체도 있고. 보통 이렇게 2종류만 쓴다.

 

응답의 경우 요청의 Accept와 컨트롤러의 반환타입등을 보고 어떤 컨버터를 쓸 지 결정한다.

 

스프링 mvc에서는 HttpEntity라는 컨버터를 쓴다. ResponseEntity와 RequestEntity 가 있다.

 

 

HttpMessageConverter인터페이스는 canRead()와 canWrite()가 있다.

이거는 읽을 수 있는건지, 또 쓸 수 있는건지 검사하는 것이다.

그리고 read()와 write()가 있다. 실제 읽고, 쓰는 것이다.

 

이렇게 또 canRead나 canWrite로 맵핑하는 듯 하다.

 

스프링 부트의 메시지 컨버터는 이 우선순위로 판단한다.

ByteArrayHttpMessageConverter 바이트단위

StringHttpMessageConverter 텍스트, String단위

MappingJackson2HttpConverter Json단위

 

이렇게가 주요하고 더 여러 개 있다.

 

일단, 아마 검사하는 순서가 저거일 것이다. 검사 기준은 메시지바디의 클래스타입(byte[], String, 객체 등)과 미디어타입이다(content-type). 미디어타입을 보고 검사하기 때문에,

메시지바디에 뭔가가 있다면 응답이든 요청이든 컨텐츠타입을 지정해주는게 중요하다.

 

byte[]의 경우 요청 미디어타입은 */*로 가능하고, 응답 미디어타입은 application/octet-stream 이렇게 표시된다.

String도 마찬가지로 요청의 타입인 */*도 가능하고, 응답의 미디어 타입은 text/plain이다.

json은 요청 미디어타입이 application/json이여야 하고, 클래스 타입은 HashMap 또는 객체여야 한다.

응답은 application/json으로 나간다.

 

http 요청이 올 경우,

컨트롤러에서 @RequestBody나 HttpEntity를 사용하면,

읽을 수 있는건지 확인하기 위해 canRead()로 컨버터들을 검사해본다.

대상의 클래스타입(인자타입, 반환타입 등)이 읽을 수 있는건지[byte[], String, 객체] 검사한다.

대상의 Content-type이 읽을 수 있는 것인지 검사한다.

만약 canRead()의 조건을 만족하면, read()를 실행하여 객체를 생성하고 그 파라미터로 넘겨준다.

 

 

응답 시에

컨트롤러에 @ResponseBody나 HttpEntity쪽으로 값이 반환된다.

먼저 쓸 수 있늕지 검사하기 위해 canWrite()가 호출된다.

대상의 클래스타입(인자타입, 반환타입 등)을 검사해본다[byte[], String, 객체].

요청이 미디어타입을 지원하는지(요청의 Accept 헤더) 검사한다.

그 전에 우리가 @RequestMapping 할 때 응답 메시지바디의 타입을 지정할 수 있었는데(produces), 먼저 그거 먼저 확인 하고 거기서 없을 경우 요청의 Accept헤더에서 검사

canWrite()의 조건을 만족하면 Write()를 호출해서 Http응답 메시지바디에 데이터를 생성해서 넣는다.

 

 

 

 

즉, 정리하자면 @RequestBody를 쓰면 메시지 바디에 있는 것이 컨버터를 거쳐서 변환되는 거다. json -> 객체 이든, text -> String이든, 

 

실제로 HttpMessageConverter 인터페이스 들어가 보면

boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);

boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);

이렇게 있음.

 

클래스랑 미디어 타입보고 검사함

 

일단 다시 정리하겠는데,

 

ByteArrayHttpMessageConverter 

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

 

StringHttpMessageConverter 

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

 

MappingJackson2HttpConverter 

클래스타입 : 객체 또는 HashMap, 미디어타입 : application/json

 

그래서 만약

application/json이 헤더의 컨텐츠타입이고,

@RequestMapping

void hello(@RequestBody String data){}

 

이렇게 하면 StringHttpMessageConverter가 선택 됨. 저걸 먼저 검사해서.

1번은 byte[]타입이 아니므로 패스,

2번은 String 타입에 모든 미디어타입을 받을 수 있으므로 저게 선택된다.

 

그래서 만약 Json으로 쓰고 싶으면 String 말고 객체나 HashMap으로 해야 Json컨버터가 선택되어 저게 실행된다.

 

 

'스프링 > 3. 스프링 MVC' 카테고리의 다른 글

50. 스프링MVC 구조 전체정리.  (0) 2023.08.13
49. 컨버터가 실행되는 위치, ArgumentResolver  (0) 2023.08.13
47. HTTP API  (0) 2023.08.13
46. 정적 리소스, 뷰 템플릿  (0) 2023.08.13
45. HTTP API JSON  (0) 2023.08.12