• @ResponseBody의 원리를 먼저 확인해보자
  • @ResponseBody를 사용할 경우 HTTP Body에 내용을 직접 반환하게 되는데,
    viewResolver 대신에 HttpMessageConverter가 동작한다.
    - 기본 문자를 처리할 경우에는 StringHttpMessageConverter가 동작하고,
    객체를 처리할 때는 MappingJackson2HttpMessageConverter가 동작한다.
    - byte처리 등 여러 HttpMessageConverter가 기본적으로 등록되어 있다.
  • HTTP 메세지 컨버터는 요청, 응답에서 모두 사용되는데, 요청 http 바디에서 파라미터 값을 읽어와 컨트롤러로 넘겨주는 역할, 컨트롤러의 리턴 값을 응답 http 바디에 넣어주는 역할을 한다.
    따라서 다음의 경우 메세지컨버터가 동작한다.

메세지 컨버터 동작 순서

  • HTTP 요청 데이터 읽기
  1. HTTP 요청이 오고, 컨트롤러에서 @RequestBody , HttpEntity 파라미터를 사용한다.
  2. 메시지 컨버터가 메시지를 읽을 수 있는지 확인하기 위해 canRead() 를 호출한다. 이 때 아래의 2가지를 동시에 확인한다.
    - 대상 클래스 타입을 지원하는가.
    @RequestBody 의 대상 클래스 ( byte[] , String , HelloData )
    - HTTP 요청의 Content-Type 미디어 타입을 지원하는가.
    예) text/plain , application/json , /
  3. canRead() 조건을 만족하면 read() 를 호출해서 객체 생성하고, 반환한다.
  • HTTP 응답 데이터 생성
  1. 컨트롤러에서 @ResponseBody , HttpEntity 로 값이 반환된다.
  2. 메시지 컨버터가 메시지를 쓸 수 있는지 확인하기 위해 canWrite() 를 호출한다.
    • 대상 클래스 타입을 지원하는가.
      예) return의 대상 클래스 ( byte[] , String , HelloData )
    • HTTP 요청의 Accept 미디어 타입을 지원하는가.(더 정확히는 @RequestMapping 의 produces )
      예) text/plain , application/json , /
  3. canWrite() 조건을 만족하면 write() 를 호출해서 HTTP 응답 메시지 바디에 데이터를 생성한다.
  • 그렇다면 메세지 컨버터의 종류와 그 우선 순위는 어떻게 될까?

메세지 컨버터의 종류와 우선순위

  • 스프링 부트 기본 메시지 컨버터
    (일부 생략)
    0 = ByteArrayHttpMessageConverter
    1 = StringHttpMessageConverter
    2 = MappingJackson2HttpMessageConverter

스프링 부트는 다양한 메시지 컨버터를 제공하는데, 대상 클래스 타입과 미디어 타입 둘을 체크해서 사용여부를 결정한다. 만약 만족하지 않으면 다음 메시지 컨버터로 우선순위가 넘어간다.

1. ByteArrayHttpMessageConverter

  • byte[] 데이터를 처리한다.
    클래스 타입: byte[] , 미디어타입: / ,
    요청 예) @RequestBody byte[] data
    응답 예) @ResponseBody return byte[] 쓰기 미디어타입 application/octet-stream

2. StringHttpMessageConverter

  • String 문자로 데이터를 처리한다.
    클래스 타입: String , 미디어타입: /
    요청 예) @RequestBody String data
    응답 예) @ResponseBody return "ok" 쓰기 미디어타입 text/plain

3. MappingJackson2HttpMessageConverter

  • application/json
    클래스 타입: 객체 또는 HashMap , 미디어타입 application/json 관련
    요청 예) @RequestBody HelloData data
    응답 예) @ResponseBody return helloData 쓰기 미디어타입 application/json 관련

  • 예시로 몇가지 상황을 확인해보자

  1. StringHttpMessageConverter
    content-type: application/json
    @RequestMapping
    void hello(@RequestBody String data) {}
  • 컨텐츠 타입이 application/json이고, 클래스 타입이 String인 경우 StringHttpMessageConverter가 실행된다.
  1. MappingJackson2HttpMessageConverter
    content-type: application/json
    @RequestMapping
    void hello(@RequestBody HelloData data) {}
  • 컨텐츠 타입이 application/json이고, 클래스 타입이 HelloData(사용자 정의 타입)인 경우 MappingJackson2HttpMessageConverter가 실행된다.
  1. 매칭이 안되는 경우
    content-type: text/html
    @RequestMapping
    void hello(@RequestBody HelloData data) {}
  • 클래스 타입이 HelloData(사용자 정의 타입)인데, 컨텐츠 타입은 text/html이므로 매칭이 되지 않는다.
profile
꾸준히 하자!

0개의 댓글

관련 채용 정보

Powered by GraphCDN, the GraphQL CDN