Spring(Web)

검색 조건이 담긴 Body를 쓰는 HTTP 요청 METHOD는 GET일까 POST일까?

kjy0349 2024. 4. 27. 21:37

Http Standard로는, Get 요청에는 Body가 존재하지 않는다. 모든 데이터를 QueryString으로 처리할 뿐이다. 하지만, 복잡한 검색 조건이 담긴 필터링은 JSON 필터 정보들을 담을 공간이 필요하다. 이때 검색을 위해서는 HTTP METHOD GET을 써야할까, POST를 써야할까?

StackOverflow에서도 POST 요청을 사용하는 것이 좋다고 하지만, 확신을 가질 수 없었다.

https://stackoverflow.com/questions/20550514/post-or-get-in-a-search-form

그래서 HTTP Protocol에 대한 RFC 문서를 찾아보며 각 METHOD를 사용할 때를 가정한 후 결정을 내렸다.

GET

  1. GET을 사용한다. 하지만, 일반적으로 Get 요청에는 @RequestBody 어노테이션이 작동하지 않는다. Header 용량 제한도 브라우별로 다르지만 존재한다.
   A payload within a GET request message has no defined semantics;
   sending a payload body on a GET request might cause some existing
   implementations to reject the request.

( https://www.rfc-editor.org/rfc/rfc7231#section-4.3.1 RFC 7321 - GET)

RFC 7231에 있는 GET Section을 보면 GET 요청의 payload는 정의되지 않았지만, GET 요청에 body를 담아 보내는것은 해당 request의 요청이 거부될 수 있다는 점을 지적하고 있다.

그래서 GET 요청에 Body를 담아 필터링 검색 요청을 한다는 생각은 접어두었다.

 

POST

  1. POST를 사용한다. 하지만, POST 요청은 게시글을 작성하는 것과 같은 데이터베이스에 변경이 생길 때 쓰는 HTTP METHOD로 알고 있다. 그래서 실제 데이터베이스에 변경이 일어나지 않기 때문에 고민이 된다.
  2. 그래서 상용서비스에서는 어떻게 사용하고 있는지 찾아보았다. 가장 쉽게 찾을 수 있는 곳은, 네이버 지도였다. 지도에서 검색한 후, 영업 중/분위기 좋은 과 같은 필터들을 이용해 검색 결과를 필터링 할 수 있었다.
  3. network단을 뜯어보니, graphgl을 사용 중 이었다. REST API 통신은 아니기 때문에 이에 대한 예로 사용되기엔 어려워 보였다.

그래서 RFC 7231(http 1.1) 문서를 보고, 힌트가 될 만한 문장을 찾았다.

4.3.3.  POST

   If the result of processing a POST would be equivalent to a
   representation of an existing resource, an origin server MAY redirect
   the user agent to that resource by sending a 303 (See Other) response
   with the existing resource's identifier in the Location field.  This
   has the benefits of providing the user agent a resource identifier
   and transferring the representation via a method more amenable to
   shared caching, though at the cost of an extra request if the user
   agent does not already have the representation cached.

(https://www.rfc-editor.org/rfc/rfc7231#section-4.3.3 RFC 7321 - POST)

 

→ POST 요청을 처리한 이후 기존 리소스에 변경이 없을 경우, 서버는 user에게 303(See other) 응답을 보낼 것이다.

(RFC에서 사용되는 MAY와 같은 단어는 규격화된 의미를 가지고 있다. 아마도 보다는 OPTIONAL과 같은 뜻으로 쓰인다. https://datatracker.ietf.org/doc/html/rfc2119 RFC2119)

 

이 부분을 보니, 데이터베이스에 변경을 일으키지 않는 요청도 POST로 사용할 수 있다는 말로 이해가 되었다.

추가적인 힌트도 얻게 되었는데, POST로 검색 요청을 할 경우 GET과 같이 캐싱이 되지 않기 때문에 결국 조회 이후에 GET 요청으로 검색 결과를 볼 수 있게 만들어야 한다. 이 때, 303 요청을 받고 GET 요청으로 변경해 검색결과 조회 페이지로 보낼 수 있다는 뜻이다.

하지만 현재 개발 중인 서비스의 프론트가 SPA로 구현되고 있기 때문에, 이 부분을 적용하기에는 조금 어려워 보였다.

결론

검색 조건 필터링과 같이 데이터베이스에 변경은 없지만 BODY가 필요한 경우, POST를 사용할 수 있다.