1. HttpMessageConverter 용도
- HTTP API처럼 JSON 데이터를 HTTP 메시지 바디 내 직접 읽거나 쓰는 경우 사용
- @ResponseBody 어노테이션을 사용할 때 HTTP Body 내 문자 내용을 직접 반환하므로 HttpMessageConverter가 동작
- String 문자 처리에는 StringHttpMessageConverter, 객체 처리에는 MappingJackson2HttpMessageConverter 사용
- 이외에도 다양한 HttpMessageConverter가 존재
* 응답의 경우 클라이언트의 HTTP Accept 헤더와 서버 컨트롤러의 반환 타입을 조합해 MessageConverter가 선택됨 (하단에 추가 설명)
2. 스프링 MVC의 HttpMessageConverter 적용 사례
- HTTP 요청: @RequestBody, HttpEntity(RequestEntity)
- HTTP 응답: @ResponseBody, HttpEntity(ResponseEntity)
3. HttpMessageConverter 인터페이스 뜯어보기
* canRead(), canWrite() 메서드: 메시지 컨버터가 해당 클래스 혹은 미디어타입을 지원하는지 체크하는 용도
* read(), write() 메서드: 메시지 컨버터를 통해서 메시지를 읽고 쓰는 기능 지원
3.1 HTTP 요청 데이터 읽는 과정
- HTTP 요청이 들어오고, 컨트롤러에서 @RequestBody 혹은 HttpEntity 파라미터 사용하는 상황
- MessageConverter가 메시지를 읽을 수 있는 확인하기 위해 canRead() 메서드 호출 (대상 클래스 타입을 지원하는지, HTTP 요청의 Content-Type 미디어 타입을 지원하는지 체크)
- canRead() 조건을 만족할 경우 read() 메서드를 호출해서 객체 생성 후 반환
3.2 HTTP 응답 데이터 생성하는 과정
- 컨트롤러에서 @ResponseBody 혹은 HttpEntity로 값이 반환되는 상황
- MessageConverter가 메시지를 쓸 수 있는지 확인하기 위해 canWrite() 메서드 호출 (대상 클래스 타입을 지원하는지, HTTP 요청의 Accept 미디어 타입을 지원하는지 체크)
- canWrite() 조건을 만족할 경우 write() 메서드를 호출해서 HTTP 응답 메시지 바디 내 데이터 생성
4. 주로 사용하는 메시지 컨버터 세 가지 (우선순위 순)
- ByteArrayHttpMessageConverter
- StringHttpMessageConverter
- MappingJackson2HttpMessageConverter
* 앞서 언급한 대로 스프링에서 메시지 컨버터를 선정할 때 대상 클래스 타입과 미디어 타입을 체크 후 사용 여부를 결정하고, 만족하지 않을 경우 다음 우선순위에 있는 메시지 컨버터로 넘어가 체크 진행
4.1 ByteArrayHttpMessageConverter
- byte [] 데이터 처리
- 클래스 타입: byte []
- 미디어 타입: */*
- HTTP 요청 예시: @RequestBody byte [] example
- HTTP 응답 예시: @ResponeBody return byte[] (쓰기 MediaType: application/octet-stream)
4.2 StringHttpMessageConverter
- String 문자열로 데이터 처리
- 클래스 타입: String
- 미디어 타입: */*
- HTTP 요청 예시: @RequestBody String example
- HTTP 응답 예시: @ResponseBody return example (쓰기 MediaType: text/plain)
4.3 MappingJackson2HttpMessageConverter
- application/json 처리
- 클래스 타입: 객체 또는 HashMap
- 미디어 타입: application/json
- HTTP 요청 예시: @RequestBody Example example
- HTTP 응답 예시: @ResponseBody return example (쓰기 MediaType: application/json)
4.4 오류가 나는 경우
* 대상 클래스 타입과 미디어 타입이 매칭이 안되기 때문에 오류가 발생
HttpMessageConverter가 쓰이는 시점?
우선, 기존 게시물에서 작성한 Spring MVC 구조를 살펴봅시다. (https://jaimemin.tistory.com/1820)
* 위 그림에서는 HttpMessageConverter가 쓰이는 시점이 보이지 않지만, HttpMessageConverter는 아래 사진처럼 @RequestMapping을 처리하는 HandlerAdapter인 RequestMappingHandlerAdapter에서 쓰입니다.
- 어노테이션 기반 컨트롤러는 HttpServletRequest, Model, @RequestParam, @ModelAttribute, @RequestBody, HttpEntity와 같이 다양한 파라미터를 사용할 수 있는데 이렇게 유연하게 처리해줄 수 있는 이유는 ArgumentResovler 덕분
- 즉, 컨트롤러를 처리하는 RequestMappingHandlerAdapter가 ArgumentResolver를 호출하면서 필요로 하는 다양한 파라미터의 값을 생성한 후 컨트롤러를 호출하며 파라미터를 넘겨줌 (사진 내 1번과 2번 과정)
- ReturnValueHandler는 응답 값을 변환하고 처리하는데, 컨트롤러에서 String으로 뷰의 논리적 이름만 반환하더라도 동작하는 이유가 ReturnValueHandler 덕분 (사진 내 3번 과정)
- 이 과정에서 HttpMessageConverter는 요청과 응답을 처리하는 과정에서 모두 필요한데 아래와 같은 상황에서 사용이 됨
- 요청: @RequestBody 혹은 HttpEntity를 처리하는 ArgumentResovler가 HttpMessageConverter를 사용해서 필요하는 객체를 생성
- 응답: @ResponseBody 혹은 HttpEntity를 처리하는 ReturnValueHandler에서 HttpMessageConverter를 사용해서 응답 결과 생성
출처
인프런 스프링 MVC 1편 (김영한 강사님)
'Spring' 카테고리의 다른 글
[SpringBoot] Validation 간단 정리 - 1 (BindingResult, Validator) (6) | 2021.07.16 |
---|---|
[Spring Boot] 메시지, 국제화 간단 정리 (0) | 2021.07.10 |
Spring MVC 구조 정리 (0) | 2021.06.09 |
클라이언트에서 서버로 HTTP 요청 메시지 보내는 방법 (0) | 2021.06.02 |
빈 스코프 (Bean Scope) (0) | 2021.05.26 |