open:graphql-caching

GraphQL Caching

개체 식별자를 제공하면 클라이언트가 풍부한 캐시를 구축할 수 있습니다.1)

엔드포인트 기반 API에서 클라이언트는 HTTP 캐싱을 사용하여 리소스를 쉽게 다시 가져오는 것을 방지하고 두 리소스가 동일한 경우를 식별할 수 있습니다. 이러한 API의 URL은 클라이언트가 캐시를 구축하는 데 활용할 수 있는 전역적으로 고유한 식별자입니다. 그러나 GraphQL에는 주어진 객체에 대해 이 전역적으로 고유한 식별자를 제공하는 URL과 유사한 프리미티브가 없습니다. 따라서 API가 클라이언트가 사용할 수 있도록 이러한 식별자를 노출하는 것이 모범 사례입니다.2)

이에 대한 한 가지 가능한 패턴은 id와 같은 필드를 전역 고유 식별자로 예약하는 것입니다. 이 문서 전체에서 사용되는 예제 스키마는 다음 접근 방식을 사용합니다.3)

{
  starship(id:"3003") {
    id
    name
  }
  droid(id:"2001") {
    id
    name
    friends {
      id
      name
    }
  }
}

{
  "data": {
    "starship": {
      "id": "3003",
      "name": "Imperial shuttle"
    },
    "droid": {
      "id": "2001",
      "name": "R2-D2",
      "friends": [
        {
          "id": "1000",
          "name": "Luke Skywalker"
        },
        {
          "id": "1002",
          "name": "Han Solo"
        },
        {
          "id": "1003",
          "name": "Leia Organa"
        }
      ]
    }
  }
}

이것은 클라이언트 개발자에게 전달할 수 있는 강력한 도구입니다. 리소스 기반 API의 URL이 전역적으로 고유한 키를 제공한 것과 같은 방식으로 이 시스템의 id 필드는 전역적으로 고유한 키를 제공합니다.4)

백엔드가 식별자에 대해 UUID와 같은 것을 사용하는 경우 이 전역적으로 고유한 ID를 노출하는 것은 매우 간단할 수 있습니다! 백엔드에 이미 모든 개체에 대해 전역적으로 고유한 ID가 없는 경우 GraphQL 계층에서 이를 구성해야 할 수 있습니다. 종종 유형의 이름을 ID에 추가하고 이를 식별자로 사용하는 것만큼 간단합니다. 그런 다음 서버는 base64로 인코딩하여 해당 ID를 불투명하게 만들 수 있습니다.5)

선택적으로 이 ID는 전역 개체 식별의 노드 패턴으로 작업하는 데 사용할 수 있습니다.6)

이 목적으로 id 필드를 사용할 때의 한 가지 문제는 GraphQL API를 사용하는 클라이언트가 기존 API와 작동하는 방식입니다. 예를 들어 기존 API가 유형별 ID를 허용했지만 GraphQL API가 전역적으로 고유한 ID를 사용하는 경우 두 가지를 동시에 사용하는 것이 까다로울 수 있습니다.7)

이러한 경우 GraphQL API는 이전 API의 ID를 별도의 필드에 노출할 수 있습니다. 이를 통해 두 가지 장점을 모두 누릴 수 있습니다.8)

  • GraphQL 클라이언트는 전역적으로 고유한 ID를 얻기 위해 일관된 메커니즘에 계속 의존할 수 있습니다.9)
  • 이전 API로 작업해야 하는 클라이언트는 객체에서 previousApiId를 가져와 사용할 수도 있습니다.10)

글로벌 고유 ID는 과거에 강력한 패턴으로 입증되었지만 사용할 수 있는 유일한 패턴이 아니며 모든 상황에 적합하지도 않습니다. 클라이언트가 필요로 하는 정말 중요한 기능은 캐싱에 대해 전역적으로 고유한 식별자를 파생시키는 기능입니다. 서버가 해당 ID를 파생하도록 하면 클라이언트가 단순화되지만 클라이언트도 식별자를 파생할 수 있습니다. 종종 이것은 객체의 유형(__typename으로 쿼리됨)을 일부 유형 고유 식별자와 결합하는 것처럼 간단합니다.11)

또한 기존 API를 GraphQL API로 교체하는 경우 전역적으로 고유하게 변경된 id를 제외하고 GraphQL의 모든 필드가 동일하면 혼동될 수 있습니다. 이것이 id를 전역적으로 고유한 필드로 사용하지 않기로 선택하는 또 다른 이유입니다.12)



1)
Providing Object Identifiers allows clients to build rich caches
2)
In an endpoint-based API, clients can use HTTP caching to easily avoid refetching resources, and for identifying when two resources are the same. The URL in these APIs is a globally unique identifier that the client can leverage to build a cache. In GraphQL, though, there's no URL-like primitive that provides this globally unique identifier for a given object. It's hence a best practice for the API to expose such an identifier for clients to use.
3)
One possible pattern for this is reserving a field, like id, to be a globally unique identifier. The example schema used throughout these docs uses this approach:
4)
This is a powerful tool to hand to client developers. In the same way that the URLs of a resource-based API provided a globally unique key, the id field in this system provides a globally unique key.
5)
If the backend uses something like UUIDs for identifiers, then exposing this globally unique ID may be very straightforward! If the backend doesn't have a globally unique ID for every object already, the GraphQL layer might have to construct this. Oftentimes, that's as simple as appending the name of the type to the ID and using that as the identifier; the server might then make that ID opaque by base64-encoding it.
6)
Optionally, this ID can then be used to work with the Global Object Identification's node pattern.
7)
One concern with using the id field for this purpose is how a client using the GraphQL API would work with existing APIs. For example, if our existing API accepted a type-specific ID, but our GraphQL API uses globally unique IDs, then using both at once can be tricky.
8)
In these cases, the GraphQL API can expose the previous API's IDs in a separate field. This gives us the best of both worlds:
9)
GraphQL clients can continue to rely on a consistent mechanism for getting a globally unique ID.
10)
Clients that need to work with our previous API can also fetch previousApiId from the object, and use that.
11)
While globally unique IDs have proven to be a powerful pattern in the past, they are not the only pattern that can be used, nor are they right for every situation. The really critical functionality that the client needs is the ability to derive a globally unique identifier for their caching. While having the server derive that ID simplifies the client, the client can also derive the identifier. Oftentimes, this would be as simple as combining the type of the object (queried with __typename) with some type-unique identifier.
12)
Additionally, if replacing an existing API with a GraphQL API, it may be confusing if all of the fields in GraphQL are the same except id, which changed to be globally unique. This would be another reason why one might choose not to use id as the globally unique field.
  • open/graphql-caching.txt
  • 마지막으로 수정됨: 2022/09/06 02:07
  • 저자 127.0.0.1