지나공 : 지식을 나누는 공간

webclient UnsupportedMediaTypeException: content type 'text/html' not supported for bodytype 이유 & Header 기본 본문

우당탕탕 삽질기

webclient UnsupportedMediaTypeException: content type 'text/html' not supported for bodytype 이유 & Header 기본

해리리_ 2022. 8. 7. 23:09

 

지난 신입 과제 때 webclient로 기상청 API를 호출하는 과정에서 아래와 같은 에러를 마주한 적이 있다.

(해결법을 보고 싶은 분은 이 포스팅 맨 아래쪽으로 내리세욤)

에러내용
호출 코드

HTTP 헤더에 대한 기본 지식이 없었다. 그래서 지금 보니 진짜 엉망진창의 요청헤더였네?!?! 어디로 숨을가... 이 사진을 그대로 여쭤봤다니....어휴어휴..

 

아무튼 과거의 쪽팔림은 뒤로 하고,(ㅋㅋ) HTTP 헤더 기본 내용도 공부했으니, 이제 이 내용을 적용해서 위에서 뭐가 잘못됐었는지 아래에서 살펴볼 예정이다.

 

Header 기본

뭐가 잘못됐는지 보기에 앞서, 필요한 기본 개념부터 정리하잣.

 

Header의 용도

HTTP 전송에 필요한 모든 부가 정보. 메시지 바디의 내용, 크기, 압축은 뭘로 했는지, 인증에 대해서, 캐시 관리 정보 등등...

표준 헤더가 굉장히 많고, 필요 시 임의의 헤더를 추가할 수 있다.

 

HTTP Body 속 Header

body는 헤더랑 데이터로 나뉜다.

  • 메시지 본문 = payload
  • 표현 전체는 요청이나 응답에서 전달할 실제 데이터를 의미.
  • 표현 헤더 = 표현 데이터를 해석하기 위한 정보들.
    • html, json 등 데이터 유형이 뭔지, 데이터 길이, 압축 정보 등
    • 전송과 응답 둘다 사용한다.

표현

표현 헤더는 응답과 요청 둘다 사용된다.

  • Content-Type : 표현 데이터 형식
  • Content-Encoding : 표현 데이터 압축방식
  • Content-Language :  표현 데이터의 자연 언어
  • Content-Length : 표현 데이터의 길이

각각 요청 응답 중 어디에 쓰이는지, 공통에 쓰이는지 등은 아래 블로그에 잘 나와있어서 링크 첨부!

https://goddaehee.tistory.com/169

 

[HTTP 기초_1] 헤더 (요청(Request) 헤더, 응답(Response)헤더)

[HTTP 기초_1] 헤더 (요청(Request) 헤더, 응답(Response)헤더) 안녕하세요. 갓대희 입니다. 이번 포스팅은 [ HTTP란?, HTTP 헤더 입니다. : ) 헤더로 들어가기 앞서 HTTP가 무엇인지 부터 알아보자. ▶ HTTP..

goddaehee.tistory.com

 

협상 (콘텐츠 네고시에이션)

클라이언트가 선호하는 표현을 서버에게 요청하는 내용을 이 필드로 담는다.

협상 헤더는 요청 시에만 사용한다.

  • Accept : 클라이언트가 선호하는 미디어 타입을 전달
  • Accept-Charset : 클라이언트가 선호하는 문자 인코딩
  • Accept-Encoding:  클라이언트가 선호하는 압축 인코딩
  • Accept-Language: 클라이언트가 선호하는 자연 언어

 

무엇이 잘못됐나?

일단 기상청 open api 쿼리 파라미터에 데이터 타입 요청하는 필드가 있다. xml인지 json인지 요청이 가능하다.

하지만 이것과 실제 데이터를 어떤 타입으로 요청하는지는 상관이 없다.

 

  1. 일단 위 사진에서 accept를 썼다. 위에서 알아본 바와 같이 클라이언트가 서버한테 원하는 데이터를 말하는 건데, 저기서부터 text/html로 달라고 말하고 있으니까 문제다. 내가 원하는 건 application/json이다.
  2. 그리고 요청 header로 Content-Type도 넣어놨는데 text/html이라고 넣어놨다. content-type이 요청헤더랑 응답헤더 둘 다에 쓰이긴 하지만 둘이 쓰여지는 내용이 좀 다르다. 내가 넣은 text/html 또는 application/json은 응답 헤더에서 "이런 타입으로 너에게 줄게~" 를 말할 때 쓰거나, 클라이언트 측에서 POST나 PUT할 때 요청 메시지 바디 타입이 뭔지 알려줄 때 사용한다.

요청에서 쓰이는 Content-Type은 좀 다르다.

 

그럼 어떻게 고칠까?

UnsupportedMediaTypeException: content type 'text/html' not supported for bodytype = "내 매핑 클래스경로"

위 에러는 응답 온 text/html이 class 객체로 변환이 안되니까 생긴 오류다. 왜 text/html로 오지? json으로 왔으면 좋겠는데!

 

서버 측에서 text/html로 주고 있으니, class 객체 변환이 어렵다. 따라서 나는 json으로 보내달라고 요청해야 한다.

 

클라이언트가 서버한테 선호하는 표현을 요청하는 걸 '협상(콘텐츠 네고시에이션)'으로 위에서 공부했다.

Webclient에서 체이닝으로 accept 헤더를 추가할 수 있다. accept에 application/json으로 요청하면 된다.

글고 text/html은 요청하지도 말고.

이렇게?

근데. 그럼 Content-Type을 요청에 쓰는 경우를 본 것 같은데 그건 뭘까?? 거기에 accept도 같이 쓰면 어떻게 되는걸까?

뭐 이런저런 생각이 들었다.

 

요청에서의 Content-Type와 accept 헤더의 차이가 궁금해졌다. 아래 글에서 잘 설명해주셔서 첨부한다.

 

Content-Type 과 accept의 차이

https://webstone.tistory.com/66

 

Contents-Type Header 와 Accept Header의 차이점

Content-Type: HTTP 메시지(요청과 응답 모두)에 담겨 보내는 데이터의 형식을 알려주는 헤더이다. HTTP 표준 스펙을 따르는 브라우저와 웹서버는 Content-Type 헤더를 기준으로 HTTP 메시지에 담긴

webstone.tistory.com

라고 한다.

 

처음에 위 에러 해결할 때 Content-Type이랑 accept를 둘다 썼었다.

이렇게 말이다. Content-Type도 쓰고 accept도 쓰고.

 

내 요청은 GET이었기 때문에 요청 body가 없고, 따라서 Content-Type이 적용될 것도 없다. 이 요청에서만큼은 쓸데 없는 헤더다.

나한테 필요한 건 accept였지..!

 

좀 더 확인이 필요한 부분 : 위 블로그 문장 보다가 궁금해졌는데,

1. POST, PUT에서 요청메시지 바디에 대한 타입 정보 줄 때 Content-Type에 text/html, application/json 설정한다했는데, 그럼 accept랑 같이 쓰면 각각 다른 역할을 하는 거 맞는지 공식 답변 확인하고 싶다. 이럴 경우 content-type은 "제가 지금 보내는 메시지 바디가 이 타입이에요~"를 말하고, accept는 "서버 너가 나한테 줄 때는 이 타입으로 줘~"라는 의미이므로 두 필드의 역할이 달라진다.

 

암튼 좀 제대로 공식 문서를 읽어봐야겠다. 이건 담주에.. 보충을~

728x90
Comments