1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Amplify Gen2 で作る1万人規模アンケートサービス『仮想民声』

Last updated at Posted at 2025-08-20

はじめに

この記事でわかる・できること

Amplify Gen2 を使って作成した、1万人規模アンケートサービス『仮想民声』の紹介と、その際のCognito + Googleログイン連携の実装ポイントやハマった点を解説します。

開発には主にこちらのQiita記事を参考にしました。

補足:Amplify Gen2 は情報が少なく、フロントエンドの Amplify JavaScript Library も v5 → v6 に変わったことで使い方が大きく変化しています。実装時に苦戦した部分をまとめました。

この記事の対象者

  • 1万人規模アンケートサービス『仮想民声』を利用したい人
  • Amplify Gen2 で開発を行っている、もしくは行いたい人

仮想民声の紹介

なぜ仮想民声を作ったのか

アンケートは、1万人規模の回答を集めることや、対象者条件を満たす人を集めることが大変で、実施に多くのコストと労力がかかります。

そこで、AI によって大規模アンケートの回答を自動生成することで、この課題を解決できると考え、本サービスを開発しました。

仮想民声とは

「仮想民声」は、1万人分のアンケート回答を仮想的に生成して統計を出せるサービスです。

使い方

1. ログイン
まずログイン画面が表示され、メールアドレス または Googleアカウント でログインできます。

2. アンケート内容の作成
「作成画面」で 次へ を押すと、ターゲットの基本情報(年齢、性別、国etc)を柔軟に指定できます。
質問形式は以下の6種類から選択可能です。

  • 単一選択
  • 複数選択
  • 自由記述
  • 均等目盛
  • 日付
  • 時刻

3. アンケートの生成
最後にアンケート内容を確認し、送信します。

📋アンケート生成画面
image.png

4. 結果の確認
作成したアンケートは「アンケート一覧」に表示されます。
回答結果は 「回答結果」ボタン から見ることができ、1万人規模の集計結果と、うち20人の詳細な回答一覧の閲覧が可能です。
なお、アンケート結果の作成には 1~2分程度 かかり、その間は「作成中」と表示されます。失敗した場合は「作成失敗」と表示されます。

集計方法:

  • 自由記述 → ワードクラウド & 出現頻度グラフで出力
  • その他の回答形式 → クロス集計で出力

📋集計結果例
< 自由記述 >
image.png

< 日付 >
image.png

5. 追加質問
回答一覧の20人には、追加で質問をし、回答を掘り下げることができます。

📋回答一覧
image.png

サービスの特徴

  • Googleアカウントでログイン可能
  • 簡単に独自のアンケートを作成し、即座に統計を生成
  • OpenAIを使って回答や集計を自動生成するため、世間の傾向を取り入れてくれる
  • 回答者には追加質問も可能で、対話的にデータを掘り下げられる

📺 デモ動画

👉 実際のサービスはこちらから利用できます: 仮想民声から利用可能です。

実装

次に、実装について説明します。

動作環境・使用するツールや言語

  • Amplify Gen2
  • Node.js v20 (fnm use 20)
  • React + Umi.js + Ant Design Pro
  • AWS Cognito, DynamoDB, Lambda
  • OpenAI API

アーキテクチャ

  1. ログイン
    Cognito + Google Federated Login

  2. アンケート生成
    ユーザーがフロントエンドからアンケート「作成」ボタンを押すと DynamoDB にデータ保存

  3. データ保存をトリガーに Lambda 実行
    DynamoDB Streams 経由で Lambda 起動
    Lambda 内で OpenAI API を呼び出し、仮想回答を生成

  4. フロントエンドで結果を表示
    React (Umi.js + Ant Design Pro) で UI を構築
    DynamoDB から取得した回答データを一覧・チャートで表示

  5. 追加質問
    集計結果ページの「質問する」ボタンから別 Lambda を呼び出し
    回答データをもとに OpenAI API で追加質問応答を生成

image.png

Amplify Gen2 でハマった点と解決策

今回、Amplify Gen2 を使用してコードベースでサービスを実装し、デプロイまで行いました。主に以下の作業を行いました。

  • Lambda 関数の生成・呼び出し
  • DynamoDB テーブル名の取得
  • Cognito と Google ログイン連携
  • 認証済みユーザーによる DynamoDB / Lambda 呼び出し権限付与
  • アンケート生成用プロンプトの作成
  • デプロイ設定(amplify.yml)の作成

特に情報が少なく苦戦した部分は以下です。

  1. DynamoDB テーブル名の取得
  2. Cognito と Google 連携
  3. 認証済みユーザーによる DynamoDB / Lambda 呼び出し権限付与
  4. デプロイ設定(amplify.yml)
  5. アンケート生成用プロンプト作成

1. DynamoDB テーブル名の取得

