GraphQL schema 위임 (GraphQL schema delegation)

GraphQL query 섹션(section)을 자동으로 subschema 로 전달
graphql-tools library 에서 GraphQL schema delegation 및 shcema stitching 작업을 하고 있는 Mikhail Novikov 가 기고한 아티클 입니다. 현재 그는 GraphQL 을 원격 지원하고 있습니다. GraphQL 에 대한 도움이 필요하다면 freiksenet@reindex.io 로 연락 바랍니다.
이번 아티클에서는 GraphQL query (또는 그 일부)를 자동으로 다른 schema 로 전달하는 방법인—schema delegation 에 대해 이야기할 것 입니다. Schema delegation 을 사용하면 별도로 query 하지 않고도 다른 schema 의 일부를 재사용할 수 있습니다. 이를 활용하기 위한 적합한 사례는 아래와 같습니다:
  • 기본적인 GraphQL 마이크로서비스(microservices)에 query를 전달하는 GraphQL 게이트웨이(gateway) 구축
  • schema 일부를 타사(third-party) GraphQL API 사용
  • Prisma 와 같은 GraphQL 데이터베이스(database) proxy 사용

GraphQL 게이트웨이 구현하기

기본적인 blog API 를 위한 GraphQL 서비스(service)를 고려해 봅시다. schema 는 User 그리고 Blog—두가지 타입(types)을 가지고 있고요. 또한 _id 로 검색 가능한 root 필드(fields)도 존재 합니다. 서비스 상단에는 기본적인 GraphQL 서비스를 위한 Node 인터페이스(interface)를 구현하는 GraphQL 게이트웨이가 있습니다.
Node 는 일부 id 로 전역적(globally)인 호출 가능한 object 를 나타내는 GraphQL의 공통 인터페이스입니다. 일반적으로 Node 구현을 위한 타입(type)의 object를 id로 반환하는 node라는 root 필드와 결합됩니다. Node 인터페이스에 대한 자세한 내용은 해당 아티클을 참고해주세요.
게이트웨이는 Node 인터페이스 구현을 위해 동일한 UserBlog 타입(types)을 재사용 합니다. 또한 기존 두 필드(fields) 위에 node root 필드를 제공하고 있습니다. 다음은 서비스 및 게이트웨이 schema 입니다.
서비스 및 게이트웨이 schema

게이트웨이에서 userByIdblogById를 재배포 하는 대신 서비스 schema 를 이용한 query 가 실행됩니다. 이를 수행하기 위해 resolver— GraphQLResolveInfo의 네번째 인수(argument)로 제공되는 정보를 통해 query 작성이 가능합니다. 현재 resolver(fieldNodes)에서 시작하는 subquery, operation(fragments)에 사용된 프래그먼트 및 operation 변수(variables)가 있습니다. 이를 통해 GraphQL Document, print 를 생성 후 서비스 schema 로 보낼 수 있습니다.
서비스 필드(fields)와 일치하는 root 필드(fields)의 경우 별다른 작업을 수행할 필요가 없습니다. 하지만 node 와 같은 새로운 필드(fields)는 전역(global) id에 따라 root 필드 이름도 변경해야 합니다.
query 필터링(filtering)
위에 작성된 예제는 게이트웨이 와 서비스 에서 모두 사용 가능한 data만 선택하는 경우에 한해 적용 가능합니다. 아쉽게도 항상 이렇게 간단하진 않습니다. 그 이유는 기본(underlying) 서비스 schema의 Node 인터페이스에는 id 필드(fields)가 존재하지 않고 호환 가능한 타입(types)으로 프래그먼트(fragments)를 확산시킬 수 없기 때문입니다: UserBlog 프래그먼트(fragments)가 모든 query 에 분산되면 이는 실패한 케이스 입니다.
실패한 query 예제

이같은 문제를 해결하려면 delegation 은 호환되지 않는 필드(fields) 및 프래그먼트(fragments) 뿐 아니라 필터링 후에 사용하지 않는 필드(fields) 및 프래그먼트(fragments)도 필터링 해야 합니다. 물론 도큐먼트를 직접 살펴보면서 타입(types)을 추적한뒤 원본 schema 에 없는 모든 필드(fields)를 제거해도 됩니다. 하지만 graphql-tools 에 포함된 delegateToSchema 덕에 여러분이 직접 수정할 필요가 없습니다.
Schema delegation 은 원본 query를 subschema 와 일치하도록 자동으로 변경합니다.

