序章

著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。

Webおよびモバイルアプリケーションがより成熟して複雑になるにつれて、ソフトウェアエンジニアは、アプリケーション内のクライアントとサーバー間の相互作用を改善する巧妙な新しい方法を発明します。 この点に関する過去数年間の最大のパラダイムシフトの1つは、APIを操作するためのオープンソースのクエリ言語およびランタイムであるGraphQLです。 GraphQLは、宣言型、クライアント駆動型、パフォーマンスの高い新しいシステムを作成することで、従来のRESTアーキテクチャのさまざまな弱点を解決するために、2012年にFacebookによって設計されました(2015年に公開されました)。

この記事では、GraphQLとは何かを確認し、GraphQLの重要な用語と概念を理解し、GraphQL仕様がRESTアーキテクチャースタイルとどのように比較されるかを発見します。

GraphQLとは何ですか?

GraphQLはGraph Q uery L anguageの略ですが、SQL( S tructured Qなどの他のクエリ言語とは異なります] uery L anguage)は、データベースと直接通信するための言語ではなく、クライアントがAPIサーバーと通信するためのコントラクトを定義する言語です。 GraphQL仕様は、言語のルールと特性を説明するオープンスタンダードです。 また、GraphQLクエリを実行するための手順も提供します。

GraphQLはオープンスタンダードで定義されているため、GraphQLの正式な実装はありません。 GraphQLの実装は、仕様で概説されているルールに従っている限り、任意のプログラミング言語で記述し、任意のタイプのデータベースと統合し、任意のクライアント(モバイルまたはWebアプリケーションなど)をサポートできます。 最も人気のある商用GraphQL実装の1つはApolloGraphQL で、これはいくつかのGraphQLクライアントおよびサーバー実装を売り込んでいますが、GraphQLを使用または理解するためにApolloを使用する必要はありません。

GraphQLの特性

GraphQLデザインにはいくつかの重要な特徴があります。 GraphQLクエリは宣言型および階層型であり、GraphQLスキーマは強く型付けされたおよび内省的です。

宣言型

GraphQLクエリはdeclarativeです。つまり、クライアントは関心のあるフィールドを正確に宣言し、応答にはそれらのプロパティのみが含まれます。

この架空のファンタジーゲームAPIのGraphQLクエリの例では、IDが"1"wizardを要求し、そのオブジェクトのnameフィールドとraceフィールドを要求します。

{
  wizard(id: "1") {
    name
    race
  }
}

JSON 形式で返される応答は、クエリが要求した2つのフィールドとともに、見つかったwizardオブジェクトを含むdataオブジェクトを返します。

{
  "data": {
    "wizard": {
      "name": "Merlin",
      "race": "HUMAN"
    }
  }
}

GraphQL応答は必要な情報のみを提供するため、常に完全なデータセットを提供する代替手段よりも効率的でパフォーマンスの高いネットワーク要求が得られます。

階層

GraphQLクエリも階層的です。 返されるデータは、クエリの形に従います。 この例では、クエリはspellsを含むように拡張されており、すべての呪文のnameおよびattackフィールドを要求しています。

{
  wizard(id: "1") {
    name
    spells {
      name
      attack
    }
  }
}

応答には、この特定のwizardに関連付けられているすべてのspellオブジェクトの配列が含まれるようになります。 wizardsspellsは別々のデータベーステーブルに格納される場合がありますが、単一のGraphQLリクエストでフェッチできます。 (ただし、GraphQLはデータ自体がどのように格納されるかについては意見が分かれていないため、これは推定です。)

{
  "data": {
    "wizard": {
      "name": "Merlin",
      "spells": [
        {
          "name": "Lightning Bolt",
          "attack": 2
        },
        {
          "name": "Ice Storm",
          "attack": 2
        },
        {
          "name": "Fireball",
          "attack": 3
        }
      ]
    }
  }
}

強いタイプ

GraphQL Type system で説明されているように、GraphQLは強く型付けされています。 タイプは、GraphQLサーバー内の値の機能を記述します。 GraphQLタイプは、文字列、ブール値、数値整数などのスカラー(プリミティブ値)や、オブジェクトなどのより高度な値を使用して、ほとんどのプログラマーに馴染みがあります。

この例では、StringおよびIntスカラー型に対応するフィールドを持つSpellオブジェクト型を作成します。

type Spell {
  name: String!
  attack: Int
  range: Int
}