DynamoDB のテーブル名は AWS コンソールから確認できますが、開発中は環境によってテーブル名が毎回変わることがあります。
そのため、コードから動的に取得する方法が便利です。

以下の例では、Amplify Gen2 で定義したバックエンドオブジェクトから DynamoDB テーブル名を取得しています。

amplify\backend.ts
const backend = defineBackend({
  auth,
  data,
  myDynamoDBFunction,
  myChatResponder,
});

// DynamoDB テーブル取得
const todoTable = backend.data.resources.tables['Survey'];

ポイント
backend.data.resources.tables には、デプロイ時に生成された全テーブル情報が格納されます。
これにより、ハードコーディングせずにテーブル名を参照でき、環境が変わってもコードを修正する必要がありません。

2.cognitoとのgoogle連携

Umi.js アプリで Google ログインを使う際の手順です。

概要

  • AWS Cognito User Pool で Google アカウントログインを有効化
  • Amplify UI React の Authenticator と useAuthenticator を使用
  • useNavigate でログイン後にページ遷移
  • ファイル構造の都合で Authenticator.Provider を使い、認証情報を下層コンポーネントに渡す

Cognito + Google 設定例

amplify\auth\resource.ts
export const auth = defineAuth({
  loginWith: {
    email: true,
    externalProviders: {
      google: {
        clientId: secret('GOOGLE_CLIENT_ID'),
        clientSecret: secret('GOOGLE_CLIENT_SECRET'),
        scopes: ['email'],
      },
      callbackUrls: ['http:xxxxx', ],
      logoutUrls: ['http:xxxxx', ],
    }
  },
}

app.tsx での Provider 設定

src\app.tsx
import { Authenticator } from '@aws-amplify/ui-react';

Amplify.configure(outputs)

export const rootContainer = (container: React.ReactNode) => {
  return <Authenticator.Provider>{container}</Authenticator.Provider>;
};

ログイン画面の実装例

src\pages\user\login\index.tsx
import { useEffect } from 'react';
import { useNavigate } from '@umijs/max';
import { Authenticator, useAuthenticator } from '@aws-amplify/ui-react';

function LoginContent() {
  const navigate = useNavigate();
  const { user, route } = useAuthenticator((context) => [context.user, context.route]);

  useEffect(() => {
    if (route === 'authenticated' && user) {
      navigate('/survey/builder', { replace: true });
    }
  }, [route, user, navigate]);

  if (route === 'authenticated') {
    return null; // ログイン済みなので表示しない
  }

  return <div>ログインフォームを表示中...</div>;
}

export default function LoginPage() {
  return (
    <Authenticator socialProviders={['google']}>
      <LoginContent />
    </Authenticator>
  );
}

3.認証済みユーザーによる DynamoDB / Lambda 呼び出し権限の付与

Amplify v6 では、User Pool 権限を用いてアクセス制御が可能です。

amplify\data\resource.ts
const schema = a.schema({
  Survey: a
    .model({
      ...省略...
      }),
    })
    .authorization((allow) => [
      allow.owner(), //ログイン済みユーザは自分自身のデータのみアクセス可
    ]),
})

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: 'userPool',
  },
})

アクセス時には authMode を指定します。

 const result = await client.models.Survey.create(formatted, {authMode: 'userPool' });
 const client = generateClient<Schema>({ authMode: 'userPool' });       

4.デプロイ設定 (amplify.yml)

Amplify でのデプロイには、プロジェクトに合わせた amplify.yml の作成が必要です。
以下は今回のサービス用に作成した例です。今回の環境では、環境変数で Node.js のバージョンを 20 (NODEJS_VERSION=20)に固定しています。

version: 1
backend:
  phases:
    build:
      commands:
        - npx ampx pipeline-deploy --branch YOUR_BRANCH --app-id YOUR_APP_ID
        - npx ampx generate outputs --branch YOUR_BRANCH --app-id YOUR_APP_ID
frontend:
  phases:
    preBuild:
      commands:
      - rm -rf node_modules
      - rm -rf package-lock.json
      - rm -rf .umi
      - npm install --legacy-peer-deps --include=optional
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: dist
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*

5.アンケート結果生成用プロンプトの作成

プロンプトが1万2千文字以上になってしまったので、分けて送信しデータを生成してもらうことで、精度を向上させることができました。

まとめ

今回は、1万人規模アンケートサービス 「仮想民声」 の開発を通して、Amplify Gen2 を活用しました。

ただし課題もありました。

  • Amplify Gen2 に関する情報が少ない
  • Amplify JavaScript Library のバージョン更新で使い勝手が大きく変わっていた
  • AI にアンケート集計を依頼すると、プロンプトが長くなりすぎる
  • 集計結果のパーセンテージが100%にならなかったり、表がきりの良い数に丸められてしまう

今後開発を進める際は、公式ドキュメントを参照しつつ、ChatGPTや各種サイトを併用して進めるのが効果的だと感じました。

参考資料

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?