delegateToSchema

delegateToSchema 는 기본 schema에 유효한 GraphQL query를 만들고 실행합니다.이는 아래와 같은 옵션(options) object 를 수락합니다:
  • schema 는 delegation된 query 를 처리해야하는 sub-schema 입니다.
  • operation 은 "query", "mutation" 또는 "subscription" 이며 GraphQL 도큐먼트의 operation 을 결정합니다.
  • fieldName 은 query를 시작할 schema의 root 필드 입니다.
  • args 는 필드에 전달할 추가적인 인수(arguments) object 입니다. 여기서 인수(arguments)는 parent schema의 원본 필드에 지정된 인수를 보완 및/또는 override 합니다.
  • context 는 실행을 위한 GraphQL 컨텍스트 입니다.
  • info 는 GraphQLResolveInfo 입니다. 변수(variables) 및 프래그먼트(fragments)와 함께 현재 query 의 선택(selection) 세트를 추출하는데 사용 됩니다.
  • transforms 는 GraphQL schema 변환(transforms) 배열 입니다. Transforms 에 더 자세한 내용은 다음 아티클 에서 다룰 예정입니다.
delegateToSchema 를 사용하는 게이트웨이 resolvers 는 다음과 같습니다:
게이트웨이 resolvers

다음은 node query 를 서비스 로 delegation하는 방법 입니다.
node 로 부터 query delegation

root 필드에서 전달하는 것 외에 delegateToSchema를 사용하여 또다른 모든 resolvers 에서도 delegation할 수 있습니다. 예를들어 UserBlog 타입(types)의 서비스(services)를 분리하면 각각의 서비스 즉, User 서비스에서 User.blogs 를 Blog 서비스에서 Blog.user 를 가져올 수 없습니다. 하지만 게이트웨이 서버에 연결하고 delegation을 사용하면 관련 data 를 가져올 수 있습니다:
presentation
Gist 로부터 가져온 code

Schema stitching 및 delegation

Schema delegation 은 종종 schema stitching과 함께 사용 됩니다. Schema stitching은 여러개의 GraphQL schema를 결합하는 프로세스입니다. 특히 서비스가 여러개인 경우—게이트웨이 스키마 생성을 간소화 합니다. Schema stitching은 stitching된-schema들에 존재하는 root 필드(fields)에 대한 delegation을 자동으로 설정합니다. 신규 root 필드(root 필드가 아닌 새 필드)는 새로운 resolvers 가 필요 합니다. 이같은 게이트웨이 schema는 다음과 같이 생성할 수 있습니다:
mergeSchemas 예제

공식 문서를 통해 schema stitching을 좀 더 자세히 확인 할 수 있습니다.

추가 참고 목록

다음 주제로는, transforms 를 사용하여 schema delegation을 사용자 정의 하는 법을 다루려 합니다. schema transforms를 이용해 schema에 큰 변화가 생겼더라도 subschema에서 delegation 가능한 schema 기능은 그대로 유지할 수 있습니다.
업데이트 된 schema delegation 과 schema transforms는 graphql-tools version 3 에서 사용 가능하며 npm 을 통해 graphql-tools@next 로 제공되고 있습니다— 최종 버전의 API 가 출시 되기 전까지는 API 가 약간의 변경이 있을수 있음을 유의하세요. 아래 GiuHub 에서 PR 된 code 를 확인해 보세요.
GraphQL schema delegation 에 대해 더 자세히 알고 싶다면 아래 리소스(resources)를 확인해주세요:
  • 공식 문서
  • Graphcool 을 통해 설명한 GrahpQL Schema Stitching
  • GraphQL Bindings 문서. GraphQL Bindings 은 프로그래밍 방식의 API를 schema root 필드(fields)에 제공하는 잘 추상화된 schema delegation 입니다.

Ben Newman 과 Ville Immonen 에게 감사드립니다.

이글은 번역글입니다.
원문은 아래를 참고 바랍니다.