캠프 타임어택 테스트를 보면서 궁금한 점이 생겼다.
이전에 플라스크를 사용해서 개발할 때 ajax 프론트 코드에서 아래와 같이 작성했다. (아래 코드는 예시)
<script>
let name = "kj";
let age = 25;
$.ajax({
type: "POST",
url: "/person",
data: {name: name, age: age},
success: function (response) {
// 로직 생략
}
});
</script>
'data 옵션에 서버로 요청할 데이터들을 넣어서 키-값 형태로 보내는구나' 라는 일차원적인 생각만 했다.
하지만 이번 타임어택 테스트를 볼 때는 JSON 포맷으로 데이터를 보낸다. 서버로 데이터를 전송하니까 이번에도 data 옵션에 기존에 하던대로 넣으면 되겠다 싶었다. 그래서 당연히 위에 적었던 코드처럼 작성했다.
Front
<script>
let content = $('#content').val();
$.ajax({
type: 'POST',
url: '/memo',
data: {content: content},
success: function (response) {
// 로직
}
});
</script>
Back
@PostMapping("/memo")
public Memo addMemo(@RequestBody MemoDto memoDto) {
Memo memo = memoService.createMemo(memoDto);
return memo;
}
하지만 Exception이 발생하며 WARN 로그가 찍혔다.
org.springframework.web.HttpMediaTypeNotSupportedException:
Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
application/x-www-form-urlencoded를 사용할 때 Spring이 이를 RequestBody로 이해하지 못하는 것이라고 한다.
근데 왜 Content-Type이 application/x-www-form-urlencoded로 되었지? 라는 생각을 가지며 ajax Content-Type의 디폴트 값을 찾아보았다. 역시 디폴트가 application/x-www-form-urlencoded였다.
(사진 출처: https://api.jquery.com/jquery.ajax/)
지금까지 플라스크를 사용하며 작성했던 ajax 코드들은 application/x-www-form-urlencoded 타입으로 이뤄졌던 것이다.
아무튼 !
data: {name: name, age: age}
data: {content: content}
이 부분은 application/x-www-form-urlencoded 타입이라는 것이다.
그러면 JSON 형식으로 보내려면 어떻게 해야할까?
<script>
let content = $('#content').val();
$.ajax({
type: 'POST',
url: '/memo',
contentType: "application/json",
data: JSON.stringify({content: content}),
success: function (response) {
// 로직
}
});
</script>
이와 같이 작성하면 된다.
contentType에 application/json으로 명시하고, data에도 JSON.stringify(json)를 사용한다.
JSON.stringify() 메서드는 JavaScript 값이나 객체를 JSON 문자열로 변환한다.
참고
“Post - Http: MDN.” HTTP | MDN, https://developer.mozilla.org/ko/docs/Web/HTTP/Methods/POST.
“JSON.stringify() - Javascript: MDN.” JavaScript | MDN, https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify.
번외
application/x-www-form-urlencoded
POST / HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
name=kj&age=25
application/x-www-form-urlencoded도 요청 메시지 body 부분을 보면 키-값 형태로 되어있고 파라미터가 여러 개일 때 &로 구분한다. Spring에서 @RequestParam을 사용하면 파라미터 값을 가져올 수 있다.
application/json
POST / HTTP/1.1
Host: localhost
Content-Type: application/json
{
"name": "kj",
"age": 25
}