メインコンテンツに移動
 デベロッパーのためのクラウド活用方法

サーバーレスでできるリアルタイム通信 ! AWS AppSync Events を使ってゲームギルドチャットを作ってみよう

2025-04-02 | Author : 大西 啓太郎、西坂 信哉

builders.flash メールメンバー登録

毎月提供されるクラウドレシピのアップデート情報とともに、クレジットコードを受け取ることができます。 
今すぐ特典を受け取る »

1. AWS AppSync Eventsとは ?

AWS AppSync Events は、2024 年 10 月に発表された AWS AppSync の新機能です。AppSync というと「GraphQL のマネージドサービス」というイメージが強いかもしれませんが、実は今回のアップデートは GraphQL は関係ありません。

従来、リアルタイム通信を実現するためには、WebSocket サーバーの構築・運用、コネクション状態の管理、メッセージのファンアウト実装など、多くの技術的課題がありました。AWS AppSync Events はこれらの課題を解決し、安全で高性能なサーバーレス WebSocket API を提供します。

この機能の核心は、チャネルベースの Pub/Sub モデルにあります。開発者はチャネル名前空間を定義し、その中に様々なチャネルを動的に作成できます。クライアントは特定のチャネルをサブスクライブし、サーバーサイドのコードは簡単な HTTP リクエストでイベントをパブリッシュできます。ワイルドカード機能を使えば、複数のチャネルを一度にサブスクライブすることも可能です。

AWS AppSync Events の最大の特長は、インフラ管理からの解放です。WebSocket コネクションの確立・維持、認証、スケーリングといった煩雑な作業を AWS が全て処理するため、開発者はビジネスロジックに集中できます。数人から数百万人のユーザーまで、自動的にスケールするため、トラフィック変動の心配もありません。AWS AppSync Events API はサーバーレスで、使用した分だけ支払うため、コスト効率も優れています。

2. アーキテクチャ概要

今回実装するギルドチャットシステムのアーキテクチャは以下のとおりです。

コンポーネントと処理フロー

主なコンポーネントは以下の通りです。

フロントエンド

  • Webブラウザ (HTML/JavaScript) : 今回のサンプル実装では Web ブラウザベースの UI を使用します。この HTML とJavaScriptは、AWS App Runner 上の Express.js サーバーから直接配信されます。
  • ゲームクライアント (Unity、Unreal Engine など) : 同じバックエンド API を利用して、ネイティブゲームクライアントからも接続可能です。

バックエンド

  • AWS App Runner 上の Express.js サーバー: RESTful API による、ギルド管理、メッセージ履歴管理、JWT 認証、といった機能と、フロントエンドの配信機能を担当します。
  • AWS AppSync Events: WebSocket 接続管理を含めた、リアルタイムメッセージング部分の機能を担当します。
  • AWS Lambda: AppSync Events の認証処理を行うハンドラーとしての機能を担当します。


主な処理フローは以下の通りです。

認証フロー
本サンプルでは、チャンネルへの接続 (Connect) およびメッセージの送信 (Publish) には API キーによる認証を、メッセージの受信 (Subscribe) では RS256 アルゴリズムを使用した JWT ベースの認証を使用します。JWT ベース認証のフローは以下の通りです。

  1. App Runner上のバックエンドサーバーが認証処理の後、JWT を発行
  2. クライアントが JWT を Authentication ヘッダーに格納し、AppSync Events へ Subscribe 要求を送信
  3. Lambda 関数が JWT を検証し、Subscribe をリクエストされたチャネルにアクセスする権限があるかどうか確認
  4. 権限があればアクセス許可、なければアクセス拒否として応答

※ なお本記事執筆時点では、認証方式として「API キー」「Lambda 認証」「Amazon Cognito ユーザープール」「AWS Identity and Access Management (IAM) 認証」「OpenID Connect」が選択できます。本番利用においては適切な認証方式の選定・利用をご検討ください。

