AWS AppSync とは
AWS AppSync(アプリデータをリアルタイムで保存、同期)| AWS
AppSync GraphQL を使用すると、アプリケーションデベロッパーは、単一の GraphQL API リクエストで、複数のデータベース、マイクロサービス、AI モデルからのデータにアクセスできます。
AWS が提供しているマネージドな GraphQL サービスです。
GraphQL
GraphQL とは - AWS AppSync GraphQL
GraphQL は API のクエリ言語であり、それらのクエリを実行するランタイムでもあります。GraphQL を使用すると、クライアントは必要なデータを正確にリクエストできるため、多くのシナリオで REST よりも柔軟で効率的な代替手段となります。事前定義されたエンドポイントに依存する REST とは異なり、GraphQL は 1 つのエンドポイントを使用し、クライアントはクエリとミューテーションの形式でデータ要件を指定できます。
- API のクエリ言語
- 単一のエンドポイントを提供
GraphQL のコンポーネント
GraphQL API のコンポーネント - AWS AppSync GraphQL
標準の GraphQL API は、クエリされるデータの形状を処理する単一のスキーマで構成されています。スキーマは、データベースや Lambda 関数などの 1 つ以上のデータソースにリンクされています。2 つのリゾルバーの間には、リクエストのビジネスロジックを処理する 1 つ以上のリゾルバーがあります。
- GraphQL API は 3 つのコンポーネントで構成されている
- スキーマ
- データソース
- リゾルバー
スキーマ
GraphQL スキーマ - AWS AppSync GraphQL
GraphQL スキーマは GraphQL API の基盤です。データの形状を定義する設計図として機能します。また、データの取得方法や変更方法を定義する、クライアントとサーバー間の契約でもあります。
- データの形状を定義
- データの取得方法や変更方法を定義
- スキーマ定義言語である SDL で記述
- タイプとフィールドで構成
以下は上記ドキュメントに記載されているスキーマの例です。
type Person {
id: ID!
name: String
age: Int
}
type Query {
people: [Person]
}
type Mutation {
addPerson(id: ID!, name: String, age: Int): Person
}
上記スキーマは以下のような構造になっています。
- タイプ: Person, Query, Mutation
- Person: id, name, age の値を保持
- オブジェクト型
- ID! であるため id は必須の値
- Query: ソースからデータを取得
- データベースから Person オブジェクトを取得して people というキーに保存
- [Person] の記述により Person オブジェクトをすべて取得
- REST API の GET に近い
- データベースから Person オブジェクトを取得して people というキーに保存
- Mutation
- データを変更
- REST API の PUT や POST に近い
- addPerson 操作によって Person オブジェクトをデータベースに追加
- addPerson の実装はリゾルバーで定義する
データソース
スキーマはデータソースのデータにアクセスして処理し、クライアントに中継します。
AppSync でサポートされているデータソースは以下の通りです。
- DynamoDB
- Lambda
- OpenSearch
- HTTP エンドポイント
- EventBridge
- RDS
- データソースなし
各データソースのユースケースについては上記ドキュメントをご参照ください。
リゾルバー
リゾルバーは、サービスにリクエストが送信されたときに、そのフィールドのデータをどのように解決するかを処理するコード単位です。リゾルバーは、スキーマのタイプ内の特定のフィールドにアタッチされます。クエリ、ミューテーション、サブスクリプションフィールド操作の状態変更操作を実装するために最もよく使用されます。
- スキーマのフィールドのデータの処理方法をコードレベルで定義
- スキーマの特定のフィールドにアタッチされる
- AppSync がサポートしているリゾルバーランタイムは 2 種類
- APPSYNC_JS for JavaScript
- Velocity Template Language (VTL)
- ユニットリゾルバーとパイプラインリゾルバーで構成されている
- ユニットリゾルバー: データソースに対して実行される単一のリクエストハンドラーとレスポンスハンドラーを定義
- パイプラインリゾルバー: 3 つの実行タイミングがある
- before step: データがリゾルバーを通過する前に一部の前処理操作を実行
- 関数: 独自のリクエストハンドラーとレスポンスハンドラーを含むリゾルバーのコードのサブセット
- after step: GraphQL レスポンスに渡す前に最終オペレーションを実行
以下はドキュメントに記載されているリゾルバーハンドラーの例です。
export function request(ctx) {
// Code goes here
}
export function response(ctx) {
// Code goes here
}
Query タイプに以下のフィールドが定義されている例が紹介されています。
type Query {
helloWorld: String!
}
上述の通り Query は REST API の GET に近いので、文字列を取得して helloWorld という変数に格納するという定義に読み替えることができます。
ただし、スキーマの定義だけではデータを取得することはできないので、スキーマ内の helloWorld フィールドにリゾルバーをアタッチする必要があります。
ドキュメントでは以下のリゾルバーをアタッチする例が紹介されています。
export function request(ctx) {
return {}
}
export function response(ctx) {
return "Hello World"
}
今回の例だとデータソースを定義していないため、request ハンドラーはデータソースを呼び出しません。
そのため、空の値を返す処理、つまり何も処理を実行しないという定義になっています。
一方で、response ハンドラーは Hello World という固定文字列を返します。
これにより、Query タイプの helloWorld には Hello World が保持されます。
GraphQL と REST の違い
GraphQL と REST API の比較 - API デザインアーキテクチャの違い - AWS
上記公式サイトに差異がまとまっていますのでご参照ください。
相違点の要約: REST とGraphQL
REST >GraphQL 内容 REST は、クライアントとサーバー間の構造化されたデータ交換を定義する一連のルールです。 GraphQL は、API を作成および操作するためのクエリ言語、アーキテクチャスタイル、およびツールのセットです。 こんな方に最適 REST は、リソースが明確に定義されている単純なデータソースに適しています。 GraphQL は、大規模で複雑な、相互に関連するデータソースに適しています。 データアクセス REST には、リソースを定義する URL 形式の複数のエンドポイントがあります。 GraphQL には単一の URL エンドポイントがあります。 戻りデータ REST は、サーバーによって定義された固定の構造でデータを返します。 GraphQL は、クライアントによって定義された柔軟な構造でデータを返します。 データの構造と定義方法 REST データは弱い型指定です。そのため、クライアントは、フォーマットされたデータが返されたときにどのように解釈するかを決定する必要があります。 GraphQL データは厳密に型指定されています。そのため、クライアントは、あらかじめ決められた、相互に理解し合える形式でデータを受け取ります。 エラーチェック REST では、クライアントは返されたデータが有効かどうかを確認する必要があります。 GraphQL では、通常、無効なリクエストはスキーマ構造によって拒否されます。その結果、エラーメッセージが自動生成されます。
チュートリアル
AWS AppSync コンソールでスキーマを起動する - AWS AppSync GraphQL
ドキュメントのチュートリアルをやってみました。
01. GraphQL API の作成
AppSync コンソールで GraphQL API を作成します。