GraphQLスキーマは、型システムを使用して定義されます。これにより、サーバーは、データのクエリを試行する前に、クエリが有効かどうかを判断できます。 GraphQL Validation は、リクエストが構文的に正しく、明確で、間違いがないことを保証します。

自己文書化

Introspection 機能を使用すると、GraphQLクライアントとツールは、基盤となるスキーマの形状とデータについてGraphQLサーバーにクエリを実行できます。 これにより、 GraphiQL 、GraphQLクエリを操作するためのブラウザー内IDEとプレイグラウンド、およびドキュメントを自動的に生成するための他のツールなどのツールを作成できます。

たとえば、Spellタイプの詳細については、__schemaを介したこのイントロスペクション機能を参照してください。

{
  __schema {
    types {
      name
      kind
      description
    }
  }
}

応答も、他のGraphQL応答と同様にJSONになります。

{
  "data": {
    "__schema": {
      "types": [
        {
          "name": "Spell",
          "kind": "OBJECT",
          "description": "A powerful spell that a wizard can read from a scroll."
        }
      ]
    }
  }
}

クライアント主導

GraphQL APIの開発作業は、スキーマが定義および実装されているバックエンドで行われます。 ただし、GraphQL APIのすべての機能はサーバー上の単一のエンドポイントに含まれているため、必要なデータを正確に決定するのは宣言型クエリを介してクライアントに任されています。 これにより、開発者は迅速に反復処理できます。フロントエンド開発者は、追加のバックエンド作業を行うことなく、GraphQLAPIが公開するデータのクエリを続行できるためです。

建築

GraphQLは、クライアントとデータの間のアプリケーション層に存在します。 GraphQL server は、APIで公開されている機能を記述し、clientは要求の要件を記述します。

サーバ

GraphQL APIは、単一のエンドポイント、通常は/graphqlエンドポイントで定義され、GraphQLサーバーの全機能にアクセスできます。 GraphQLはアプリケーション層テクノロジーであり、トランスポートに依存しないため、どのプロトコルでも提供できますが、最も一般的にはHTTPで提供されます。

GraphQLサーバーの実装は、Node /ExpressHTTPサーバーでGraphQLAPIを作成できるexpress-graphqlミドルウェアなどの任意のプログラミング言語で記述できます。 GraphQLもデータベースに依存せず、アプリケーションのデータは MySQL PostgreSQL MongoDB 、またはその他のデータベースに保存できます。 データは、いくつかの従来のRESTAPIエンドポイントの集約によって提供することもできます。 重要なのは、データがGraphQL schema で定義されていることです。これは、クエリに使用できるデータを記述することでAPIを定義します。

クライアント

GraphQLサーバーに対して行われるリクエストは、ドキュメントと呼ばれ、クエリ(読み取りリクエストの場合)やミューテーション(書き込みリクエストの場合)などの操作で構成されます。

ApolloClientやFacebookのRelayなどの高度なGraphQLクライアントがあり、キャッシュのメカニズムと追加のツールを提供しますが、GraphQLサーバーにリクエストを送信するために特別なクライアントは必要ありません。 。 GraphQLドキュメントをGraphQLサーバーに送信してリクエストを行うには、Webブラウザーからの単純なXMLHttpRequestまたはfetchで十分です。

以下は、/graphqlエンドポイントへのfetchリクエストの例です。このエンドポイントは、POSTリクエストの本文でGraphQLドキュメントを文字列として渡します。

async function fetchWizards() {
  const response = await fetch('/graphql', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      query: `{
    wizards {
      id
      name
    },
  }`,
    }),
  })
  const wizards = await response.json()

  return wizards
}

fetchWizards()

これにより、リクエストに対するJSON応答が返されます。

{
  "data": {
    "wizards": [
      { "id": "1", "name": "Merlin" },
      { "id": "2", "name": "Gandalf" }
    ]
  }
}

GraphQLと 残り

GraphQLとRESTは互換性のある概念ではありませんが、アプリケーションの同様の問題を解決します。 RESTは、 Re presentational S tate T transferの略で、異なるシステム間でデータを共有するためのソフトウェアアーキテクチャスタイルです。 RESTful APIは、RESTの原則と制約に準拠するAPIです。これには、ステートレス、キャッシュ可能、クライアントとサーバー間の関心の分離の実施、URIなどによる統一されたインターフェイスの適用が含まれます。 前に説明したように、GraphQLは、クエリ言語とクエリを実行するためのランタイムの仕様です。

