[HTTP 에러] 415 Unsupported Media Type (@RequestBody 관련)

jyleever·2022년 5월 23일
0

Helpring 에러 로그

목록 보기
6/12
post-custom-banner

415 Unsupported Media Type Error

리뷰 데이터 저장하기 위해 컨트롤러로 파라미터를 매핑하는 과정에서 415 error가 발생했다.

간단히 말하자면 415 Unsupported Media Type 에러는 지원되지 않는 형식으로 클라이언트가 요청을 해서 서버가 요청에 대한 승인을 거부한 오류를 의미한다. 이럴 경우에는 ContentType, Content Encoding 데이터를 확인할 필요가 있다.

우선 파라미터로 컨트롤러와 매핑하는 방법 중 하나인 RequestBody에 대해 잠깐 알아보자.

RequestBody

@RequestBody는 클라이언트가 전송하는 Json(application/json) 형태의 HTTP Body 내용을 Java Object로 변환시켜주는 역할을 한다. 따라서 Body가 존재하지 않는 Get 메소드에 @RequestBody를 활용하려고 한다면 에러가 발생하게 된다.

@RequestBody로 받는 데이터는 Spring에서 관리하는 MessageConverter들 중 하나인 MappingJackson2HttpMessageConverter를 통해 Java 객체로 변환된다.

form 태그를 사용하여 전송할 경우 Default ContentType은 application/x-www-form-urlencoded 이다.

@RequestBody는 JSON 형태로 데이터가 들어오면 해당 json 데이터를 jackson 라이브러리를 사용하여 model 객체로 변환한다. 따라서 ContentType 이 (application/json) 이어야 한다.

원인

현재 서버단에서는 review를 저장하는 컨트롤러에서 @RequestBody 타입으로 객체를 받아오도록 했다.
그런데 view단에서 리뷰를 작성할 때에는 form 데이터로 설정하고 ContentType을 수정하지 않았기 때문에 기본 ContetntType인 application/x-www-form-urlencoded로 요청이 전달되므로 415 에러가 발생한 것이다.

해결

  1. server단의 컨트롤러에서 파라미터를 매핑하는 방식을 @ModelAttribute 로 변경하거나
  2. view단에서 ajax 통신 시 리뷰 작성 형식을 form 데이터 형식이 아닌 json 형태로 데이터를 넘겨주기로 했다. (contentType : 'application/json')
  • 나는 리뷰 작성 형식을 form 데이터 형식이 아닌 json 형태로 데이터를 넘겨주는 방법을 채택하여 오류를 해결했다.
<div class="mb-3" name="reviewForm" id="reviewForm" method="post">
  <fieldset>
      <span class="text-bold">별점을 선택해주세요</span>
      <input type="radio" name="reviewStar" value="5" id="rate1"><label for="rate1"></label>
      <input type="radio" name="reviewStar" value="4" id="rate2"><label for="rate2"></label>
      <input type="radio" name="reviewStar" value="3" id="rate3"><label for="rate3"></label>
      <input type="radio" name="reviewStar" value="2" id="rate4"><label for="rate4"></label>
      <input type="radio" name="reviewStar" value="1" id="rate5"><label for="rate5"></label>
  </fieldset>
  <div>
      <textarea class="col-auto form-control" type="text" id="reviewContents" placeholder="수강평을 남겨보세요"></textarea>
  </div>
</div>
<button class="col-auto btn btn-primary btn-lg" id="review-write-btn">리뷰 등록</button>
    /** 리뷰 작성 **/
    $("#review-write-btn").click(function () {
        const reviewStar = $('[name=reviewStar]:checked').val()
        const reviewContents = $("#reviewContents").val();
        const lectureId = $("#lectureId").val();
        const data = {
            'rate': reviewStar,
            'content': reviewContents,
        }
        $.ajax({
            type: 'post',
            url: '/rest/lecture/review/' + lectureId,
            data: JSON.stringify(data),
            contentType : 'application/json; charset=utf-8',
            beforeSend: function(xhr){
                xhr.setRequestHeader(header, token);
            }
        }).done(function(){
            window.location.reload();
        }).fail(function(error){
            alert(JSON.stringify(error));
        })
    });

참고
https://velog.io/@cms02/Spring-RequestBody

post-custom-banner

0개의 댓글