通信フロー

  • メッセージ送信 (Publish): クライアントがメッセージを RESTful API 経由で App Runner 上のバックエンドサーバーへ送信します。バックエンドサーバーは AppSync Events に HTTP 経由でメッセージを Publish します。
  • メッセージ受信 (Subscribe): クライアントが AppSync Events の Websocket に接続することで、リアルタイムにメッセージを受信します。

なお 2025 年 3 月 13 日のアップデート で、WebSocket 接続経由でのメッセージ publish も行えるようになりました。HTTP 経由の publish と比較すると、実装がシンプルになったり、publish の通信オーバーヘッドが減ることによるレイテンシー低減などの効果が見込めます。一方で、本サンプルのように API サーバーを介した HTTP 経由の publish では、高度なメッセージモデレーションやログ取得機能を持たせやすいメリットもあります。例えばゲームチャットでは、NG ワードフィルタリングをしたいので HTTP 経由とするが、ステータス同期はレイテンシー低減のため WebSocket 経由とするなど、用途によって適した方法を選択できます。

3. AWS AppSync Event API の実装

3-1. AWS AppSync Event API の作成

まず、AWS Management Console で AWS AppSync Events の設定を行います。
AWSマネジメントコンソールの日本語インターフェースで『AppSync』を検索した結果を示した画面。AppSyncサービスやWAF & Shieldサービス、APIの作成機能などが表示されている。

Event API を作成

Event API を作成」を選択します。
Screenshot of the AWS AppSync API types selection screen in Japanese, showing options for creating GraphQL API and Event API, with Japanese UI elements and descriptions for each API type.

API に名前を入力

API に名前を付け (例: GuildChatAPI)、「 作成」を選択します。

数秒で API が作成され、イベント API、デフォルトの名前空間、API キーが自動的に生成されます。
Screenshot of the AWS AppSync console in Japanese, showing the creation form for an Event API named GuildChatAPI. The interface displays fields for API name, optional contact name, and tag setup options.

設定内容をコピー

設定」タブを選択し、「 認可モード - API キー」、「 DNS エンドポイント - HTTP」 および「 DNS エンドポイント - リアルタイム」が発行されていることを確認し、コピーしてメモに控えておいてください。
Screenshot of the AWS AppSync GuildChatAPI settings page, displayed in Japanese. The image shows setup confirmation messages, API details, and DNS endpoint information for GuildChatAPI, using the Japanese language interface.

3-2. AWS Lambda 認証ハンドラーの実装

AppSync Events の認証を行うための Lambda 関数を作成します。この関数は JWT トークンを検証し、ユーザーが適切なギルドチャネルにのみアクセスできるようにします。

実際のゲーム環境では、ギルドに所属していないプレイヤーが悪意を持ってチャットに参加することを防ぐ必要があります。Lambda 認証を使うことで、ゲームバックエンドが発行した正規の JWT トークンを検証し、各プレイヤーが自分の所属ギルドのチャネルにのみアクセスできるようにセキュリティを確保できます。

また、ほとんどのゲームでは、ログイン、キャラクター情報、アイテム管理などですでに認証されたセッション情報を持っているため、その既存の認証基盤と連携したセキュリティモデルが自然です。Lambda 認証ハンドラーを用いることで連携を容易にします。

AWS Lambda コンソールにアクセス

AWS Lambda コンソールにアクセスします。
Screenshot of the AWS Management Console showing a search for 'Lambda' in the services menu, with results such as Lambda, CodeBuild, and AWS Signer, displayed in Japanese language.

関数を作成

関数を作成」を選択します。
Screenshot of the AWS Lambda management console showing a list of Lambda functions in Japanese, including search and action options in the user interface.

関数名とランタイムを入力

  • 「関数名」: 「guild-chat-auth-handler
  • ランタイム : 「Python 3.12」

※ 最新の選択できるランタイムバージョンとは異なりますが、後述の AWS CloudShell の Python とバージョンを揃える為、「Python 3.12」を選択することを強く推奨します。

他はデフォルトの設定で「関数の作成」を選択します。

