GraphQL Introspection
GraphQL 스키마가 지원하는 쿼리에 대한 정보를 요청하는 것이 종종 유용합니다. GraphQL을 사용하면 내성 시스템을 사용하여 그렇게 할 수 있습니다!1)
Star Wars 예제의 경우 starWarsIntrospection-test.ts 파일에는 자체 검사 시스템을 보여주는 여러 쿼리가 포함되어 있으며 참조 구현의 자체 검사 시스템을 실행하기 위해 실행할 수 있는 테스트 파일입니다.2)
우리는 유형 시스템을 설계했기 때문에 어떤 유형이 사용 가능한지 알 수 있지만, 그렇지 않은 경우 쿼리의 루트 유형에서 항상 사용할 수 있는 __schema
필드를 쿼리하여 GraphQL에 요청할 수 있습니다. 이제 그렇게 하고 어떤 유형을 사용할 수 있는지 물어보겠습니다.3)
{ __schema { types { name } } }
{ "data": { "__schema": { "types": [ { "name": "Query" }, { "name": "String" }, { "name": "ID" }, { "name": "Mutation" }, { "name": "Episode" }, { "name": "Character" }, { "name": "Int" }, { "name": "LengthUnit" }, { "name": "Human" }, { "name": "Float" }, { "name": "Droid" }, { "name": "FriendsConnection" }, { "name": "FriendsEdge" }, { "name": "PageInfo" }, { "name": "Boolean" }, { "name": "Review" }, { "name": "ReviewInput" }, { "name": "Starship" }, { "name": "SearchResult" }, { "name": "__Schema" }, { "name": "__Type" }, { "name": "__TypeKind" }, { "name": "__Field" }, { "name": "__InputValue" }, { "name": "__EnumValue" }, { "name": "__Directive" }, { "name": "__DirectiveLocation" } ] } } }
Group Types
우와 종류가 많네요! 그들은 무엇인가? 그룹화해 보겠습니다.4)
- Query, Character, Human, Episode, Droid : 이것들은 우리의 유형 시스템에서 정의한 것들입니다.5)
- String, Boolean : 타입 시스템이 제공한 내장 스칼라입니다.6)
__Schema, __Type, __TypeKind, __Field, __InputValue, __EnumValue, __Directive
: 이 모든 항목 앞에는 이중 밑줄이 표시되어 내부 검사 시스템의 일부임을 나타냅니다.7)
이제 어떤 쿼리를 사용할 수 있는지 살펴보기에 좋은 위치를 찾아 보겠습니다. 유형 시스템을 설계할 때 모든 쿼리가 시작되는 유형을 지정했습니다. 그것에 대해 내성 시스템에 물어보자!8)
{ __schema { queryType { name } } }
{ "data": { "__schema": { "queryType": { "name": "Query" } } } }
그리고 그것은 우리가 유형 시스템 섹션에서 말한 것과 일치합니다. 쿼리 유형은 우리가 시작할 곳입니다! 여기에서 명명한 것은 관례에 따른 것입니다. 쿼리 유형의 이름을 다른 이름으로 지정할 수 있으며 쿼리의 시작 유형으로 지정했다면 여전히 여기에 반환되었을 것입니다. 하지만 이름을 Query로 지정하는 것은 유용한 규칙입니다.9)
하나의 특정 유형을 조사하는 것이 종종 유용합니다. Droid 유형을 살펴보겠습니다.10)
{ __type(name: "Droid") { name } }
{ "data": { "__type": { "name": "Droid" } } }
하지만 Droid에 대해 더 알고 싶다면 어떻게 해야 할까요? 예를 들어 인터페이스인가 객체인가?11)
{ __type(name: "Droid") { name kind } }
{ "data": { "__type": { "name": "Droid", "kind": "OBJECT" } } }
kind
는 값 중 하나가 OBJECT인 __TypeKind
열거형을 반환합니다. 대신 Character에 대해 물으면 인터페이스라는 것을 알 수 있습니다.12)
{ __type(name: "Character") { name kind } }
{ "data": { "__type": { "name": "Character", "kind": "INTERFACE" } } }
객체가 어떤 필드를 사용할 수 있는지 아는 것이 유용하므로 Droid에 대한 내성 시스템에 물어보겠습니다.13)
{ __type(name: "Droid") { name fields { name type { name kind } } } }
{ "data": { "__type": { "name": "Droid", "fields": [ { "name": "id", "type": { "name": null, "kind": "NON_NULL" } }, { "name": "name", "type": { "name": null, "kind": "NON_NULL" } }, { "name": "friends", "type": { "name": null, "kind": "LIST" } }, { "name": "friendsConnection", "type": { "name": null, "kind": "NON_NULL" } }, { "name": "appearsIn", "type": { "name": null, "kind": "NON_NULL" } }, { "name": "primaryFunction", "type": { "name": "String", "kind": "SCALAR" } } ] } } }
그것들은 우리가 Droid에서 정의한 우리의 필드입니다!14)
id는 거기에서 약간 이상해 보입니다. 유형에 대한 이름이 없습니다. NON_NULL
종류의 “래퍼” 유형이기 때문입니다. 해당 필드의 유형에 대해 ofType을 쿼리하면 ID 유형이 발견되어 이것이 null이 아닌 ID임을 알려줍니다.15)
유사하게, friend
와 appearsIn
은 모두 LIST 래퍼 유형이기 때문에 이름이 없습니다. 우리는 이러한 유형에 대해 ofType을 쿼리할 수 있으며 이는 목록이 무엇인지 알려줍니다.16)
{ __type(name: "Droid") { name fields { name type { name kind ofType { name kind } } } } }
{ __type(name: "Droid") { name fields { name type { name kind ofType { name kind } } } } }
툴링에 특히 유용한 인트로스펙션 시스템의 기능으로 끝내자. 시스템에 문서를 요청합시다!17)
{ __type(name: "Droid") { name description } }
{ "data": { "__type": { "name": "Droid", "description": null } } }
따라서 우리는 내성을 사용하여 유형 시스템에 대한 문서에 액세스하고 문서 브라우저 또는 풍부한 IDE 환경을 만들 수 있습니다.18)
이것은 자기 성찰 시스템의 표면을 긁은 것뿐입니다. 열거형 값, 유형이 구현하는 인터페이스 등을 쿼리할 수 있습니다. 우리는 자기 성찰 시스템 자체를 성찰할 수도 있습니다. 사양은 “인트로스펙션” 섹션에서 이 주제에 대해 더 자세히 설명하고, GraphQL.js의 내성 파일에는 사양을 준수하는 GraphQL 쿼리 내성 시스템을 구현하는 코드가 포함되어 있습니다.19)
Continue Reading
관련 문서
__schema
field, always available on the root type of a Query. Let's do so now, and ask what types are available.__TypeKind
enum, one of whose values is OBJECT. If we asked about Character instead we'd find that it is an interface:NON_NULL
. If we queried for ofType on that field's type, we would find the ID type there, telling us that this is a non-null ID.