API タイプはデフォルト設定で進めます。

API 名に Todo API と入力して次に進みます。

「DynamoDB テーブルを使用するタイプを今すぐ作成」を選択します。

モデル名に Todo と入力します。

ドキュメントに沿って新しいフィールドを追加します。
| 名前 | タイプ | 配列 | 必須 |
|---|---|---|---|
| id | ID | No | Yes |
| name | String | No | No |
| when | String | No | No |
| where | String | No | No |
| description | String | No | No |

モデルテーブルを以下のように設定します。
- テーブル名: TodoAPITable
- Primary key: id
- Sort key: None

確認画面で設定を確認して API を作成します。

02. ミューテーションで DynamoDB にデータを追加
AppSync コンソールでクエリを選択します。

クエリエディターの左サイドバーの上から 3 つ目にある「Show GraphQL Explorer」をクリックします。

createTodo の 5 つの項目すべてにチェックをつけます。

Variables を以下のように定義します。
{
"createtodoinput": {
"name": "Shopping List",
"when": "Friday",
"where": "Home",
"description": "I need to buy eggs"
}
}

以下のようなクエリになっていることを確認します。
mutation createTodo($createtodoinput: CreateTodoInput!) {
createTodo(input: $createtodoinput) {
id
name
description
when
where
}
}
クエリの実行ボタンで createTodo を実行します。

以下の結果が表示されます。
{
"data": {
"createTodo": {
"id": "4c0d9cc0-e62f-46db-8347-5a40d31ed00e",
"name": "Shopping List",
"description": "I need to buy eggs",
"when": "Friday",
"where": "Home"
}
}
}
DynamoDB コンソールから TodoAPITable テーブルを確認すると、クエリで指定した値が保存されていることがわかります。

03. DynamoDB からデータを取得する
listTodos クエリに含まれる getTodo を展開します。

getTodo の 6 つの項目すべてにチェックをつけます。

クエリエディタの id に手順 02 で実行したクエリの ID を指定します。

クエリの実行ボタンで listTodo を実行します。
以下のような結果が表示されることを確認します。
{
"data": {
"getTodo": {
"description": "I need to buy eggs",
"id": "4c0d9cc0-e62f-46db-8347-5a40d31ed00e",
"name": "Shopping List",
"when": "Friday",
"where": "Home"
}
}
}

まとめ
今回は AWS AppSync について紹介しました。
どなたかの参考になれば幸いです。
Discussion