両方のシステムには長所と短所があり、どちらも最新のAPI開発で使用されています。 ただし、GraphQLは、RESTシステムで認識されているいくつかの弱点に対抗し、より効率的なクライアント駆動型APIを作成するために開発されました。

  • アーキテクチャ-RESTAPIは通常、サーバー上の複数のエンドポイントによって定義されますが、GraphQLは単一のエンドポイントを介してデータを交換します。 GraphQLエンドポイントは、複数のRESTクエリを必要とする可能性のあるデータの複雑なグラフを返すことができるため、単一のビューに対するネットワーク上のリクエストの数を減らすことができます。

  • データフェッチ-RESTAPIは、サーバー上で決定されたデータのセットを返します。 これは、ビューが応答から1つのプロパティのみを必要とする場合など、データが多すぎる可能性があります。 また、テーブルがビューで必要とするすべてのプロパティを返さないリストエンドポイントなど、十分ではない場合もあります。 GraphQLは、宣言型クエリを介したデータのフェッチの過不足を防ぎます。

  • エラー処理-GraphQLをHTTP経由で提供する必要がないため、エラーにHTTP応答コードを使用することについての仕様はありません。 通常、すべてのGraphQLエンドポイントは200 HTTPコード応答で解決され、失敗した結果には、応答のdataプロパティに加えてerrorsプロパティが含まれます。 一方、RESTful APIは、クライアントエラーにはさまざまな400レベルのHTTPコードを使用し、正常な応答には200レベルのHTTPコードを使用します。

  • バージョニング-GraphQLAPIは、URL自体に/v1または/v2が含まれることが多い、バージョニングエンドポイントの一般的なRESTパターンとは対照的に、下位互換性を保ち、変更を壊さないように努めています。バージョンを決定します。 ただし、GraphQLを使用して独自のバージョン管理を実装したり、RESTを使用して進化を介してバージョン管理したりすることは可能です。

  • キャッシング-キャッシュ可能性は、RESTガイド制約の不可欠な部分です。 HTTPベースのRESTAPIは、さまざまなHTTPメソッドを使用する複数のエンドポイントで構成されているため、既存のHTTP規則を利用して、リソースのキャッシュと再フェッチを回避できます。 基本的にすべてのGraphQLリクエストは異なりますが、単一のエンドポイントを使用するため、組み込みのHTTPキャッシングメカニズムを利用することはできません。 GraphQLクライアントは、 Global Object Identification を利用して、単純なキャッシュを有効にすることができます。

このリストは、RESTとGraphQLのすべての類似点と相違点を網羅しているわけではありませんが、最も重要なポイントの多くを要約しています。 さらに、GraphQLは、複数のRESTエンドポイントまたはサービスを集約するゲートウェイとして使用できます。その場合、両方のテクノロジーを並行して使用できます。

特徴 GraphQL 残り
説明 GraphQLは、APIのクエリ言語であり、サーバー側のランタイムです。 Webサービスを設計するためのアーキテクチャスタイル
データフェッチ 決定論的クエリに応答する単一のHTTPエンドポイント 通常、事前に定義されたデータセットを返すHTTPエンドポイントのセット
バージョニング バージョン管理は推奨されません 一般的なバージョン管理
HTTPステータスコード エラーを含むすべての応答は、通常200です。 HTTPステータスコードを実装します
検証 組み込みのメタデータ検証 検証は手動で実装する必要があります
ドキュメンテーション 型システムとイントロスペクションを介して組み込まれています 自己文書化ではなく、OpenAPIのようなツールが利用可能
キャッシング いいえ はい
リクエストメソッド クエリ、ミューテーション、およびサブスクリプション(HTTPの場合はPOST経由) 使用されるすべてのHTTPメソッド(GETPOSTPATCHPUTDELETEなど)
応答コンテンツタイプ JSON 任意(JSON、XML、HTMLなど)

結論

GraphQLは、API用のオープンソースのクエリ言語およびランタイムです。 GraphQLは、APIのクライアント駆動型の宣言型クエリ言語を作成することにより、データのオーバー/アンダーフェッチや非効率的なネットワークリクエストなど、従来のRESTAPIで発生するさまざまな問題を解決するためにFacebookの開発者によって発明されました。

GraphQLはRESTと互換性のある概念ではありませんが、どちらもクライアントとサーバー間の通信を管理するためのさまざまな方法を説明しています。 この記事では、GraphQLとは何か、GraphQLとRESTの主な相違点と類似点、およびGraphQLサーバーがデータをクライアントに公開する方法について学習しました。