웹개발/웹서버

스프링 MVC: 요청 메시지

RisingJade 2024. 1. 19. 00:00

HTTP 요청 메시지 - 단순 텍스트

content-body를 통해 단순 텍스트를 얻는 방법에는 여러가지가 있다 .

  • request.getInputStream이용

    @PostMapping("/request-body-string-v1")
      public void requestBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException {
          ServletInputStream inputStream = request.getInputStream();
          //stream은 bytecode이니 string으로 바꿀때는 어떤 인코딩으로 바꿀건지 설정해주어야 한다. 지정 안할경우 default값이 설정된다.
          String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
    
          log.info("message-body={}", messageBody);
    
          response.getWriter().write("ok");
      }

    위의 방식이 너무 지저분하다면 inputstream만 미리 떼와서 쓸수도 있다.

  • 스프링 MVC는 다음 파라미터를 지원한다.
    InputStream(Reader): HTTP 요청 메시지 바디의 내용을 직접 조회
    OutputStream(Writer): HTTP 응답 메시지의 바디에 직접 결과 출력

    @PostMapping("/request-body-string-v2")//input stream과 writer를 그냥 받아서 바로 쓴다.
      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이용

    @PostMapping("/request-body-string-v3")
      public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
          String messageBody = httpEntity.getBody();
          log.info("messageBody={}", messageBody);
          return new HttpEntity<>("ok");
      }
  • HttpEntity: HTTP header, body 정보를 편리하게 조회

    • 메시지 바디 정보를 직접 조회
    • 요청 파라미터를 조회하는 기능과 관계 없음 @RequestParam X, @ModelAttribute X
  • HttpEntity는 응답에도 사용 가능

    • 메시지 바디 정보 직접 반환
    • 헤더 정보 포함 가능
    • view 조회X (@ResponseBody처럼 사용)

      HttpEntity 를 상속받은 다음 객체들도 같은 기능을 제공한다.

  • RequestEntity

    • HttpMethod, url 정보가 추가, 요청에서 사용
  • ResponseEntity

    • HTTP 상태 코드 설정 가능, 응답에서 사용
    • return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED)

TIP:
스프링MVC 내부적으로 HTTP메시지 바디를 읽어서 문자나 객체로 변환해서 전달하는데 이때 스프링은 HTTP 메시지 컨버터라는 기능을 사용하는 것이다.

  • @RequestBody

    @RequestBody 를 사용하면 HTTP 메시지 바디 정보를 편리하게 조회할 수 있다. 참고로 헤더 정보가 필요하다면 HttpEntity를 사용하거나 @RequestHeader를 사용하면 된다. 이렇게 메시지 바디를 직접 조회하는 기능은 요청 파라미터를 조회하는 @RequestParam, @ModelAttribute 와는 전혀 관계가 없다.
      @ResponseBody
      @PostMapping("/request-body-string-v4")
      public String requestBodyStringV4(@RequestBody String messageBody) {
          log.info("messageBody={}", messageBody);
          return "ok";
      }

HTTP 요청 메시지 - JSON

기본형은 아래와 같다.

  1. HttpServletRequest를 사용해서 직접 HTTP 메시지 바디에서 데이터를 읽어와서, 문자로 변환한다.

  2. 문자로 된 JSON 데이터를 Jackson 라이브러리인 objectMapper 를 사용해서 자바 객체로 변환한다.

    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("messageBody={}", messageBody);
         HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
         log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
    
         response.getWriter().write("ok");
     }
  • @RequestBody

    딱봐도 위의 방법은 너무 복잡하다. Spring에선 @RequestBody를 지원하는데 바디의 타입이 JSON일 경우 HTTP 메시지 컨버터가 자동으로 ObjectMapper를 호출해서 매개변수로 둔 객체에 맴버변수가 이름이 같은경우에 한해서 넣어 준다.
      @ResponseBody
      @PostMapping("/request-body-json-v3")
      public String requestBodyJsonV2(@RequestBody HelloData helloData) throws IOException {
          log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
          return "ok";
      }

    주의!

  1. @RequestBody는 생략 불가능!
    @RequestBody 를 생략하면 @ModelAttribute가 적용되어버린다.
  2. HTTP 요청시에 content-type이 application/json인지 꼭! 확인해야 한다.
    그래야 JSON을 처리할 수있는 HTTP 메시지 컨버터가 실행된다.
  • HttpEntity<>

    일반 텍스트에서도 HttpEntity<String>을 썼듯이 이번에는 HttpEntity<HelloData>라고 쓰면된다.
      @ResponseBody
      @PostMapping("/request-body-json-v4")
      public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) throws IOException {
          HelloData helloData = httpEntity.getBody();// <>제네릭 선언이 되어있어서 getBody를 하면 HelloData타입으로 받아짐
          log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
          return "ok";
      }

    Tip.
    단순히 받을때만 @RequestBody를 통해 JSON 타입을 받는것이 아니라 @ResponseBody를 통해서 응답을 JSON으로 반환 할 수 있다. (당연히 HTTP 메시지 컨버터가 해준다.)