Screenshot of the AWS Lambda function creation interface in Japanese, showing how to initialize a function with Python 3.12, x86_64 or arm64 architecture, and set configuration options. The UI includes fields for function name, runtime selection, architecture, permissions, and other setup details.

AWS CloudShell にアクセス

AWS CloudShell にアクセスします。AWS CLI を使用してZIP ファイルを Lambda 関数にデプロイするにあたり、このAWS CloudShell 上のシェルでコマンド操作を行います。

Screenshot of the AWS Management Console showing a search for 'CloudShell' with the interface displayed in Japanese.

Screenshot showing an error tab in AWS CloudShell for the ap-northeast-1 region with the terminal prompt visible. The interface is displayed in Japanese.

Lambda 関数に必要なパッケージとソースコードををデプロイ

AWS CloudShell を使用して、サンプルプロジェクトの ZIP ファイルから Lambda 関数に必要なパッケージとソースコードををデプロイします。

Screenshot of Japanese code instructions for downloading, extracting, installing, and deploying a Python 3.12 AWS Lambda function for a Game Guild Chat AppSync events demo, including commands for ZIP file handling, requirements installation, and function update.

認証ハンドラーの主なポイント

この認証ハンドラーの主なポイントは以下の通りです:

  1. JWKS エンドポイント連携: バックエンドサーバー (Express.js) が提供する JWKS (JSON Web Key Set) エンドポイントから公開鍵を取得して JWT を検証します。これにより、署名鍵の管理が簡単になります。

  2. チャネル名とギルド名の検証: トークンのペイロードに含まれる guildname と、アクセスしようとしているチャネル名が一致するかを検証します。これにより、プレイヤーは自分が所属するギルドのチャットにのみアクセスできます。

  3. 堅牢なエラーハンドリング: 無効なトークンや不正なチャネルアクセスをきちんと拒否し、セキュリティを確保します。

※ 本番利用に向けては、要件に応じた適切な JWT 検証処理の実装をご検討ください。

3-3. Lambda 認証を使用するためのチャネル名前空間の設定

作成した Lambda 関数を AppSync Events の認証ハンドラーとして設定します。

「AWS App Sync」で作成した、「GuildChatAPI」の「設定」タブから、「認可設定」にある「追加」を選択します。

Screenshot displaying the authentication settings for GuildChatAPI in the AWS AppSync console, interface shown in Japanese, including API key authentication modes and expiry details.

認証モードを設定

  • 「認可モード」:「AWS Lambda」

  • 「AWS リージョン」: 「AP-NORTHEAST-1」

  • 「関数の ARN」: 「guild-chat-auth-handler

を選択し、「追加」を選択します。

Screenshot of the AWS AppSync settings interface showing the configuration for Lambda authentication in Japanese. The interface highlights options for authentication modes, with AWS Lambda selected, and displays relevant Lambda settings such as region, ARN, and TTL options.

名前空間を作成

続いて、作成した Lambda 関数をサブスクライブ認証に使用する名前空間を作成します。

「AWS App Sync」で作成した、「GuildChatAPI」の「名前空間」から、「名前空間を作成」を選択します。

Screenshot of the AWS AppSync console showing the GuildChatAPI namespace management section in the Japanese language user interface, dated 2025. The display includes tabs for dashboard, namespace, Pub/Sub editor, integration, and settings, with details for a default channel namespace.

名前空間の設定

  • 「名前空間名」: 「guild」

  • 「この名前空間にカスタム認証を追加」: チェックを入れる

  • 「認証モードをパブリッシュ - オプション」: 「API_KEY」

  • 「サブスクライブ認証モード - オプション」: 「AWS_LAMBDA」

を選択し、「作成」を選択します。

※ 「default」名前空間は今回は不要のため、セキュリティ考慮する場合は削除してください。残したままでも後続の手順は進められます。

Screenshot showing the AWS AppSync UI in Japanese for creating a channel namespace, including settings for name, authentication modes, handlers, and tags.

4. バックエンドサーバーの実装

