인프런/스프링 MVC 1편

12)HTTP요청 메시지 처리방법 [데이터타입 :JSON] (v1 ~ v4)

backend dev 2023. 1. 26.

HTTP요청 메시지 처리방법 [데이터타입 :JSON]  

요청 메시지의 바디안에 JSON이 담겨왔을때 처리 방법

 

 

V1 - HttpServletRequest,Response

직렬화
- 객체에 저장된 데이터를 I/O 스트림에 쓰기(출력) 위해 연속적인(serial) 데이터로 변환하는 것

역직렬화
- I/O 스트림에서 데이터를 읽어서(입력) 객체를 만드는 것

 

이므로 여기서는

직렬화 = 객체 -> JSON

역직렬화 = JSON -> 객체

@Slf4j
@Controller
public class RequestBodyJsonController {

    private ObjectMapper objectMapper = new ObjectMapper();//json을 역직렬화하려면 ObejectMapper가 필요하다.

    @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); //ObejctMapper로
        //{"username":"hello", "age":20} 이런식으로 생긴 String을 HelloData 객체로 변환해준다.
        log.info("username = {}, age ={}", helloData.getUsername(), helloData.getAge());
        response.getWriter().write("ok");
    }

}

Request,Response 객체는 spring에서 넣어주는것이고  Response객체에 들어있는 값을 이용해 응답Message를 만들것이니까 따로 반환할게없으므로 void타입

 

V2 - @RequestBody, @ResponseBody

@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";
}

@RequestBody를 이용해 HttpMessageBody에 있는 값을 받아오고 (String messageBody에 넣으니까 String형식으로 받아짐)     {"username":"hello", "age":20} 이런내용의 문자열일것이다.

 

ObejectMapper를 이용해서 문자열로 표현된 JSON을 객체로 변환해준다.

 

@ResponseBody를 사용하므로, @Controller 어노테이션을가진 컨트롤러의 메소드에서 String을 반환해도 뷰이름으로 처리하지않고, 응답Message바디에 들어갈 값으로 처리해서 응답한다.

똑같이 잘 동작한다.

 

V3 -  @RequestBody 객체변환

@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData helloData) {
    log.info("username = {}, age ={}", helloData.getUsername(), helloData.getAge());
    return "ok";
}

잘 동작한다.

@RequestBody에 단순한 String말고,  (ex ) @RequestBody String messageBody

객체를 파라미터로 넘길 수 있다.  ( ex) @RequestBody HelloData helloData

HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter 
(contenttype:application/json)

HTTP메시지 컨버터가 Content-Type를 보고 JSON임을 판단하고, json을 객체로 변환해주는 컨버터를 이용해 변환시켜준다.

 

V3_2 HttpEntity,ResponseEntity,RequestEntity

HttpEntity,ResponseEntity,RequestEntity도 <객체> 를 넣어주면 객체로 지정할 수 있다.

@ResponseBody
@PostMapping("/request-body-json-v3-2")
public ResponseEntity<HelloData> requestBodyJsonV3_2(RequestEntity<HelloData> request) {
    HelloData helloData = request.getBody();
    log.info("request = {}", request);
    log.info("body = {}", helloData);
    return new ResponseEntity<>(helloData, HttpStatus.OK);
}

JSON으로 들어온 데이터를 HTTP메시지컨버터가 HelloData 객체로 바꿔주고,

응답메시지 바디에 객체를 넣어도 JSON으로 잘 바꿔서 응답해준다.

 

TEXT로 넣어보려고하면 오류가 발생한다. (텍스트 컨버터는 없나보다)

V3_3 @RequestBody는 생략하면 안된다.

@ResponseBody
@PostMapping("/request-body-json-v3-3")
public String requestBodyJsonV3_3(HelloData helloData) {
    log.info("username = {}, age ={}", helloData.getUsername(), helloData.getAge());
    return "ok";
}

다음과 같이 생략했을경우

어노테이션을 생략하면 @ModelAttribute가 동작해서 파라미터값을 체크한다.

요청한 파라미터가 없으므로 기본값들이 들어가는데 

HelloData에서 username은 String이므로 기본값인 null로 설정되고

age는 int이므로 기본값인 0으로 설정된다.

 

V4 - @ResponseBody 객체 변환

@RequestBody가 메시지컨버터를 이용하여 JSON데이터를 객체로 변환해주는것과 같이

@ResponseBody를 쓰고있는데 객체를 반환하면 메시지컨버터가 객체를 JSON데이터로 변환하게되서 JSON데이터가 HTTP응답메시지에 들어가게 된다. 

 

@ResponseBody
@PostMapping("/request-body-json-v4")
public HelloData requestBodyJsonV4(@RequestBody HelloData helloData) {
    log.info("username = {}, age ={}", helloData.getUsername(), helloData.getAge());
    return helloData;
}

잘 동작한다.

JSON데이터가 들어왔고 @RequestBody를 이용해 객체로 변환받을때 http메시지컨버터가 JSON을 객체로 변환해주고

 

@ResponseBody가 있는데 객체를 반환할때 http메시지컨버터가 객체를 JSON으로 변환해주고 http응답메시지에 넣는다.

 

결론 V4의 형태를 쓰자.

@RequestBody를 사용해서  Http메시지바디에 들어온값의 타입이 text이든 Json이든

String으로 변환하던지, 객체로 변환하던지 해서 들어온 데이터를 쓰면되고

 

@ResponseBody를 사용해서 반환하려고하는값이 String이든 객체든

String이면 그냥 응답메시지바디에 넣어 응답해줄것이고 , 객체면 JSON으로 변환해서 메시지바디에 넣어 응답해준다. 

댓글