GET 요청 시 body 사용을 권장하지 않는 이유

Paya·2024년 4월 16일

Dansup 프로젝트

목록 보기
5/6
post-thumbnail

Dansup 프로젝트에서, 검색창에 댄서 이름을 입력했을 때 서버로부터 해당되는 댄서 데이터를 받아와야 했다.

처음에 백엔드에서 댄서 검색어를 body에 담아 GET 요청을 보내면 해당되는 댄서 데이터를 보내주는 구조의 api를 만들어 주었기 때문에, 프론트에서 api 요청 함수 코드를 이렇게 작성했었다.

const getFilterdDancerList = async (searchWord) => {
  const response = await axios.get('/profile', 
      { nickname: searchWord }  //body                          
  );
  
  return response.data;
};

😥 그런데, 서버로부터 데이터가 제대로 받아와지지 않았다..!!

api가 '백엔드'에서는 잘 동작되지만 '프론트엔드'에서는 잘 동작하지 않았다...


그래서 mdn 사이트를 찾아보니 이렇게 나와있었다.

Sending body in a GET request may cause some existing implementations to reject the request — while not prohibited by the specification, the semantics are undefined.
It is better to just avoid sending body in GET requests.

📙 GET 요청 시 body를 사용하는 것은
금지되어 있지는 않지만, 의미가 정의되어 있지 않아 요청을 거부당할 수 있어 '권장하지 않는다'
고 나와있다.


GET 요청 시 body를 사용하는 것을 권장하지 않는 이유를 GET 메서드의 특징과 관련하여 더 구체적으로 알아보고자 한다.


이유를 알아보기 전에 먼저 HTTP에 대해서 간단히 알아보자.

HTTP란 서버와 클라이언트가 서로 데이터를 주고받기 위해 사용되는 통신 규약(프로토콜)이다.
HTTP 통신은 클라이언트가 서버에 요청(request)을 보내면, 서버가 클라이언트에게 응답(response)을 보내는 구조로 이루어진다.


HTTP 메시지는 기본적으로 start-line, header, empty-line, body로 구성되어 있다.
HTTP 메서드 종류에 따라 body가 포함될 수도 있고 아닐 수도 있다.


HTTP 메서드란 클라이언트와 서버 사이에 이루어지는 요청(request)과 응답(response) 데이터를 전송하는 방법이다. 쉽게 말하면 서버가 주어진 리소스에 수행하길 원하는 행동을 서버에게 보내는 방법이다.

주요 HTTP 메서드에는 이런 것들이 있다.

  • GET : 리소스 조회
  • POST : 리소스 생성
  • PUT : 리소스 수정
  • PATCH : 리소스 일부 수정
  • DELETE : 리소스 삭제

💡 이제, GET 요청 시 body를 사용하는 것을 권장하지 않는 이유를 GET 메서드의 특징과 관련하여 구체적으로 알아보자.

  1. GET 메서드의 목적은 리소스를 조회하는 것이다.
    그런데 GET 요청 시 데이터를 body에 담아 전달하면, GET 메서드의 목적을 흐리기 때문에 표준 HTTP 규약에 어긋난다.

  2. GET 메서드는 동일한 요청을 반복적으로 보내도 결과가 변하지 않는 특성인 멱등성을 가지고 있다.
    그런데 GET 요청 시 데이터를 body에 담아 전달하면, body가 결과에 영향을 미칠 수 있어 멱등성을 해칠 수 있다.

  3. GET 요청에 의한 결과는 캐시되어 재사용될 수 있다.
    그런데 GET 요청 시 데이터를 body에 담아 전달하면, body의 캐시 키의 복잡성 문제로 캐싱이 동작하지 않는다.

  4. GET 요청 시 데이터를 URL 쿼리 스트링에 담아 전달하면, 북마크가 가능하다.
    그런데 GET 요청 시 데이터를 body에 담아 전달하면, 북마크가 불가능하다.


✨ 위와 같은 이유로 GET 요청 시 데이터를 전달하고자 한다면
body에 담아 전달하지 말고, URL 쿼리 스트링를 통해 전달하는 것이 좋다..!

하지만, 전달하고자 하는 데이터가 민감한 정보를 담고 있거나 / 길이가 길다면,
데이터를 URL 쿼리 스트링에 담아 GET 요청을 보내 리소스를 조회하는 방식 말고
데이터를 body에 담아 POST 요청을 보내 리소스를 조회하는 방식을 사용하는 것이 좋다..!
(이때, POST 메서드는 리소스 '조회' 목적으로 사용될 수 있다.)

⇒ 이유가 뭘까? 🤔

  • 민감한 정보를 담은 데이터를 URL 쿼리 스트링에 담아 보내면
    데이터가 URL의 일부로 전송되고 그 때문에 브라우저 히스토리에 저장되며 서버가 플레인 텍스트로 로그를 남겨 보안상 좋지 않다.
  • 데이터를 URL 쿼리 스트링에 담아 보내면
    URL 길이가 제한되기 때문에 데이터 길이도 제한되지만,
    데이터를 body에 담아 보내면
    길이 제한 없이 데이터를 전달할 수 있다.

단, 데이터를 body에 담아 POST 요청을 보내 리소스를 조회하는 방식은 캐싱이 되지 않는다.


문제 해결 ✨

댄서 검색어를 body에 담아 GET 요청을 보내면 해당되는 댄서 데이터를 보내주는 구조의 기존의 api는 '백엔드'에서는 잘 동작되지만 '프론트엔드'에서는 잘 동작되지 않았기 때문에
위와 같은 이유를 백엔드 개발자님께 직접 설명드렸다.

전달하고자 하는 데이터인 댄서 검색어는 민감한 정보가 아니고 길이가 길지 않기 때문에
댄서 검색어를 URL 쿼리 스트링에 담아 GET 요청을 보내면 해당되는 댄서 데이터를 보내주는 구조로 api를 수정해주셨다...!

프론트에서 수정한 api 요청 함수 코드는 다음과 같다.

const getFilterdDancerList = async (searchWord) => {
  const response = await axios.get('/profile', 
      {
	    params: { nickname: searchWord }
	  } //쿼리 스트링                   
  );
  
  return response.data;
};

출처: https://apidog.com/blog/http-get-request-with-body/

0개의 댓글