バックエンドサーバーは、Node.js と Express.js を使用して実装します。今回はコンテナアプリケーションを手軽にホスティングできる AWS App Runner を利用します。
このサーバーは以下の重要な機能を提供します:

  • ギルドとメンバーの管理
  • Web アプリケーション UI (HTML/CSS/JavaScript) の提供
  • JWT 発行と JWKS エンドポイントの提供
  • メッセージの AppSync Events への転送

AWS CloudShell にアクセス

AWS CloudShell にアクセスします。しばらくはこの AWS CloudShell 上のシェルでコマンド操作を行います。

Screenshot of the AWS Management Console showing a search for 'CloudShell' with the interface displayed in Japanese.

Screenshot showing an error tab in AWS CloudShell for the ap-northeast-1 region with the terminal prompt visible. The interface is displayed in Japanese.

4-1. AWS CloudShell でサンプルコードを準備

AWS CloudShell を使用して、サンプルプロジェクトの ZIP ファイルからサーバーをデプロイします。ZIP ファイルには、完全に機能するギルドチャットサーバーのすべてのファイル (Dockerfile、package.json、index.js など) が含まれています。

bash
# 作業ディレクトリへ移動 
cd ~

# ZIPファイルをダウンロード
curl -L https://pages.awscloud.com/rs/112-TZM-766/images/appsync-event-api-demo-guild-chat.zip -o guild-chat.zip

# ファイルを解凍
unzip guild-chat.zip

# 解凍したディレクトリに移動
cd appsync-event-api-demo-guild-chat

# ファイル内容を確認
ls -la

4-2. Amazon Elastic Container Registry (ECR) リポジトリの作成と Docker イメージのビルド・プッシュ

ECR リポジトリの作成から Docker イメージのビルド・プッシュまで、すべて CloudShell で行います。

bash
# リージョンを設定
export AWS_REGION=ap-northeast-1

# ECR リポジトリを作成
aws ecr create-repository --repository-name guild-chat-server

# 作成されたリポジトリの URI を取得
export ECR_REPOSITORY_URI=$(aws ecr describe-repositories --repository-names guild-chat-server --query 'repositories[0].repositoryUri' --output text)
echo "リポジトリURI: $ECR_REPOSITORY_URI"

# ECR にログイン
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ECR_REPOSITORY_URI

# Docker イメージをビルド
docker build -t guild-chat-server .

# イメージにタグを付ける
docker tag guild-chat-server:latest $ECR_REPOSITORY_URI:latest

# イメージを ECR にプッシュ
docker push $ECR_REPOSITORY_URI:latest

# イメージの URI
echo $ECR_REPOSITORY_URI:latest

4-3. JWT 認証に用いる公開鍵・秘密鍵の作成

JWT 認証には公開鍵・秘密鍵のペアが必要となるため、以下の手順にて、openssl を用いて鍵を作成します。ここで出力した各鍵の値は後の手順で利用するため控えておいてください。

bash
# JWT トークンの署名に用いるキーペアの作成
openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private.pem -out public.pem

# Base64 エンコード
export JWT_PRIVATE_KEY_BASE64=$(cat private.pem | base64 -w 0)
export JWT_PUBLIC_KEY_BASE64=$(cat public.pem | base64 -w 0)

# JWT_PRIVATE_KEY_BASE64 (秘密鍵)
echo $JWT_PRIVATE_KEY_BASE64

# JWT_PUBLIC_KEY_BASE64 (公開鍵)
echo $JWT_PUBLIC_KEY_BASE64

サービスの作成を選択

サービスの作成」を選択します。
Screenshot of the AWS AppSync service list interface in Japanese, showing available application services and filter options.

4-4. AWS App Runner の設定

次に、ECR イメージを使用して AWS App Runner サービスを作成します。

AWS App Runner にアクセスします。

Screenshot of the AWS Management Console with a search for 'App Runner' in Japanese, highlighting the AWS App Runner service result.

ソース・デプロイ設定

  • 「コンテナイメージの URL」:「xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/guild-chat-server:latest」※ 前章で ECR にプッシュしたイメージの URI (:latest 含む) を入力します
  • 「ECR アクセスロール」:「新しいサービスロールの作成」を選択します
  • 「サービスロール名」:「AppRunnerECRAccessRole-GuildChatServer」を入力

