[Web]HTTP와 REST와 GraphQL까지 모두 쌈싸먹기

Euiyeon Park·2024년 8월 23일

Web

목록 보기
7/13
post-thumbnail

REST과 관련된 이론을 포스팅하면서 공부하다보니
여러 개념들이 유기적으로 연결되어 있는데,
어떤 포스트에 추가를 할까 하다가 그냥 새로 하나 파기로 했다 ..


이 포스트를 작성하게 된 계기는 Idempotent(멱등성) 때문이다.
그냥 지나치기엔 아쉽고(?) 작성하기엔 이것 저것 다른 얘기도 끄집어 내야될 거 같고
무튼 렛츠고 🚗

🍧멱등성(Idempotent)

멱등성(Idempotent)이란 ,
같은 요청을 여러 번 보내도 결과가 동일하게 유지지되는 성질
을 의미한다.
즉, 멱등한 작업의 결과는 한 번을 수행하든 여러 번 수행하든 동일하게 유지된다.

멱등성REST의 특징을 정리하면서 접한 개념인데,
REST의 특징보다는 HTTP의 메서드가 가진 속성으로 이해하는 것이 더 좋을 것 같다.

하지만 REST웹의 구조와 HTTP의 원칙을 기반으로
웹 서비스와 API를 설계
하기 때문에 HTTP의 속성에 대해 짚어보고 가자


🍧HTTP Method에 멱등성이 필요한 이유

🍭 1. 안정성 및 예측 가능성

멱등성은 클라이언트가 네트워크 문제나 서버 오류 등으로 인해
동일한 요청을 여러 번 보내야 할 때,
서버의 상태가 예측 가능한 방식으로 유지되도록 한다.

즉, 같은 요청을 여러 번 보내더라도 결과가 변화지 않으므로
클라이언트는 결과를 안정적으로 처리할 수 있다.

또한 클라이언트는 멱등성을 통해 요청이 중복되더라도 시스템의 상태가
변하지 않음을 확신할 수 있으므로 요청의 결과를 예측하고 처리할 수 있다.

🍭 2. 중복 요청 처리

네트워크 지연, 실패 또는 다른 문제로 인해 클라이언트가 같은 요청을 다시 보내는 경우,
멱등성으로 인해 서버는 요청이 중복된 것을 감지하고 동일한 결과를 반환할 수 있다.
이는 중복 작업을 방지하고 데이터의 일관성을 유지하도록 한다.


🍧HTTP Method

모든 HTTP Method가 멱등성을 보장하지 않는다.

출처

🍭 멱등성을 가지는 HTTP Mehthod

  • GET
    • 서버에서 리소스를 조회한다.
    • GET 요청은 서버의 상태를 변경하지 않으므로,
      여러 번 호출해도 동일한 결과를 반환한다.
  • PUT
    • 특성 리소스를 생성하거나 업데이트한다.
    • PUT 요청은 지정된 리소스의 상태를 특정 값으로 설정한다.
      같은 PUT요청을 여러 번 보내도 리소스는 항상 동일한 상태로 유지된다.
  • DELETE
    • 특정 리소스를 삭제한다.
    • DELETE요청은 리소스를 삭제하므로, 리소스가 삭제된 경우
      추가적인 DELETE요청을 보내도 리소스의 상태는 동일하게 유지된다.
  • HEAD
    • 클라이언트가 요청한 URI의 컨텐츠가 웹 서버에 존재하는지 여부를 확인한다.
    • GET요청과 유사하지만 응답 본문이 없고 헤더 정보만 반환한다.
  • OPTIONS
    • 웹 서버에서 지원하는 HTTP 요청 방식을 확인한다.
    • 서버가 해당 리소스에 대해 어떤 메서드를 지원하고 어떤 권한을 가지고 있는지 확인한다.
  • TRACE
    • 클라이언트가 서버로 보낸 요청이 어떻게 도달했는지 네트워크 경로를 추적한다.

🍭 멱등성을 가지지 않는 HTTP Mehthod

  • POST
    • 서버에 데이터를 제출하거나 리소스를 생성한다.
    • POST요청은 서버의 상태를 변경할 수 있으며,
      같은 POST요청을 여러번 보내면 새로운 리소스가 생성되거나 데이터가 변경될 수 있다.
  • PATCH
    • 특정 리소스의 일부만 업데이트한다.

