[6] 스프링 MVC (12) - HTTP 메시지 컨버터 원리 (+Argument Resolver / ReturnValue Handler)

HTTP 메시지 컨버터
[ 역할 ]

HTTP response로 뷰가 아닌 데이터를 담아서 보내는 경우
viewResolver대신 HttpMessageConventer가 동작 (다양한 종류의 컨버터가 존재함)
- 기본 문자 -->
StringHttpMessageConverter가 처리
- 기본 객체 -->
MappingJackson2HttpMessageConverter가 처리
HTTP request가 오거나 HTTP response로 데이터를 body에 담아서 보낼 때 우리는 별 생각 없이 했다
--> 스프링이 모든 메시지 내용을 알맞게 변환해주었기 때문
--> 이러한 역할을 해주는 것이 바로 HTTP 메시지 컨버터
[ 사용 원리 ]
( HTTP 메시지 컨버터 핵심 코드 )

canRead() / canWrite() --> 메시지 컨버터가 해당 클래스, 미디어타입을 지원하는지 체크
read() / write() --> 메시지 컨버터를 통해서 메시지를 읽고 쓰는 기능
( HTTP 컨버터가 사용되는 경우 )
스프링 MVC는 다음의 경우에 HTTP 메시지 컨버터를 적용
: 메시지 컨버터가 필요한 경우 --> HTTP request Body에 데이터가 있는 경우
HTTP 요청 : @RequestBody / HttpEntity(RequestEntity)
HTTP 응답 : @ResponseBody / HttpEntity(ResponseEntity)
( 주요 메시지 컨버터 )

메시지 컨버터는 2가지를 통해 조합해서 매칭
요청 파라미터의 클래스 타입
HTTP request 특정 필드(Content-Type / Accept)의 미디어 타입
- ex)
요청 파라미터로 객체가 왔는데, 미디어 타입이 application/json이 아니다 ?
--> 매핑되는 컨버터가 없음 --> 오류 발생
( HTTP 요청 / HTTP 응답 흐름 )
- HTTP 요청 흐름
HTTP Request 요청
Controller에서 @RequestBody 혹은 HttpEntity 파라미터를 사용
메시지 컨버터가 메시지를 읽을 수 있는지 확인하기 위해 canRead()를 호출
- 대상 클래스 타입 확인
: ex) @RequestBody로 받은 대상 클래스 타입(byte[] / String 등등)
HTTP request의 Conent-Type에 해당하는 미디어 타입을 지원하는지 확인
: ex) text/plain, application/json 등등
canRead()를 만족하면 read()를 호출해서 객체를 읽어서 우리가 쓸 수 있도록 생성하고 반환
- HTTP 응답 흐름
Controller에서 @ResponseBdy / HttpEntity로 값이 반환
메시지 컨버터가 메시지를 쓸 수 있는지 확인하기 위해 canWrite()를 호출
대상 클래스 타입 확인
HTTP request의 Accept에 해당하는 미디어 타입을 지원하는지 확인
canWrite()을 만족하면 write()를 호출해서 HTTP Response Body에 데이터 생성
( 추가 정보 )
- 그렇다면
스프링 MVC구조에서 HTTP 메시지 컨버터는 어디쯤에서 수행이 되는가?
- 정답은
핸들러 어댑터가 실제 핸들러(Controller)를 호출하는 과정에서 일어난다
정확한 위치를 알기 위해서는 Argument Resolver / ReturnValue Handler를 알아야 한다!
Argument Resolver & ReturnValue Handler ?
[ 설명 ]

스프링 MVC 구조에서 핸들러 어댑터를 통해 실제 핸들러(컨트롤러)를 호출하는 과정을 자세히 알 필요가 있다

- 생각해보면,
어노테이션 기반의 컨트롤러는 정말 많은 종류의 파라미터를 사용했다
(HttpSErvletRequest / Model / @RequestParam / @ModelAttribute 등)
- 이렇게
유연하게 파라미터를 사용할 수 있던 비밀은 바로 중간에 Argument Resolver가 있기 때문이다.
[ Argument Resolver ]
( 설명 )
유연하게 다양한 파라미터를 처리하기 위한 것
핸들러 어댑터는 Argument Resolver를 호출해서 미리 들어갈 매개변수를 파악 & 생성
스프링은 30개가 넘는 ArgumentResolver를 기본으로 제공
- 정확히는
HandlerMethodArgumentResolver 이다.
( 동작 원리 )
핸들러 어댑터가 Argument Resolver를 호출
Argument Resolver는 내부에 supportsParameter()를 호출하며 어떤 파라미터를 지원하는지 확인
지원하는 파라미터를 찾은 뒤 resolveArgument()를 호출해서 실제 객체를 생성
(실제 객체를 생성할 때 HTTP 메서드 컨버터를 통해 메시지를 변환하여 사용)
[ ReturnValue Handler ]
( 설명 )
-
ArgumentResolver와 비슷한데, 이것은 응답 값을 변환하고 처리
컨트롤러에서 String으로 뷰 이름을 반환해서 동작하는 이유가 바로 ReturnValueHandler 덕분
스프링은 10개가 넘는 RetrurnValueHandler를 지원
스프링 MVC 구조에서 HTTP 메시지 컨버터


스프링 MVC 구조에서 HTTP 메시지 컨버터가 사용되는 시점
ArgumentResolver / ReturnValueHandler가 대응되는 파라미터 / 반환값을 만들어주는 과정에서
HTTP 메시지 컨버터를 호출해서 사용
스프링은 ArgumentResolver / ReturnValueHandler / HttpMessageConverter 모두 인터페이스로 제공
실제 확장이 필요할 때 이러한 내부 원리를 알고있어야 확장 포인트를 알 수 있음!