これらを入力し、「次へ」を選択します。

App Runnerのソース設定とデプロイ方法設定画面(日本語UI)。コンテナイメージURI、Amazon ECR設定、デプロイトリガーやアクセスロールの選択オプションが表示されています。

サービスの設定

  • サービス名」: 「guild-chat-server」

  • 環境変数 – オプション」では、「環境変数を追加」を選択し、次の合計 5 つの環境変数を登録します。

    • APPSYNC_API_KEY : 前の手順で控えた「認可モード - API キー」の値

    • APPSYNC_HTTP_DOMAIN : 前の手順で控えた「DNS エンドポイント - HTTP」の値

    • APPSYNC_REALTIME_DOMAIN : 前の手順で控えた「DNS エンドポイント - リアルタイム」の値

    • JWT_PRIVATE_KEY_BASE64 : 前の手順で控えた秘密鍵の値 (BASE64 エンコードしたもの)

    • JWT_PUBLIC_KEY_BASE64 : 前の手順で控えた公開鍵の値 (BASE64 エンコードしたもの)

他はデフォルトの設定で「次へ」を選択します。

※ 本番利用に向けては、秘密鍵の値のような機微な情報の管理には AWS Secrets Manager 等の利用をご検討ください。

AWSサービス設定画面の日本語インターフェイスで、guild-chat-serverのサービス名、仮想CPU・メモリ設定および環境変数(APPSYNC_API_KEYなど)の入力フィールドが表示されているスクリーンショット。

デプロイ

「確認および作成」の画面で入力内容を確認後、「作成とデプロイ」を選択します。数分待ち、正常にでデプロイされたことを確認してください。

AWS AppRunnerでギルドチャットサーバーをデプロイする際の設定画面(日本語)。Amazon ECRからイメージを取得し、サービス設定や環境変数も表示されています。

AWS App Runnerでguild-chat-serverが正常にデプロイされ、ステータスが「Running」となっている状態を日本語で表示した管理画面のスクリーンショット。

登録する環境変数の解説

  • APPSYNC_API_KEY : バックエンドが AppSync HTTP API へパブリッシュする際や、クライアントが WebSocket API に接続する際に利用する API_KEY です。「AWS App Sync」で作成した、「GuildChatAPI」の「設定」から確認が可能で、デフォルトの有効期限が 7 日と短くなっている為、必要に応じて有効期限を延長するよう編集してください。

  • APPSYNC_HTTP_DOMAIN : バックエンドがAppSync HTTP APIへパブリッシュする際に利用するエンドポイントです。「AWS App Sync」で作成した、「GuildChatAPI」の「設定」から確認可能です。

  • APPSYNC_REALTIME_DOMAIN : クライアントがWebSocket APIに接続する際に利用するWebSocketのエンドポイントです。「AWS App Sync」で作成した、「GuildChatAPI」の「設定」から確認可能です。

  • JWT_PRIVATE_KEY_BASE64 : JWTトークンに署名するための秘密鍵を Base64 エンコードしたもの。

  • JWT_PUBLIC_KEY_BASE64 : JWTトークンの署名を検証するための公開鍵を Base64 エンコードしたもの。

4-5. Lambda 認証のための URL 設定

最後に、Lambda 認証ハンドラーが JWKS エンドポイントにアクセスできるように環境変数を設定します。

AWS Lambda の認証ハンドラー関数 (guild-chat-auth-handler)「設定」タブから「環境変数」を選択し、「編集」を選択します。

Screenshot of the AWS Lambda console showing the settings tab for the 'guild-chat-auth-handler' function, with interface elements and configuration options in Japanese.

環境変数の編集

環境変数の追加」を選択し 1 つの環境変数を追加します。

保存」を選択します。

AWS App Runnerの環境変数編集画面を日本語で表示。環境変数キー「JWKS_URL」と、その値としてjwksエンドポイント(ap-northeast-1リージョン)が設定された様子が表示されています。

