[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
모두 인터페이스로 제공
실제 확장이 필요
할 때 이러한 내부 원리
를 알고있어야 확장 포인트
를 알 수 있음!