AWS AppSync で構築するリアルタイム GraphQL API - サブスクリプションとリゾルバー設計

WebSocket ベースのサブスクリプションでリアルタイム通知を実現し、DynamoDB・Lambda のパイプラインリゾルバーで複数データソースを統合する設計パターンを紹介します。

AppSync と REST API の使い分け

AppSync は AWS のマネージド GraphQL サービスで、1 秒あたり最大数千リクエストを処理し、WebSocket で最大 10 万の同時接続をサポートします。REST API では複数のエンドポイントを呼び出して必要なデータを組み立てる必要がありますが、GraphQL では単一のクエリで必要なフィールドだけを取得できます。モバイルアプリのように帯域幅が限られる環境や、複数のデータソースを横断して取得するダッシュボードに特に有効です。一方、単純な CRUD やサードパーティ向けの公開 API では API Gateway + Lambda の REST 構成の方がシンプルです。AppSync が力を発揮するのは、リアルタイム更新が必要なアプリケーション、複雑なデータ取得パターン、フロントエンドチームが API の柔軟性を求める場面です。

リアルタイムサブスクリプション

AppSync のサブスクリプションは WebSocket 上で動作し、Mutation の実行をトリガーにクライアントへデータをプッシュします。スキーマで Subscription タイプを定義し、@aws_subscribe ディレクティブで対象の Mutation を指定するだけで、リアルタイム通知が有効になります。チャットアプリケーションでは、新しいメッセージの Mutation が実行されると、同じチャットルームをサブスクライブしている全クライアントに即座にメッセージが配信されます。サブスクリプションのフィルタリングにより、クライアントは自分に関連するデータ変更のみを受信できます。接続管理は AppSync が自動的に行うため、WebSocket サーバーの運用は不要です。

リゾルバー設計とデータソース統合

リゾルバーは GraphQL のフィールドとデータソースを接続するコンポーネントです。 DynamoDB リゾルバーは VTL (Velocity Template Language) または JavaScript でマッピングテンプレートを記述し、 GetItem 、 PutItem 、 Query 、 Scan などの DynamoDB オペレーションを実行します。パイプラインリゾルバーは複数の関数を直列に実行し、前の関数の結果を次の関数に渡せます。例えば、最初の関数で DynamoDB からユーザー情報を取得し、次の関数でそのユーザーの注文履歴を別テーブルから取得するといった構成が可能です。 Lambda リゾルバーは複雑なビジネスロジックや外部 API 呼び出しが必要な場合に使用し、 DynamoDB リゾルバーはシンプルな CRUD に使用するという使い分けが効果的です。 AppSync に関する詳しい解説はAmazon の関連書籍でも確認できます。

AppSync の料金

AppSync の料金はクエリ・ミューテーションの実行回数とリアルタイム更新で構成されます。クエリとミューテーションは 100 万リクエストあたり約 4.00 ドルで、リアルタイム更新 (サブスクリプション) は 100 万回の接続分あたり約 2.00 ドルとデータ転送量で課金されます。キャッシュを有効にすると、キャッシュインスタンスの時間課金 (t2.small で約 0.028 ドル/時) が追加されますが、DynamoDB や Lambda への呼び出し回数を削減できるため、読み取りが多いワークロードではトータルコストが下がる場合があります。API Gateway + Lambda の REST 構成と比較すると、リクエスト単価は高めですが、N+1 問題の解消によるバックエンド呼び出し削減を考慮すると、複雑なデータ取得パターンでは AppSync の方がコスト効率が良いケースもあります。

スキーマ設計の基本

GraphQL API の設計は、スキーマを定義することから始まります。スキーマは、扱うデータの型と、クライアントが実行できる操作を宣言したもので、API の仕様そのものになります。データを取得するクエリ、変更を行うミューテーション、変更をリアルタイムに受け取るサブスクリプションを定義します。スキーマを最初にしっかり設計することで、クライアントとサーバーの開発者が共通の仕様をもとに並行して作業できます。必要なデータだけを過不足なく取得できる柔軟性が GraphQL の強みであり、それを活かすスキーマ設計が、使いやすい API の土台になります。

リゾルバーの種類と設計

リゾルバーは、スキーマで定義された操作を、実際のデータソースへの処理に結びつけるものです。一つのデータソースに対する単純な処理には、単体のリゾルバーを使います。複数のデータソースを順に呼び出したり、処理を組み合わせたりする場合は、複数のステップをつなげたパイプライン型のリゾルバーを使います。これにより、関連する複数のデータを一度のリクエストで統合して返せます。一部のデータソースには、リゾルバーから直接連携できる仕組みもあり、余分なコードを省けます。操作の複雑さに応じてリゾルバーの構成を選ぶことが、効率的な API 実装につながります。

認証・認可モード

AppSync は、複数の認証方式に対応しており、API の用途に応じて選べます。利用者の認証基盤と連携する方式、AWS の権限の仕組みを使う方式、簡易なキーによる方式、独自の認証ロジックを差し込む方式などがあります。さらに、フィールド単位で認可を制御でき、特定のデータは特定の利用者グループにだけ公開する、といったきめ細かい制御が可能です。複数の認証方式を組み合わせて、用途ごとに使い分けることもできます。誰がどのデータにアクセスできるかを適切に設計することが、安全な API を提供するうえで欠かせません。

オフライン対応と競合解決

モバイルアプリなど、ネットワークが不安定な環境で使われるアプリケーションでは、オフライン時の動作が重要になります。AppSync は、オフラインでもローカルでデータを操作でき、接続が回復したときにサーバーと同期する仕組みを提供します。このとき、複数の利用者が同じデータを変更していると、変更が衝突することがあります。どちらの変更を優先するかといった競合の解決方法を設計しておくことで、データの整合性を保てます。オフライン対応と競合解決を組み込むことで、通信状況に左右されない、快適なアプリケーション体験を実現できます。

まとめ

AppSync はリアルタイム更新と柔軟なデータ取得を必要とするアプリケーションに最適な GraphQL サービスです。WebSocket ベースのサブスクリプションでリアルタイム通知を実現し、パイプラインリゾルバーで DynamoDB、Lambda、RDS など複数データソースを統合します。マルチ認証によるきめ細かいアクセス制御もマネージドで提供します。