5. 動作確認

AWS App Runner が発行したデフォルトドメインを Webブラウザで開ききます。表示されている任意のギルドに参加し、チャットメッセージを送信してみましょう。複数のブラウザや、シークレット モードなどを利用して複数のセッションからチャットに参加することで、リアルタイムにチャットメッセージが送受信できていることを確認できます。

ログイン画面

ログイン画面 : ユーザー名とギルド名を入力してギルドに参加します。(本サンプルではユーザー名は任意です)

Side-by-side comparison of two Guild Chat login interface screens in Japanese, showing different user name inputs and active guild list. The interfaces feature fields for username, guild name, a join guild button, a login success message, and a list of active guilds with member counts.

チャット画面

チャット画面 : リアルタイムにチャットメッセージが送受信できていることを確認できます。
※ もし送信したメッセージが画面に反映されない場合は、画面上部に「接続済み」の表示が出ているかの確認、「Enter」キーではなく「 送信」ボタンを押下で送信、をお試しください。
A side-by-side comparison of a Japanese chat application user interface, displaying conversational messages and different UI components, including text input fields and chat bubbles.

6. リソースの削除

以上でサンプルチャットアプリの動作確認は完了です。不要なコスト発生を防ぐため、リソースの後片付けをしっかりやりましょう。

  • AWS AppSync Event API
    • AWS AppSync」-「API」-「GuildChatAPI」を選択し、「削除
  • AWS Lambda 関数
    • AWS Lambda」-「guild-chat-auth-handler」の画面から、右上の「アクション」-「関数の削除
  • AWS App Runner サービス
    • AWS App Runner」-「サービス」-「guild-chat-server」の画面から、右上の「アクション」-「削除
  • ECR リポジトリ
    • ECR」-「リポジトリ」から「guild-chat-server」を選択し、右上の「削除
  • Amazon CloudWatch ロググループ
    • Amazon CloudWatch」-「ロググループ」から、以下の 3 つのロググループを選択し、右上の「アクション」-「ロググループの削除
      • /aws/apprunner/guild-chat-server/xxxxxxxxxxxxxxxxxxxxxxxx/application
      • /aws/apprunner/guild-chat-server/xxxxxxxxxxxxxxxxxxxxxxxx/service
      • /aws/lambda/guild-chat-auth-handler

7. まとめ

AWS AppSync Events の登場により、ゲーム開発者はこれまで技術的に難しかったリアルタイムコミュニケーション機能を手軽に実装できるようになりました。従来の WebSocket サーバー構築・運用から解放され、スケーラビリティやコスト効率に優れたソリューションを短期間で提供できます。本記事で紹介したギルドチャットシステムは、AWS AppSync Events、Lambda 認証、App Runner を組み合わせることで、セキュリティを確保しながらリアルタイム性の高いコミュニケーション体験を実現します。サーバーレスアーキテクチャと AWS のマネージドサービスの組み合わせは、開発リソースを削減しながら、プレイヤーにとって価値のある機能を素早く提供するための強力な選択肢となるでしょう。

筆者プロフィール

A portrait of a man with short dark hair wearing a suit jacket and collared shirt against a black background.

大西 啓太郎(Keitaro Onishi)

アマゾン ウェブ サービス ジャパン合同会社
ゲームソリューションアーキテクト

ゲーム会社のエンジニアを経て 2022 年にアマゾンウェブサービスジャパン合同会社に入社。現在は主にゲーム業界のお客様の技術支援を担当しています。

好きな北斗神拳の奥義は北斗残悔拳。

Portrait of a smiling man with glasses wearing a blue shirt, standing in front of a neutral background.

西坂 信哉(Shinya Nishizaka)

アマゾン ウェブ サービス ジャパン合同会社
ゲームソリューションアーキテクト

SIer のインフラエンジニアを経て 2019 年にアマゾンウェブサービスジャパン合同会社に入社。現在は主にゲーム業界のお客様の技術支援を担当しています。

二児の父として育児奮闘中。ときどきアフタヌーンティーに出かけます。