-
[김영한 스프링] 25. 스프링 MVC 기본 기능 - HTTP 요청 메시지Spring/스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 2023. 7. 14. 03:41
HTTP 요청 메시지 - 단순 텍스트
- HTTP message body에 데이터를 직접 담아서 요청
- HTTP API에서 주로 사용, JSON, XML, TEXT
- 데이터 형식은 주로 JSON 사용
- POST, PUT, PATCH
요청 파라미터와 다르게, HTTP 메시지 바디를 통해 데이터가 직접 넘어오는 경우는 @RequestParam, @ModelAttribute를 사용할 수 없다. (물론 HTML Form 형식으로 전달되는 경우는 요청 파라미터로 인정된다.)
먼저 가장 단순한 텍스트 메시지를 HTTP 메시지 바디에 담아서 전송하고, 읽어보자.
HTTP 메시지 바디의 데이터를 InputStream을 사용해서 직접 읽을 수 있다.
RequestBodyStringController
main/java/hello/springmvc/basic/request/RequestBodyController 생성
package hello.springmvc.basic.request; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.PostMapping; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; @Slf4j @Controller public class RequestBodyStringController { @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"); } }
실행
결과
Input, Output 스트림, Reader - requestBodyStringV2
/** * 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 - requestBodyStringV3
/** * 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) throws IOException { String messageBody = httpEntity.getBody(); log.info("messageBody={}", messageBody); return new HttpEntity<>("ok"); }
스프링 MVC는 다음 파라미터를 지원한다.
- HttpEntity : HTTP header, body 정보를 편리하게 조회
- 메시지 바디 정보를 직접 조회
- 요청 파라미터를 조회하는 기능과 관계없음 @RequestParam X, @ModelAttribute X
- HttpEntity는 응답에도 사용 가능
- 메시지 바디 정보 직접 반환
- 헤더 정보 포함 가능
- view 조회X
HttpEntity를 상속받은 다음 객체들도 같은 기능을 제공한다.
- RequestEntity
- HttpMethod, url 정보가 추가, 요청에서 사용
- ResponseEntity
- HTTP 상태 코드 설정 가능, 응답에서 사용
- return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED)
참고
스프링MVC 내부에서 HTTP 메시지 바디를 읽어서 문자나 객체로 변환해서 전달해 주는데, 이때 HTTP 메시지 컨버터(HttpMessageConverter)라는 기능을 사용한다.실행
결과
@RequestBody - requestBodyStringV4
/** * @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 메시지 바디
- 요청 파라미터를 조회하는 기능 : @RequestParam, @ModelAttribute
- HTTP 메시지 바디를 직접 조회하는 기능 : @RequestBody
@ResponseBody
@ResponseBody를 사용하면 응답 결과를 HTTP 메시지 바디에 직접 담아서 전달할 수 있다.
물론 이 경우에도 view를 사용하지 않는다.
실행
결과
HTTP 요청 메시지 - JSON
RequestBodyJsonController
main/java/hello/springmvc/basic/request/RequestBodyJsonController 생성
package hello.springmvc.basic.request; import com.fasterxml.jackson.databind.ObjectMapper; import hello.springmvc.basic.HelloData; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.PostMapping; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; /** * {"username":hello, "age":20} * content-type: application/json */ @Slf4j @Controller public class RequestBodyJsonController { private ObjectMapper objectMapper = new ObjectMapper(); @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("message={}", messageBody); HelloData helloData = objectMapper.readValue(messageBody, HelloData.class); log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); response.getWriter().write("ok"); } }
HttpServletRequest를 사용해서 직접 HTTP 메시지 바디에서 데이터를 읽어와서, 문자로 변환한다.
문자로 된 JSON 데이터를 Jackson 라이브러리인 objectMapper를 사용해서 자바 객체로 변환한다.
실행
결과
requestBodyJsonV2 - @RequestBody 문자 변환
/** * @RequestBody * HttpMessageConverter 사용 -> StringHttpMessageConverter 적용 * * @ResponseBody * - 모든 메서드에 @ResponseBody 적용 * - 메시지 바디 정보 직접 반환(view 조회X) * - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용 */ @ResponseBody @PostMapping("/request-body-json-v2") public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException { log.info("message={}", messageBody); HelloData helloData = objectMapper.readValue(messageBody, HelloData.class); log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); return "ok"; }
- 이전에 학습했던 @RequestBody를 사용해서 HTTP 메시지에서 데이터를 꺼내고 messageBody에 저장한다.
- 문자로 된 JSON 데이터인 messageBody를 objectMapper를 통해서 자바 객체로 변환한다.
실행
결과
requestBodyJsonV3 - @RequestBody 객체 변환
/** * @RequestBody 생략 불가능(@ModelAttribute 가 적용되어 버림) * HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter (contenttype: application/json) * */ @ResponseBody @PostMapping("/request-body-json-v3") public String requestBodyJsonV3(@RequestBody HelloData helloData) { log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); return "ok"; }
@RequestBody 객체 파라미터
- @RequestBody HelloData data
- @RequestBody에 직접 만든 객체를 지정할 수 있다.
HttpEntity, @RequestBody를 사용하면 HTTP 메시지 컨버터가 HTTP 메시지 바디의 내용을 우리가 원하는 문자나 객체 등으로 변환해 준다.
HTTP 메시지 컨버터는 문자뿐만 아니라 JSON도 객체로 변환해 주는데, 우리가 방금 V2에서 했던 작업을 대신 처리해 준다.
@RequestBody는 생략 불가능
@ModelAttribute에서 학습한 내용을 떠올려보자.
스프링은 @ModelAttribute, @RequestParam과 같은 해당 애노테이션을 생략 시 다음과 같은 규칙을 적용한다.
- String, int, Integer 같은 단순 타입 = @RequestParam
- 나머지 = @ModelAttribute(argument resolver로 지정해둔 타입 외)
따라서 이 경우 HelloData에 @RequestBody를 생략하면 @ModelAttribute가 적용되어 버린다.
HelloData data -> @ModelAttribute HelloData data
따라서 생략하면 HTTP 메시지 바디가 아니라 요청 파라미터를 처리하게 된다.
주의
HTTP 요청시에 content-type이 application/json인지 꼭! 확인해야 한다. 그래야 JSON을 처리할 수 있는 HTTP 메시지 컨버터가 실행된다.실행
결과
requestBodyJsonV4 - HttpEntity
@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"; }
실행
결과
requestBodyJsonV5
/** * @RequestBody 생략 불가능(@ModelAttribute 가 적용되어 버림) * HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter (contenttype: application/json) * * @ResponseBody 적용 * - 메시지 바디 정보 직접 반환(view 조회X) * - HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter 적용 (Accept: application/json) */ @ResponseBody @PostMapping("/request-body-json-v5") public HelloData requestBodyJsonV5(@RequestBody HelloData helloData) { log.info("username={}, age={}", helloData.getUsername(), helloData.getAge()); return helloData; }
@ResponseBody
응답의 경우에도 @ResponseBody를 사용하면 해당 객체를 HTTP 메시지 바디에 직접 넣어줄 수 있다.
물론 이 경우에도 HttpEntity를 사용해도 된다.
- @RequestBody 요청
- JSON 요청 -> HTTP 메시지 컨버터 -> 객체
- @ResponseBody 응답
- 객체 -> HTTP 메시지 컨버터 -> JSON 응답
실행
결과
출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1
'Spring > 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술' 카테고리의 다른 글
[김영한 스프링] 27. 스프링 MVC 기본 기능 - HTTP 메시지 컨버터 & 요청 매핑 헨들러 어뎁터 구조 (0) 2023.07.18 [김영한 스프링] 26. 스프링 MVC 기본 기능 - 응답 (0) 2023.07.17 [김영한 스프링] 24. 스프링 MVC 기본 기능 - HTTP 요청 파라미터 (0) 2023.07.14 [김영한 스프링] 23. 스프링 MVC 기본 기능 - HTTP 요청 기본, 헤더 조회 (0) 2023.07.14 [김영한 스프링] 22. 스프링 MVC 기본 기능 - 요청 매핑 (0) 2023.07.12 - HTTP message body에 데이터를 직접 담아서 요청