PUT은 멱등성, 그런데 PATCH는?

PUTPATCH는 둘 다 리소스를 수정하는데 사용된다.
하지만 PUT과 다르게 PATCH는 항상 멱등성을 보장하지 않는다.

그니까 왜...?

🍭 PUT 메소드

PUT 요청은 특정 리소스의 전체 상태를 지정된 데이터로 완전히 교체한다.
리소스가 요청 본문에 정의된 상태로 설정되어 완전히 교체된다.
따라서 PUT 요청을 여러 번 보내더라도 서버의 리소스는 항상 동일하게 유지된다.

예를 들어, PUT/products/100 요청을 보내면서
본문에 {"name":"Laptop", "price":1000}을 포함시키면
product id 100의 정보는 항상 Laptop 이라는 이름과 100의 가격으로 설정된다.

만약 리소스가 이미 {"name":"Laptop", "price":1000} 인 상태라면
동일한 PUT요청을 여러 번 보내도 상태는 변하지 않으므로 멱등성이 유지된다.

🍭 PATCH 메소드

PATCH 메서드는 요청의 구체적인 내용과 서버 구현에 따라 멱등성의 여부가 달라진다.

PATCH 메서드는 리소스의 전체를 교체하지 않고, 특정 부분만 업데이트한다.
(사용자 프로필에서 이메일 주소만 변경하거나, 문서의 특정 필드만 수정하는 등)
요청의 본문에는 수정하고자 하는 리소스의 특정 부분에 대한 정보만 포함된다.

  • PATCH요청이 특정 필드를 값 X로 설정하도록 한다면
    여러 번 요청을 보내더라도 리소스의 해당 필드는 항상 X로 설정되므로 멱등성이 유지된다.

    PATCH /user/123 HTTP/1.1
    Host: example.com
    Content-Type: application/json
    
    {
      "email": "newemail@example.com"
    } 
  • 만약 PATCH 요청이 특정 값을 추가하거나, 증가시키는 방식이라면
    동일한 요청이 반복될 때마다 리소스의 상태가 계속 변화할 수 있으므로 멱등성이 유지되지 않는다.

    PATCH /inventory/456 HTTP/1.1
    Host: example.com
    Content-Type: application/json
    
    {
      "quantity": +10
    }

🍧HTTP와 REST를 쌈싸먹자

HTTP의 멱등성과 REST API는 밀접한 관계가 있다.
REST API를 설계할 때 멱등성을 이해하고 활용하는 것은
클라이언트와 서버 간의 신뢰성과 일관성을 유지하는데 중요한 역할을 한다.

또한 멱등성은 REST의 주요 원칙인

  • 클라이언트-서버구조와
  • 무상태성(Stateless)

맞물려 서버의 상태를 안정적으로 유지하는데 도움을 준다.

🍧근데 여기서 GraphQL도 쌈싸먹는다구?

사실 RESTGraphQL모두 HTTP를 기반으로 하기에 셋 다 쌈싸먹는게 이상한건 아니다.
REST와 GraphQL을 톺아보면서 HTTP 메소드 중 GETPOST의 차이에 대해서 알아보고,
거기에 이번 포스팅 주제인 멱등성에 대해서도 알아보자

🍭 GraphQL와 HTTP 멱등성

GraphQL단일 엔드포인트에서 클라이언트가 필요한 데이터를 쿼리하는데 집중된 API다.
REST와 달리 여러 자원을 한 번의 요청으로 처리할 수 있다.

GraphQL은 기본적으로 POST 요청을 통해 데이터를 전송하는데,
POST 메소드는 위에서 살펴본 바와 같이 멱등성을 보장하지 않는다.
동일한 GraphQL 쿼리를 여러 번 실행하면, 그 결과는 서버 상태에 따라 달라질 수 있다.

GraphQL에서 멱등성을 고려하려면 QueryMutation을 구분해야 한다.

  • Query
    • 데이터를 조회하는데 사용되며, REST의 GET과 유사하게 멱등성을 가진다.
    • 여러 번 쿼리해도 서버의 상태는 변하지 않는다.
  • Mutation
    • 서버의 상태를 변경하는 작업을 수행하며, REST의 POST과 유사하게 작동한다.
    • 일반적으로 멱등성을 가지지않는다.

