개요.

뷰와 스프링을 연동하던 중, 클라이언트에서 서버단으로 Http Post 방식으로 전송하는 와중에 content-type 을 두가지로 달리하고 해당 내용이 크롬 개발자도구에서 다르게 찍힘을 확인할 수 있었다. 동일한 request body 이지만 표현하는 방식이 다르기 때문에 서버단에서 처리하는 방식또한 달랐다. 그리고 그 결과를 바탕으로 해당 내용에 대해서 정리하기 위함이다.

 

+) content-type

  • post/ put 메시지와 같이 body 에 데이터를 실어보낼때, 웹서버에서 현재 보내는 데이터의 형식이 무엇인지 알려주기 위함.
  • 만약 content-type 이 맞지 않는다면 415 Unsupported Media Type 이라는 에러가 발생한다.

 

+) accept

현재 클라이언트가 특정한 데이터 형식으로 받을 수 있다고 웹서버에게 알려주기 위함. 웹 서버가 반드시 그 형식을 따를 필요는 없다.

 

기본적으로 axios  는 자바스크립트의 객체, object 를 JSON 으로 직렬화한다. 직렬화된 내용은 스프링의 HttpMessageConverter 가 적절히 처리하는데, HttpMessageConverter 내의 수 많은 구현중에서 MappingJackson2HttpMessageConverter 을 이용한다. 해당 컨버터는 내부적으로 ObjectMapper 를 구현하고 있으며 JSON 으로 들어오는 내용에 대해서 직렬화 및 역직렬화를 수행하고 있다. 이러한 매핑을 수행하기 위하여, 나는 항상 요청 본문을 받기위해 @RequestBody 라는 어노테이션을 사용하고 있다.

 

만약에 axios 를 이용하는 와중에 application / x-www-form-urlencoded 형식으로 데이터를 전송하고자 한다면 아래와 같이 사용하여야 한다.

const qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 }));

 

 

[ Request Payload ]

 Vue Code

  • request header, content-type : application/json
  • request payload
payloadActions() {

    const uri = '/test-api/req-payload';

    const payload = {};
    payload.name = 'payload-name';
    payload.desc = 'payload-desc';
    console.debug(payload);

    return new Promise((resolve, reject) => {

        request.post(uri, payload).then((response) => {
            console.debug(response);
        }).catch((error) => {
            console.error(error.response);
        })

    });
},

 

 Spring Code

@PostMapping("/req-payload")
public ResponseEntity<Object> reqPayload(@RequestBody TestDto.PayloadRequest request) {

    log.debug("payload name : {}", request.name);
    log.debug("payload desc : {}", request.desc);

    return ResponseEntity.ok().body("ok");
}

 

 

[ Form Data ]

 Vue Code

  • request header, content-type : application/x-www-form-urlencoded
  • form data
formDataActions() {

    const uri = '/test-api/req-form';

    const formData = qs.stringify({ 'name': 'payload-name-00', 'desc': 'payload-desc-00' });
    console.debug(formData);

    return new Promise((resolve, reject) => {

        request.post(uri, formData).then((response) => {
            console.debug(response);
        }).catch((error) => {
            console.error(error.response);
        })
    });
}

 

☞ Spring Code

@PostMapping("/req-form")
public ResponseEntity<Object> reqForm(HttpServletRequest request) {

    log.debug("form-data name : {}", request.getParameter("name"));
    log.debug("form-data desc : {}", request.getParameter("desc"));

    return ResponseEntity.ok().body("ok");
}

 

결론

위의 request body 와 form data 모두 요청본문에 데이터를 담고있지만 그 담고있는 데이터를 표현하는 방식은 크롬 개발자 도구로 보았을 때 전혀 다른 모양을 띄고 있다. 또한 추가적으로 브라우저 콘솔로 확인해보았을 때도 찍히는 내용도 상이하다. 결국 요청 본문이 어떠한 content-type 유형에 속하는지 파악하고 이에 대응하기 위해 서버단에서 어떻게 데이터를 받을 것인지에 대해서 고민해보아야 할 것이다.

 

 

크롬 개발자도구 상에서 찍힌 요청 본문의 데이터.

▶ request payload

 

form data

 

참고링크

https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#rest-message-conversion

https://stackoverflow.com/questions/23118249/whats-the-difference-between-request-payload-vs-form-data-as-seen-in-chrome

Posted by doubler
,