Reactアプリ公開の次は、バックエンド機能を追加する
前回の記事では、AWS Amplify公式ハンズオン Build a Full Stack React Application のTask 1として、Reactアプリの作成からGitHub連携、Amplify Hostingへの自動デプロイまでを進めました。
具体的には、ViteでReactプロジェクトを作成し、GitHubリポジトリにpushし、AWS AmplifyコンソールからGitHubのmainブランチを接続しました。最後に App.jsx を少し書き換えてpushし、公開URL側の表示が自動で更新されることも確認しました。
つまり前回の時点で、Reactアプリをクラウド上に公開し、GitHubにpushすれば自動で再デプロイされる状態まではできています。
ただし、ここまでで作ったのはあくまで「フロントエンドを公開する土台」です。ログイン機能、ユーザーごとのデータ保存、画像アップロードといった、いわゆるフルスタックアプリらしい機能はまだ動いていません。
今回のStep 2では、そのバックエンド側の準備を進めます。
AWS公式チュートリアルのTask 2では、Amplify Auth、Amplify Data、Amplify Storageを設定し、最後にcloud sandboxを起動する流れになっています。Amplify Gen 2では、バックエンドをTypeScriptで定義するコードファーストな開発体験が採用されています。
今回やること
今回のゴールは、Reactアプリに認証・データ保存・画像保存を追加するためのバックエンド構成を作ることです。
やることを整理すると、以下のようになります。
- 既存の認証設定を確認する
- Noteモデルを定義する
- Noteごとに所有者だけがアクセスできる認可ルールを設定する
- 画像保存用のStorage設定を追加する
backend.tsに auth / data / storage をまとめて登録する- AWS認証情報を設定する
- 必要に応じてIAM権限エラーに対応する
npx ampx sandboxを実行するamplify_outputs.jsonが生成されることを確認する
ここで大事なのは、今回のStep 2ではまだReact側の画面はほとんど変わらないという点です。
ログイン画面やノート作成画面を実際に表示するのは、次のStep 3です。今回はその前段階として、裏側で動く認証、データ、ストレージの設計図を作り、開発用のクラウド環境に反映するところまでを進めます。
Task 2の全体像
Task 1では、ReactアプリをAmplify Hostingにデプロイしました。
一方、Task 2では、アプリの裏側に必要なバックエンド機能を追加します。
Task 1
Reactアプリを作成して、GitHub経由でAmplify Hostingに公開する
Task 2
認証・データ・ストレージを定義して、cloud sandboxにデプロイする前回の記事で npm create amplify@latest -y を実行したため、プロジェクト内にはすでに amplify/ フォルダが作られています。
今回編集する主なファイルは以下です。
amplify/
auth/
resource.ts
data/
resource.ts
storage/
resource.ts
backend.tsauth/resource.ts は認証、data/resource.ts はデータモデル、storage/resource.ts はファイル保存、backend.ts はそれらをまとめる入口のような役割です。
認証設定を確認する
まずは認証設定です。
Task 1で npm create amplify@latest -y を実行した時点で、以下のファイルが作成されています。
amplify/auth/resource.ts公式チュートリアルでは、この認証設定はデフォルトのままで進めます。アプリではメールアドレスをデフォルトのログイン手段として使い、ユーザー登録時には確認メールが送信される構成です。
そのため、このStepでは auth/resource.ts を大きく書き換える必要はありません。
ここでのポイントは、Amplify Gen 2では認証設定もTypeScriptファイルとして管理することです。
AWSコンソールでCognitoを手動設定していくのではなく、アプリのバックエンド定義としてコードで管理していく流れになります。
Noteモデルを定義する
次に、ノートアプリで使うデータモデルを定義します。
編集するファイルは以下です。
amplify/data/resource.tsこのファイルを開き、以下のように更新します。
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';
const schema = a.schema({
Note: a
.model({
name: a.string(),
description: a.string(),
image: a.string(),
})
.authorization((allow) => [allow.owner()]),
});
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: 'userPool',
},
});ここでは Note というモデルを作成しています。
フィールドは以下の3つです。
name ノート名
description ノートの説明
image 画像ファイル名一見するとかなりシンプルですが、この定義が後のStep 3でノートの作成、一覧表示、削除につながっていきます。
公式チュートリアルでも、このNotesアプリはノートの作成・削除・一覧表示を学ぶためのサンプルとして説明されています。
allow.owner() の意味
このコードで特に重要なのが、以下の部分です。
.authorization((allow) => [allow.owner()])これは、作成したノートに対して「作成者本人だけがアクセスできる」という認可ルールを設定するものです。
公式チュートリアルでは、allow.owner() によってNoteレコードへのアクセスを所有者に制限し、Amplify側で owner フィールドが自動的に追加されると説明されています。
つまり、Aさんが作ったノートはAさんだけが見られ、BさんがログインしてもAさんのノートは見えない、という構成になります。
ノートアプリのように、ユーザーごとにデータを分けたい場合、この所有者ベースの認可はかなり重要です。
userPool をデフォルト認証方式にする
次に見るべきポイントはここです。
authorizationModes: {
defaultAuthorizationMode: 'userPool',
},userPool は、Cognito User Poolを使った認証ユーザー向けのアクセスを意味します。
今回のアプリでは、ログインしたユーザーが自分のノートを作る構成なので、データアクセスの基本を userPool にしています。
ここで「認証」と「認可」がつながります。
認証:誰がログインしているかを確認する
認可:その人がどのデータにアクセスできるかを決めるこのStep 2では、ログインユーザー単位でNoteデータを扱うための土台を作っているわけです。
画像保存用のStorageフォルダを作成する
次に、画像アップロード用のStorage設定を追加します。
amplify フォルダの中に、storage フォルダを作成します。
amplify/
storage/
resource.tsresource.ts ファイルを作成し、以下のコードを追加します。
import { defineStorage } from "@aws-amplify/backend";
export const storage = defineStorage({
name: "amplifyNotesDrive",
access: (allow) => ({
"media/{entity_id}/*": [
allow.entity("identity").to(["read", "write", "delete"]),
],
}),
});ここでは、画像などのファイルを保存するためのストレージリソースを定義しています。
パスは以下のような構成です。
media/{entity_id}/*{entity_id} は、ユーザーごとの識別子に置き換わる予約トークンです。
公式チュートリアルでは、このStorage設定により、画像をアップロードした本人だけがアクセスできるようになり、entity_id はアップロード時にユーザー識別子へ置き換えられると説明されています。
つまり、画像についてもノートと同じように、ユーザーごとに分離された保存領域を作るイメージです。
backend.ts にAuth・Data・Storageを登録する
ここまでで、認証、データ、ストレージの定義ファイルを用意しました。
ただし、それだけではまだAmplifyバックエンド全体には組み込まれていません。
次に amplify/backend.ts を開き、以下のように更新します。
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';
import { storage } from './storage/resource';
/**
* @see https://docs.amplify.aws/react/build-a-backend/ to add storage, functions, and more
*/
defineBackend({
auth,
data,
storage
});このファイルは、Amplifyバックエンド全体の入口のような役割です。
それぞれのリソース定義を作っただけではなく、最後に defineBackend() の中へ登録することで、Amplifyが「このアプリではAuth、Data、Storageを使う」と認識できるようになります。
個人的には、この構成はかなり分かりやすいと感じました。
auth/resource.ts 認証の定義
data/resource.ts データモデルの定義
storage/resource.ts ファイル保存の定義
backend.ts 全体のまとめファイルの役割が分かれているので、どこに何を書くのかが見通しやすいです。
AWS認証情報を設定する
ここで、npx ampx sandbox を実行する前に、ローカルPCからAWSアカウントへ接続するための認証情報を設定しておきます。
ここでいう認証情報は、先ほどの auth/resource.ts で設定したアプリ利用者向けのログイン認証ではありません。
AmplifyがAWS上にAuth、Data、Storageなどのリソースを作成するための、開発者用のAWS認証情報です。
ローカル環境からsandboxを作成する場合、IAMユーザーを作成し、そのユーザーにAmplifyのバックエンドをデプロイするための権限を付与します。
今回は、学習用・開発用としてIAMユーザーを作成し、そのユーザーのアクセスキーをローカル環境に設定する流れで進めます。
IAMユーザーを作成する
まず、AWSコンソールでIAMを開きます。
AWSコンソール上部の検索ボックスで IAM と検索し、IAMの画面に移動します。
次に、左側メニューから「ユーザー」を選択し、「ユーザーの作成」をクリックします。
ユーザー名は、たとえば以下のようにします。
amplify-local-devこのユーザーは、ローカルPCからAmplifyのsandboxを作成するために使う開発用ユーザーです。