RESTHTTP 메소드의 멱등성 여부를 고려해 API를 설계해야되는 반면
GraphQLQueryMutation으로 멱등성을 고려한다.

🍭 근데 GraphQL은 왜 POST 메소드를 주로 사용할까?

GraphQL에서 쿼리가 단순하고 짧을 때 GET메소드도 사용할 수 있다.
GET /graphql?query={user(id:1){name, age}}

1. 쿼리의 복잡성

GraphQL 쿼리는 복잡하고, 변수가 많아지거나 길어질 수 있다.
이 경우에 GET메소드로 요청을 보내면 쿼리 문자열이 URL에 포함되어야 하는데
URL길이 제한에 걸릴 수 있다.
POST 메소드는 요청 본문(body)에 쿼리와 변수를 포함하므로,
길이에 대한 걱정 없이 복잡한 쿼리를 보낼 수 있다.

2. 보안

쿼리와 변수를 본문에 포함하면 민감한 데이터가 URL에 노출되지 않기 떄문에
보안 측면에서도 POST 메소드가 선호된다.


🍧HTTP Method, REST, GraphQL 삼합

위에서부터 HTTP의 속성과 메소드가 REST와 GraphQL과 어떤 관련이 있는지 살펴봤다.
그런데 또 하나는 GET 메소드와 POST 메소드의 차이다.
GET과 POST는 멱등성(Idempotent)에서도 차이가 있지만,
캐시(Cacheable)에서도 차이가 있다
(메소드의 특징이 REST와 GraphQL의 차이를 나타내기두 하고 ..)

🍭 GET 메소드의 캐시

GET은 데이터를 조회하는데 사용되며, GET 요청의 결과는 서버의 상태를 변경하지 않는다.
따라서 GET 요청의 응답은 캐시될 수 있다.

웹 브라우저CDN 등에서 GET 요청에 대한 응답을 캐시하여
같은 요청에 대해 서버를 다시 호출하지 않고도 빠르게 응답을 제공할 수 있다.

캐시 가능성은 성능 최적화와 네트워크 대역폭 절약에 도움을 준다.

🍭 POST 메소드의 캐시

POST는 서버의 상태를 변경하거나 데이터를 생성하는데 사용되며
POST 요청의 결과는 서버의 상태를 변화시키는 작업을 포함할 수 있기 때문에
일반적으로 POST 요청에 대한 응답은 캐시되지 않는다.

POST 요청은 데이터 전송의 안전성을 보장하고, 서버의 상태 변경을 유도하기 때문에
브라우저프록시 서버에서 POST 요청에 대한 응답을 캐시하지 않는 것이 표준동작이다.

🍭 삼합 결론

GET 요청은 URL에 쿼리 매개변수를 포함하여 데이터를 요청한다.
따라서 요청 URL이 동일하면 캐시된 응답을 재사용할 수 있다.
REST에서는 문제가 없지만, GraphQL에서는 쿼리가 복잡할 수 있어
URL 길이 제한에 걸릴 수 있다.

POST 요청은 서버의 상태를 변경하는 요청이기에
응답이 항상 최신 상태를 반영해야 하므로 캐시를 사용하지 않는다.
REST는 데이터 조회를 할때 GET요청을 사용하고 응답을 캐시할 수 있지만,
GraphQL은 데이터 조회에서도 POST요청을 주로 사용하므로 응답을 캐시할 수 업다.

따라서 GraphQL에서 캐시를 사용하기 위해서는 Client-side Caching을 위한 라이브러리를 사용하여 서버의 응답을 캐시하고 재사용할 수 있다.


이것저것 관련된 개념을 엮어 엮어 정리하기 위해 해당 포스트를 작성했는데,
어지럽다 ..
A를 공부하면 B가 나오고, B를 공부하면 C가 나오고.. like 끊임없는 두더지 잡기 게임 ..

포스트 마무리는 쌈밥 사진으로 마무리해야겠다.

출처

ref

https://restfulapi.net/idempotent-rest-apis/
https://velog.io/@wujin/HTTP-Method-OPTIONS-HEAD-TRACE

profile
"개발자는 해결사이자 발견자이다✨" - Michael C. Feathers

0개의 댓글