스프링을 공부하다가 우연히 @RequestBody와 @ModelAttribute를 통해 값을 바인딩할 때 오류를 겪는 상황을 발견하고, 평소 Class 바인딩은 자연스럽게 @ModelAttribute로, Json과 같은 타입은 자연스럽게 @RequestBody로 작성했었던, 아무 생각 없이 스프링을 공부했던 나 자신을 돌아보며 오늘 글을 작성하려한다.
이를 이해하기 위해서는 우선 HTTP Message에 대한 이해가 필요하다.
HTTP Message는 우리가 어떤 요청을 보내거나 요청에 대한 응답을 보낼 때, 서버와 클라이언트가 서로 데이터를 교환하는 방식이다.
데이터를 요청할 때 부르는 용어인 Rquest에는 서버가 특정 동작을 수행하도록 하는 메시지를 담고 있고, 총 4개의 섹션으로 구분하고 있는데 이는 다음과 같다.
- 첫 번째 줄에는 HTTP Method(POST,GET,PUT,HEAD,OPTIONS)를 통해 서버가 수행할 동작과 요청 컨텍스트(localhost:8080,/ITBook.com/indext.html 등)와 마지막 세 번째로는 HTTP 버전이 들어가게 된다.
- 두 번째줄 부터는 'Header'가 포함되어 있는데, 요청 헤더에는 request,general,entity 헤더가 있고, 자세한 설명은 아래에 [HTTP Headers] 참고!
- 헤더 구간을 지나면 비어있는 줄이 있는데 여기가 세 번째 구간인 요청에 대한 모든 메타 정보가 전송되어있음을 보여주는 구간이다.
- 마지막으로 네 번째 구간은 요청 바디 혹은 메시지의 페이로드라고 불리며, 요청과 관련된 내용(json 또는 html문서)
이 들어가 있고, 이 바디 부분의 존재 유무 또는 크기에 대한 정보는 바디 첫 줄과 헤더에 포함되어 있다.
응답 방식은 이번 글에 필요하지 않은 내용이라 링크 참조만 하도록 하겠다. [HTTP Message]
HTTP Message에 대한 대략적인 이해를 통해 오늘 글의 포커스 두 가지를 잡으면
1. 우리가 데이터를 보내는 형식은 '헤더'에 들어가 있다.
2. 우리가 보내는 데이터는 헤더의 Query String 혹은 페이로드에 포함되어있다.
이 두가지를 통해 오늘 본론으로 들어가려한다.
우리가 데이터를 보낼 때, 헤더에는 [Content-Type]에 해당하는 값이 들어가 있다고 알고있다.
이 타입에는 우리가 어떤 데이터를 보내는지에따라 다른 값이 들어가는데,
일반적으로 우리가 전송하는 데이터에는 [x-www-form-urlencoded] 타입이 붙고,
파일같은 것을 전송하기 위해서는 [multipart/form-data] 타입이 붙는다.
또 다른 타입들로는 raw 타입이라고 해서 [text/plain],[application/json],[application/xml] 등이 있는데,
이 타입들을 통해 우리가 왜 @RequestBody와 @ModelAttribute를 쓰는지 알아보려한다.
우선 이 content-type들로 하여금 일어나는 다양한 오류에 대한 예시는 [백기선님 온라인 강의 참조]를 통해서
알아볼 수 있고, 이를 통해 내가 알아본 대로 정리를 하자면,
@ModelAttribute는 헤더에 폼 데이터가 들어있는 요청의 바디 부분을 스프링이 받은 후에 RequestAttribute로 파싱해서
@RequestAttribute나 @ModelAttribute로 받을 수 있다고한다.
@RequestBody는 요청의 헤더에 폼 데이터가 없는 경우 바디의 데이터(JSON과 같은)를 파싱해주기 위해서 @RequestBody를 쓰는 것이고, 이를 변환하기 위한 적절한 MessageConverter가 쓰이는 것이다.(스프링에서는 json 관련 컨버터 설정이 되있기 때문에 따로 설정을 안해도 되고, xml이나 text같은 문서를 참조할 때는 따로 컨버터 설정이 필요하다.)
간단히 말해서 @RequestBody는 바디의 데이터를 해당 raw 타입에 맞게 파싱해서 전달해주기 때문에
key,value형식으로 들어온 폼데이터의 데이터 파싱 방식과 다르고, @ModelAttribute는 폼데이터의 데이터 파싱 방식을
따르기 때문에 @RequestBody와 @ModelAttribute를 통해 데이터를 해당 어노테이션에 맞지 않는 content-type을 사용하여 바인딩 했을 때, 바인딩이 되지 않거나 415 Unsupported Media Type이라는 에러가 뜨는 것이다.
[Referense]
-http message 관련
https://developer.mozilla.org/ko/docs/Web/HTTP/Messages
- 헤더 관련
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers
- 컨버터 기본설정 관련 Okky 답글
https://okky.kr/article/370152
- 스프링에서 Content-Type의 쓰임
https://kdevkr.github.io/archives/2018/understanding-http-content-types/
'Spring Framework > spring' 카테고리의 다른 글
MSA 환경에서 Kotlin + Spring Rest Docs + Swagger UI 적용 (0) | 2023.09.14 |
---|---|
Spring 컨트롤러 테스트 + Rest Docs에서 시간 개선 (0) | 2023.09.13 |
스프링 tiles(타일즈) 설정하기 (0) | 2019.08.12 |
스프링 MVC 설정으로 게시판 만들기 Part_2 (0) | 2019.08.09 |
스프링 MVC 설정으로 게시판 만들기 Part_1 (0) | 2019.08.09 |