HTTP message body
에 데이터를 직접 담아서 요청
JSON 사용
POST
, PUT
, PATCH
요청 파라미터와 다르게, HTTP 메세지 바디를 통해 데이터가 직접 넘어오는 경우는 @RequestParam, @ModelAttribute를 사용할 수 없다.
먼저 가장 단순한 텍스트 메세지를 HTTP 메세지 바디에 담아서 전송하고, 읽어보면서 점점 단계적으로 발전시켜 보겠다.
@Slf4j
@Controller
public class RequestBodyStringController {
@PostMapping("/request-body-string-v1")
public void requestBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletInputStream inputStream = request.getInputStream();
//Stream을 바굴 때에는 인코딩 형식을 지정
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
response.getWriter().write("ok");
}
}
InputStream
을 사용하는 가장 단순한 방식이다. HttpServlet
을 통해 request
, response
를 받으며 InputStream
을 통해 처리한다
/**
* InputStream(Reader): HTTP 요청 메시지 바디의 내용을 직접 조회
* OutputStream(Writer): HTTP 응답 메시지의 바디에 직접 결과 출력
*/
@PostMapping("/request-body-string-v2")
public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) throws IOException {
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
responseWriter.write("ok");
}
스프링 MVC는 다음 파라미터를 지원한다.
InputStream(Reader)
: HTTP 요청 메시지 바디의 내용을 직접 조회 OutputStream(Writer)
: HTTP 응답 메시지의 바디에 직접 결과 출력/**
* HttpEntity: HTTP header, body 정보를 편리하게 조회
* - 메시지 바디 정보를 직접 조회(@RequestParam X, @ModelAttribute X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*
* 응답에서도 HttpEntity 사용 가능
- 메시지 바디 정보 직접 반환(view 조회X)
- HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
**/
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
String messageBody = httpEntity.getBody();
log.info("messageBody={}", messageBody);
return new HttpEntity<>("ok");
}
스프링 MVC는 다음 파라미터를 지원한다.
HttpEntity
: HTTP header, body 정보를 편리하게 조회@RequestParam
X, @ModelAttribute
X HttpEntity
는 응답에도 사용 가능
HttpEntity
를 상속받은 다음 객체들도 같은 기능을 제공한다.
RequestEntity
- HttpMethod, url 정보가 추가, 요청에서 사용
ResponseEntity
- HTTP 상태 코드 설정 가능, 응답에서 사용
return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED)
/**
* @RequestBody
* - 메시지 바디 정보를 직접 조회(@RequestParam X, @ModelAttribute X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*
* @ResponseBody
* - 메시지 바디 정보 직접 반환(view 조회X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*/
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) {
log.info("messageBody={}", messageBody);
return "ok";
}
@RequestBody
@RequestBody
를 사용하면 HTTP 메시지 바디 정보를 편리하게 조회할 수 있다. 참고로 헤더 정보가 필요하다면 HttpEntity
를 사용하거나 @RequestHeader
를 사용하면 된다.
이렇게 메시지 바디를 직접 조회하는 기능은 요청 파라미터를 조회하는 @RequestParam , @ModelAttribute 와는 전혀 관계가 없다.
요청 파라미터 vs HTTP 메시지 바디
@ResponseBody
@ResponseBody 를 사용하면 응답 결과를 HTTP 메시지 바디에 직접 담아서 전달할 수 있다. 물론 이 경우에도 view를 사용하지 않는다.
지금까지 1단계 InputStream
부터 4단계 @RequestBody
까지 살펴보았다. 4가지 방법을 살펴보았지만, 결국 HttpEntity
또는 @RequestBody
중에서 선택하여 사용하면 된다.
이번에는 HTTP API에 주로 사용하는 Json
데이터 형식을 조회해보자.
Json
또한 InputStream
, @RequestBody
를 사용하지만 역시나 HttpEntity, @RequestBody 중에서 선택하여 사용하면 된다.
2가지 방식의 예를 보여주겠다.
/**
* @RequestBody 생략 불가능(@ModelAttribute 가 적용되어 버림)
* HttpMessageConverter 사용
-> MappingJackson2HttpMessageConverter (content-type: application/json)
*
*/
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData data) {
log.info("username={}, age={}", data.getUsername(), data.getAge());
return "ok";
}
@RequestBody
객체 파라미터
@RequestBody HelloData data
HttpEntity
, @RequestBody
를 사용하면 HTTP 메시지 컨버터
가 HTTP 메시지 바디의 내용을 우리가 원하는 문자나 객체 등으로 변환해준다.
@RequestBody
는 생략 불가능
스프링은 @ModelAttribute
, @RequestParam
과 같은 해당 애노테이션을 생략시 다음과 같은 규칙을 적용한다.
@RequestParam
@ModelAttribute
(argument resolver 로 지정해둔 타입 외)따라서 이 경우 HelloData에 @RequestBody 를 생략하면 @ModelAttribute 가 적용되어버린다.
HelloData data -> @ModelAttribute HelloData data
따라서 생략하면 HTTP 메시지 바디가 아니라 요청 파라미터를 처리하게 된다.
@ResponseBody
@PostMapping("/request-body-json-v4")
public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) {
HelloData data = httpEntity.getBody();
log.info("username={}, age={}", data.getUsername(), data.getAge());
return "ok";
}
앞에서 배운 것처럼 HttpEntity
또한 사용해보았다.
@RequestBody
, HttpEntity
를 사용할 때 주의할 점이 있다.
HTTP request의 Content-Type가 반드시 application/json
이어야 한다. 그래야 Json을 처리할 수 있는 HTTP 메세지 컨버터
가 실행된다.