메시지가 단순 텍스트인 경우
파라미터와 다르게 HTTP 메시지 바디를 통해 데이터가 넘어오는 경우, @RequestParam
, @ModelAttribute
를 사용하지 못한다.(Form 형식으로 전달되는 경우에는 요청 파라미터로 인정된다.)
InputStream (서블릿)
HTTP 메시지 바디의 데이터를 InputStream
을 활용해 직접 읽을 수 있다.
@PostMapping("/request-body-string-v1")
public void requestBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
response.getWriter().write("ok");
}
해당 코드를 조금 더 간략하게 바꾼다면 아래와 같이 바꿀수 있다. 스프링 MVC에서 InputStream
과 OutputStream(Writer)
을 지원하기 때문이다.
@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");
}
HttpEntity
이전에 HTTP Entity를 사용하여 HTTP 헤더와 바디 정보를 편리하게 조회할 수 있다는것을 배웠다. 이를 해당 코드에도 적용할 수 있다.
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) throws IOException {
String messageBody = httpEntity.getBody();
log.info("messageBody={}", messageBody);
return new HttpEntity<>("ok");
}
HttpEntitiy
는 응답에도 사용이 가능하며 헤더의 정보를 포함할 수 있다는 이점이있다.
HttpEntitiy를 상속받은 RequestEntitiy
, ResponseEntitiy
객체들도 아래와 같은 기능을 제공한다.
- RequestEntity : HttpMethod, url 정보 추가, 요청에서 사용
- ResponseEntity : HTTP 상태 코드 설정 가능, 응답에서 사용
@RequestBody
그리고 이를 더 간단하게 사용하자면 스프링 MVC의 @RequestBody
가 존재한다. 허나 @RequestBody 어노테이션 단일로는 헤더 정보를 조회할 수 없으므로 헤더의 정보가 필요하다면 HttpEntitiy
혹은 메서드 단위에 @ResponseBody
어노테이션을 사용하면 된다. 이 경우, view는 사용하지 않는다.
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) {
log.info("messageBody={}", messageBody);
return "ok";
}
요청 메시지가 JSON인 경우
먼저 JSON 데이터를 자바 객체로 변환하기 위해 Jackson 라이브러리인 objectMapper
를 생성한다.
private ObjectMapper objectMapper = new ObjectMapper();
그리고 포스트맨으로 테스트 시엔 꼭 json 형식으로 테스트한다.
- {"username":"hello", "age":20}
- content-type: application/json
@PostMapping("/request-body-json-v1")
public void requestBodyJsonV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
response.getWriter().write("ok");
}
해당 코드는 단순 텍스트를 읽어왔을때와 비슷하게, HttpServletRequest
를 사용하여 직접 데이터를 읽어와서 문자로 변환한다. 이후 objectMapper를 사용하여 자바 객체로 변환한다.
위에서 학습하였던 @RequestBody를 json형식에서도 사용가능하다.
@ResponseBody
@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {
log.info("messageBody={}", messageBody);
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
허나 파라미터에서 문자로 변환후, objectMapper를 사용하여 다시 json으로 변환하는 과정이 불편하다.
그래서 아래와 같이(HelloData) 직접 만든 객체를 지정할 수 있다.
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
@ResponseBody
@PostMapping("/request-body-json-v4")
public String requestBodyJsonV4(HttpEntity<HelloData> data) {
HelloData helloData = data.getBody();
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
이전에 학습하였던 @RequestParam
과 @ModelAttribute
의 경우 이름이 같다면 생략할 수 있었다. 그러나 @RequestBody
의 경우 생략하면 위의 코드에서는 @ModelAttribute
가 적용되므로 생략하지 말자. (메시지 바디가 아닌 요청 파라미터를 처리하게 된다.)
또한 위의 2번째 코드와 같이 HttpEntitiy<객체>와 같이 사용할 수도 있다.
응답의 경우에도 @ResponseBody 어노테이션을 사용하여 해당 객체를 바로 HTTP 메시지 바디에 넣어줄 수 있다.
@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return helloData;
}
해당 코드와 같이 작성하면 응답값이 ok가 아닌 json형태로 반환된다. 당연히 이 경우에도 HttpEntity<HelloData>
와 같이 사용해도 된다.
정리하자면 아래와 같다.
- @RequestBody 요청 : JSON 요청 -> Http 메시지 컨버터 -> 객체
- @ResponseBdoy 응답 : 객체 -> Http 메시지 컨버터 -> JSON 응답
위 글은 김영한 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술의 일부 내용을 정리한 것입니다.
'Backend > Spring' 카테고리의 다른 글
[Spring] 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 #5 스프링 MVC 기본 기능 - HTTP 요청 (0) | 2024.08.21 |
---|---|
[Spring] 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 #5 스프링 MVC 기본 기능 - 요청 매핑 (0) | 2024.08.05 |
[Spring] 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 #5 스프링 MVC 기본 기능 - 프로젝트 생성, 로깅 (0) | 2024.07.31 |
[Spring] 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 #5 스프링 MVC 구조 이해 (0) | 2024.07.30 |
[Spring] 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 #4 MVC 프레임워크 (0) | 2024.07.10 |