権限はグループで管理する(任意)
ユーザー作成時の「許可を設定」画面では、以下を選びます。
※なお、IAMグループの作成は必須ではありません。今回は学習用に1人でAmplifyのsandboxを動かすだけなので、手順をシンプルにするため、IAMユーザーに AmplifyBackendDeployFullAccess ポリシーを直接アタッチして進めます。
複数人で運用する場合や、本番環境で権限管理を整理したい場合は、IAMグループを作成し、グループにポリシーを付与してユーザーを追加する方法が管理しやすいです。
ユーザーをグループに追加その後、「グループを作成」をクリックします。
グループ名は、たとえば以下のようにします。
amplify-dev-group次に、ポリシー検索欄で以下を検索してチェックします。
AmplifyBackendDeployFullAccessこのポリシーは、Amplify Gen 2のバックエンドをデプロイするために必要な権限をまとめたAWS管理ポリシーです。
チェックできたら、グループを作成します。
その後、作成した amplify-dev-group にユーザーを追加し、ユーザー作成を完了します。
アクセスキーを作成する
IAMユーザーを作成したら、そのユーザーの詳細画面を開きます。
次に「セキュリティ認証情報」タブを開き、「アクセスキーを作成」をクリックします。
用途を聞かれた場合は、以下を選びます。
Command Line Interface / CLI
作成が完了すると、以下の2つが表示されます。
Access Key ID
Secret Access Key
このうち、Access Key ID は AKIA... で始まる文字列になることが多いです。
Secret Access Key は、アクセスキー作成時に一度だけ表示されます。
この2つは、後でターミナルに入力します。
アクセスキーの取り扱いに注意する
アクセスキーは、AWSアカウントを操作するための重要な認証情報です。
そのため、以下の点に注意します。
- GitHubにpushしない
- ブログ記事やスクリーンショットに載せない
- 他人に共有しない
- 不要になったら削除する
- rootユーザーのアクセスキーは使わない
今回作っているのは学習用の開発ユーザーですが、それでもアクセスキーの取り扱いには注意が必要です。
ターミナルで認証情報を入力する
npx ampx sandbox を実行したとき、以下のように聞かれることがあります。
? Do you already have IAM User credentials? y
? Enter Access Key ID:この場合は、先ほど作成したIAMユーザーの Access Key ID を入力します。
たとえば以下のような形式です。
AKIAxxxxxxxxxxxxxxxx次に、Secret Access Keyを聞かれます。
? Enter Secret Access Key:ここには、アクセスキー作成時に表示された Secret Access Key を入力します。
入力しても画面には表示されない場合がありますが、それで正常です。
最後にリージョンを聞かれたら、使用するリージョンを入力します。
たとえば東京リージョンを使うなら以下です。
ap-northeast-1シドニーリージョンを使うなら以下です。
ap-southeast-2AWSコンソール側で開いているリージョンと、sandboxで使うリージョンはなるべく揃えておくと分かりやすいです。
入力例は以下のようになります。
? Do you already have IAM User credentials? y
? Enter Access Key ID: AKIAxxxxxxxxxxxxxxxx
? Enter Secret Access Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
? Enter the AWS region to use with the 'default' profile: ap-northeast-1この設定が完了すると、ローカルPCからAWSへ接続するための認証情報が設定され、npx ampx sandbox でAWS上にバックエンドを作成できるようになります。
cloud sandboxを起動する
バックエンド定義を更新したら、いよいよcloud sandboxを起動します。
プロジェクトのルートフォルダ、つまり notesapp 直下で以下を実行します。
npx ampx sandbox公式チュートリアルでは、cloud sandboxは開発者ごとの分離された開発環境として説明されています。フルスタックアプリを素早く構築・テスト・反復するための環境で、チーム内の各開発者がそれぞれ自分用の使い捨てsandboxを利用できます。
ここで初めて、Task 1で作った amplify/ 配下の定義が、実際のAWSリソースとして展開されます。
Task 1の時点では、あくまでローカルにバックエンドの設計図があるだけでした。
Task 2で npx ampx sandbox を実行することで、認証、データ、ストレージの開発用バックエンドがAWS上に作られていきます。
npm create amplify と npx ampx sandbox の違い
今回、個人的に一番混乱しやすいと感じたのは、以下2つのコマンドの違いです。
npm create amplify@latest -y
npx ampx sandboxこの2つは似ているようで、役割がまったく違います。
npm create amplify@latest -y
Amplifyバックエンドのひな形をローカルに作る
npx ampx sandbox
その定義をもとに、AWS上へ開発用バックエンドを作る前回の記事で実行した npm create amplify@latest -y は、プロジェクトに amplify/ フォルダを追加し、バックエンド定義ファイルのひな形を作るコマンドでした。
一方、今回の npx ampx sandbox は、その定義をもとにAWS上へ開発用バックエンド環境を作るコマンドです。
この違いを理解しておくと、以下のような混乱を避けやすくなります。
amplify/ フォルダを作ったのに、なぜAWS側にリソースが見えないのか?
→ まだ sandbox を起動していないから
sandbox を起動したら何が起きるのか?
→ 定義したAuth、Data、Storageが開発用クラウド環境として作られるつまり、npm create amplify@latest -y は「設計図を作る」、npx ampx sandbox は「設計図をもとに実際の開発環境を作る」と考えると分かりやすいです。
amplify_outputs.json が生成される
sandboxの起動が完了すると、プロジェクト内に以下のファイルが生成されます。
amplify_outputs.json公式チュートリアルでも、cloud sandboxのデプロイ完了後に amplify_outputs.json がプロジェクトへ追加されると説明されています。
このファイルには、Reactアプリがバックエンドへ接続するために必要な設定情報が入ります。
次のStep 3では、このファイルをReact側から読み込みます。
import outputs from "../amplify_outputs.json";そして、以下のようにAmplifyを設定します。
Amplify.configure(outputs);つまり amplify_outputs.json は、今回作ったクラウド側のバックエンドと、次回作るReactフロントエンドをつなぐための接続情報です。
Task 2の最後にこのファイルが生成されていれば、次のTaskへ進む準備ができています。
ここまでで作られたもの
Task 2が終わった時点で、アプリの裏側には以下の構成が用意されています。
Auth
ログイン・サインアップ用の認証基盤
Data
Noteモデルを扱うデータ基盤
Storage
画像ファイルを保存するストレージ基盤
cloud sandbox
開発用のクラウドバックエンド環境ただし、まだReact側の画面はこのバックエンドに接続していません。
そのため、ブラウザで公開URLやローカル画面を見ても、この段階では大きな変化はありません。
ここで作ったものは、あくまで次のStep 3で使うためのバックエンド基盤です。
今回のポイント
今回のポイントを整理すると、以下の3つです。
1. 認証・データ・ストレージはTypeScriptで定義する
2. allow.owner() によってユーザーごとのデータ分離を行う
3. npx ampx sandbox で開発用バックエンドをAWS上に作るAmplify Gen 2では、バックエンド構成をコードで管理できるため、「どのリソースを使っているのか」がファイル上で追いやすくなっています。
特に今回のNotesアプリでは、認証、データ、ストレージの3つがすべてユーザー単位で動く構成になっています。
ログインしたユーザーだけが
自分のノートを作成できて
自分の画像だけを保存・参照できるこの形は、実務で作る小規模な業務アプリや個人向けWebアプリでもかなり基本になる構成だと感じました。
まとめ
今回は、AWS Amplify公式ハンズオンのTask 2として、cloud sandboxの起動とバックエンド構成の追加を進めました。
前回のTask 1では、ReactアプリをGitHub経由でAmplify Hostingに公開し、自動デプロイの流れを確認しました。今回のTask 2では、その公開済みReactアプリに対して、認証・データ保存・画像保存を追加するためのバックエンド定義を作成しました。
data/resource.ts では Note モデルを作成し、allow.owner() によってユーザーごとのデータ分離を設定しました。storage/resource.ts では、画像ファイルをユーザーごとに保存できるようにし、最後に backend.ts でAuth、Data、Storageをまとめて登録しました。
そして npx ampx sandbox を実行することで、これらの定義をもとに開発用のクラウドバックエンド環境を起動しました。
見た目としてはまだ大きく変わりませんが、ここで認証・データ保存・画像アップロードの土台が整いました。
次回のStep 3では、React側にAmplify UIを組み込み、ログイン画面、ノート作成、画像アップロード、ノート削除までを実際に動かしていきます。