5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

昨年、ANGEL Dojo 2024に参加し、3か月間でサービスの企画から開発までを行う経験をしました。

私たちのチームは、電話練習アプリ「Tele Talk Tutor(T3)」を開発しました。
このサービスは、電話対応が苦手な方向けに、営業アポ取りや飲食店アルバイトの予約対応など、リアルな場面での電話練習を提供します。
この電話練習機能にて、AppSyncからLambdaを呼び出す実装を行ったので、その流れを本記事に残しておこうと思います。

関連記事
本記事では取り上げていませんが、ユーザの電話対応内容からフィードバックを提供する機能も開発しました。以下の記事でチームメンバーが一部紹介してくれています!

電話練習機能では、ユーザの音声をWebSpeechAPIでテキストに起こし、Lambdaに送信してBedrockで返答内容を生成して返却します。
ここで、フロントエンドからLambdaを呼び出すため、AppSyncを設計しています。

AppSyncとは
AWS AppSyncは、GraphQLを使用してDynamoDBやLambdaなどのデータソースに対してアクセスや操作ができるサービスです。

AppSyncの設計(GraphQL)

API作成

まずは、AWS AppSyncコンソールの画面から、GraphQL APIを作成します。
※リソースは独自で設定するよう選択するので、詳細設定は省略

スキーマ

次に、左メニューからスキーマ設定画面を開いて、パラメータやデータ操作の定義を行っていきます。
Mutation要求の引数で使用する項目をinput型で定義します。(!マーク:必須項目)
戻り値はtypeを使用して定義します。

input SendDataInput {	
	sessionId: String!
	message: String!
}	

type SendDataOutput {	
	audioUrl: String!
}

データ操作の定義については、今回の処理は単純なデータ取得(Query)ではなく、リクエストデータからのレスポンスデータ作成なので、Mutationを使用しています。

type Mutation {	
	sendData(input: SendDataInput!): SendDataOutput
}	

これでスキーマ定義は完了です。

データソース

次に、左メニューからデータソース設定画面に行き、以下項目を入力します。

  • データソース名
  • 説明
  • データソース
    ※今回は「AWS Lambda関数」を選択します。関数は既に作成済みとします。
    image.png

ここまで選択すると、以下の項目が表示されるため、それぞれ入力します。

  • リージョン
  • 関数(選択もしくは手動入力)
  • ロール(新規もしくは既存から選択)
    hidden_function.png

リゾルバー

再度スキーマ画面に戻り、画面右のリゾルバーから、先ほど定義したMutationのアタッチを選択します。(以下画像では、既にアタッチ済みのためボタンは表示されていませんが、設定が完了すると画像の通りになります。)
enhance_function.png

  • リゾルバータイプ
    今回は単一のデータソース(Lambda)からの取得になるので、「ユニットリゾルバー」を選択します。
  • その他設定(リゾルバ―ランタイム)
    「Velocityテンプレート言語(VTL)」を選択します。
  • データソース
    先ほど設定したものを選択します。
    image.png
    作成が完了すると、次の設定画面へ移ります。

リクエストマッピングテンプレート

ここでは、サンプルテンプレートから「invoke and forward arguments」を選択します。
以下の内容が自動で設定されます。

#**
The value of 'payload' after the template has been evaluated
will be passed as the event to AWS Lambda.
*#
{
  "version" : "2017-02-28",
  "operation": "Invoke",
  "payload": $util.toJson($context.args)
}

レスポンスマッピングテンプレート

同じくサンプルテンプレートから「Return lambda result」を選択します。
こちらも、以下の内容が自動で設定されます。

$util.toJson($context.result)

これで、AppSync側の設定は完了です!

TypeScriptでの実装

今回フロントエンドはTypeScriptで実装していましたので、AppSyncとの接続方法も残しておきます。
一部気になる設計もあるかと思いますが、とりあえず動くことがメインの記述となります。

開発環境

  • Node.js:v20.14.0
  • TypeScript:v5.5.3
Phone.tsx
  // Apollo ClientがGraphQLリクエストを送信するためのAppSyncエンドポイントを設定
  const httpLink = new HttpLink({
    uri: "https://xxx",
  });
  // AppSyncエンドポイントへのアクセスを認証するためのAPIキーを設定
  const authLink = setContext((_, { headers }) => {
    return {
      headers: {
        ...headers,
        "x-api-key": "yyy",
      },
    };
  });

  // Apollo Client(状態管理ライブラリ)が使用するリンクを作成
  const link = ApolloLink.from([authLink, httpLink]);
  // ApolloClientのインスタンスを作成
  const client = new ApolloClient({
    link: link,
    cache: new InMemoryCache(),
  });

  // GraphQLミューテーションを定義
  const SEND_DATA_MUTATION = gql`
    mutation SendData($input: SendDataInput!) {
      sendData(input: $input) {
        audioUrl
      }
    }
  `;
  // インターフェースを定義
  interface SendDataOutput {
    audioUrl: string;
  }
  interface SendDataInput {
    sessionId: string;
    message: string;
  }

  // Lambdaに送信する関数を定義
  async function sendDataToLambda(data: SendDataInput) {
    const response = await client.mutate<{ sendData: SendDataOutput }>({
      mutation: SEND_DATA_MUTATION,
      variables: { input: data },
    });
    // 音声ファイルのURLを取得
    const audioUrl = response.data?.sendData.audioUrl;
    // その他処理
  }

  // 使用例
  const iconClick = () => {
    const data = {
      sessionId: "sessionId",
      message: "message",
    };
    sendDataToLambda(data);
  };

あとがき

私は、普段の業務でAWSやTypeScriptをほとんど使わない初心者でしたが、そこまで複雑な設計ではなかったので、使いながら慣れることができました。
本機能だけでなく、アプリケーション内の別機能でもAppSyncを利用しましたが、異なるDBやLambda関数などを1つのGraphQLスキーマで扱うので単一のエンドポイントからデータを取得できて、開発の負担はかなり減ったと思います。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?