AWSのAmplify入門ガイド:モダンなフルスタックアプリケーション開発の新時代のヒーロー画像

AWSのAmplify入門ガイド:モダンなフルスタックアプリケーション開発の新時代


AWSのAmplify入門ガイド

AWS Amplify はAWSが提供するモダンなウェブおよびモバイルアプリケーション開発のためのフルスタックフレームワークです。このガイドでは、特に2024年から正式提供が始まった「Amplify Gen2」の基本概念から実際の利用方法、そして運用のベストプラクティスまでを解説します。

Amplifyとは何か

AWS Amplifyは、フロントエンドおよびバックエンドの開発を統合し、モダンなウェブおよびモバイルアプリケーションを迅速に構築するためのプラットフォームです。UIコンポーネント、認証、ストレージ、API、ホスティング、CI/CDなど、アプリ開発に必要な全てのコンポーネントを提供します。

特に2024年に正式リリースされた「Amplify Gen2」は、TypeScriptの型安全性とパフォーマンスの向上に焦点を当てた次世代のフレームワークです。

Amplifyの主な特徴は以下の通りです:

  • 統合されたフルスタック開発体験: フロントエンドからバックエンドまで一貫した開発体験
  • コード生成機能: GraphQL APIやデータモデルを定義するだけでコードを生成
  • クラウドリソースの自動プロビジョニング: インフラストラクチャをコードで定義し、自動デプロイ
  • スケーラブルなバックエンド: AppSync(GraphQL)、Lambda、DynamoDB等のAWSサービスをシームレスに統合
  • 豊富な認証機能: CognitoによるSSOや多要素認証などのエンタープライズレベルのセキュリティ
  • CI/CD & ホスティング: プレビュー環境を含むフルマネージドのCI/CDとホスティング
  • モニタリング機能: アプリのパフォーマンスと使用状況の詳細な分析

Amplify Gen2の主要な改善点

Amplify Gen2は、従来のGen1に比べて以下の点が大幅に改善されています:

  1. タイプセーフなAPI: TypeScriptの型システムを最大限に活用し、開発時のエラー検出が向上
  2. ディレクトリベースのルーティング: Next.js/Remixスタイルのファイルベースルーティング
  3. ビルドパフォーマンスの向上: データアクセス層の最適化による高速化
  4. バックエンドのコードファースト開発: UIでの設定に頼らず、すべてをコードで定義可能
  5. 最新Reactパターンのサポート: React Server Components、Suspenseなどに対応
  6. 開発ツール統合: VSCodeとの統合が強化され、チーム開発の効率が向上

Amplify Gen2のアーキテクチャ

Amplify Gen2は、以下の主要なコンポーネントから構成されています:

フロントエンド

  • Amplify UI: ReactやVue.js用のUIコンポーネントライブラリ
  • Amplify JS: バックエンドとの通信をサポートするJavaScriptライブラリ
  • @aws-amplify/backend-cli: バックエンドリソースを管理するコマンドラインインターフェース

バックエンド

  • データ層: AppSync (GraphQL)、DynamoDB、Auroraなど
  • 認証層: Amazon Cognito
  • ストレージ層: Amazon S3
  • 関数層: AWS Lambda
  • API層: AppSync GraphQL API、REST API

デプロイ&ホスティング

  • Amplify Hosting: グローバルCDN、CI/CD、プレビュー環境を含むホスティングサービス
  • Amplify Console: バックエンドリソースを管理するための統合コンソール

Amplifyの始め方

1. 開発環境のセットアップ

AWSアカウントを設定します:

aws configure

2. プロジェクトの作成

新しいAmplify Gen2プロジェクトを作成します:

# Next.jsプロジェクトの場合
npx create-next-app my-app
cd my-app

# Amplify Gen2のパッケージをインストール
npm install aws-amplify @aws-amplify/backend @aws-amplify/backend-cli

3. バックエンドの初期化

プロジェクトでAmplify Gen2を初期化します:

npx ampx init

4. バックエンドリソースの追加

バックエンドリソースを追加します(例:GraphQL API):

// ./amplify/data/resource.ts
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';

// データモデルをTypeScriptで定義
const schema = a.schema({
  Todo: a
    .model({
      content: a.string().required(),
      completed: a.boolean().default(false),
      priority: a.enum(['LOW', 'MEDIUM', 'HIGH']).required(),
    })
    .authorization(allow => [allow.public.to(['read']), allow.authenticated.to(['create', 'update', 'delete'])]),
});

// スキーマをエクスポート
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: 'apiKey',
    apiKeyAuthorizationMode: {
      expiresIn: 30, // APIキーの有効期限(日数)
    },
  },
});

5. サンドボックス環境でローカル開発

Amplify Gen2では、開発中に変更をテストするためのサンドボックス環境を提供しています:

npx ampx sandbox

このコマンドにより、作成したバックエンドリソースがクラウドにデプロイされ、ファイルの変更を検知して自動的に再デプロイされます。

6. フロントエンドとの統合

Amplify Gen2をフロントエンドアプリケーションに統合します:

// ./app/page.tsx
'use client';

import { useState, useEffect } from 'react';
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '@/amplify/data/resource';

// Gen2クライアントの生成
const client = generateClient<Schema>();

export default function TodoList() {
  const [todos, setTodos] = useState<any[]>([]);
  const [content, setContent] = useState('');

  useEffect(() => {
    fetchTodos();
  }, []);

  async function fetchTodos() {
    const todoData = await client.models.Todo.list();
    setTodos(todoData.data);
  }

  async function addTodo() {
    await client.models.Todo.create({
      content,
      priority: 'MEDIUM',
    });
    setContent('');
    fetchTodos();
  }

  return (
    <div>
      <h1>Todo List</h1>
      <input
        value={content}
        onChange={(e) => setContent(e.target.value)}
      />
      <button onClick={addTodo}>Add Todo</button>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>
            {todo.content} - {todo.priority}
          </li>
        ))}
      </ul>
    </div>
  );
}

7. アプリケーションのデプロイ

Amplify Hostingを使用してアプリケーションをデプロイします。Amplify Consoleでリポジトリ接続を設定するか、以下のようにCLIでホスティングを追加できます:

# Amplify Consoleで新しいアプリを作成し、Gitリポジトリと接続します
# その後、デプロイはGitへのプッシュで自動的に実行されます
git push

Amplify Gen2の主要機能

データ(GraphQL API)

Amplify Gen2では、スキーマファーストではなく、コードファーストのアプローチを採用しています:

// データモデルの定義
const schema = a.schema({
  Post: a
    .model({
      title: a.string().required(),
      content: a.string(),
      status: a.enum(['DRAFT', 'PUBLISHED']).required(),
      comments: a.hasMany('Comment'),
    })
    .authorization(allow => [
      allow.authenticated.to(['create', 'update', 'delete']),
      allow.public.to(['read']),
    ]),

  Comment: a
    .model({
      content: a.string().required(),
      post: a.belongsTo('Post'),
    })
    .authorization(allow => [
      allow.authenticated.to(['create']),
      allow.public.to(['read']),
      allow.owner.to(['update', 'delete']),
    ]),
});

認証

Amplifyは、Amazon Cognitoを使用してユーザー認証を簡単に実装できます:

// ./amplify/auth/resource.ts
import { defineAuth } from '@aws-amplify/backend';

export const auth = defineAuth({
  loginWith: {
    email: true,
    phone: true,
    socialProviders: {
      google: true,
      apple: true,
    },
  },
  multifactor: {
    mode: 'OPTIONAL',
    sms: true,
    totp: true,
  },
  passwordPolicy: {
    minLength: 8,
    requireNumbers: true,
    requireSpecialCharacters: true,
    requireUppercase: true,
    requireLowercase: true,
  },
});

フロントエンドでの使用例:

'use client';

import { signUp, confirmSignUp, signIn, getCurrentUser } from 'aws-amplify/auth';
import { useState } from 'react';

export default function Authentication() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [code, setCode] = useState('');

  async function handleSignUp() {
    try {
      await signUp({
        username: email,
        password,
        options: {
          autoSignIn: true,
        },
      });
      // 確認コード送信完了メッセージを表示
    } catch (error) {
      console.error('エラー:', error);
    }
  }

  async function handleConfirmSignUp() {
    try {
      await confirmSignUp({
        username: email,
        confirmationCode: code,
      });
      // サインアップ完了メッセージを表示
    } catch (error) {
      console.error('エラー:', error);
    }
  }

  async function handleSignIn() {
    try {
      await signIn({
        username: email,
        password,
      });
      // サインイン完了、ダッシュボードへリダイレクト
    } catch (error) {
      console.error('エラー:', error);
    }
  }

  // レンダリング...
}

ストレージ

Amplify StorageはAmazon S3を使用したファイルストレージを提供します:

// ./amplify/storage/resource.ts
import { defineStorage } from '@aws-amplify/backend';

export const storage = defineStorage({
  name: 'myAppStorage',
  access: {
    auth: {
      authenticated: {
        operations: ['read', 'write'],
      },
      unauthenticated: {
        operations: ['read'],
      },
    },
  },
});

フロントエンドでの使用例:

'use client';

import { uploadData, downloadData, remove } from 'aws-amplify/storage';
import { useState } from 'react';

export default function FileStorage() {
  const [file, setFile] = useState<File | null>(null);
  const [fileUrl, setFileUrl] = useState('');

  async function handleFileUpload() {
    if (!file) return;

    try {
      const result = await uploadData({
        key: `uploads/${file.name}`,
        data: file,
        options: {
          contentType: file.type,
          accessLevel: 'guest',
        },
      });
      console.log('アップロード成功:', result);
    } catch (error) {
      console.error('アップロードエラー:', error);
    }
  }

  async function handleFileDownload(key: string) {
    try {
      const result = await downloadData({
        key,
      });
      // Blobに変換してURLを作成
      const url = URL.createObjectURL(result.body);
      setFileUrl(url);
    } catch (error) {
      console.error('ダウンロードエラー:', error);
    }
  }

  // レンダリング...
}

Amplify Hostingの料金体系(東京リージョン)

Amplify Hostingの料金は主に以下の要素で構成されます:

コンピューティングとホスティング

サービス単位料金
ビルド時間最初の1,000分/月 無料、以降 $0.01/分
ホスティングGB/月 (保存)最初の5GB/月 無料、以降 $0.023/GB
データ転送GB/月最初の15GB/月 無料、以降 $0.15/GB

プレビュー環境

サービス単位料金
プレビュー環境環境/時間$0.01/プレビュー環境/時間

サーバーサイドレンダリング(SSR)

サービス単位料金
コンピューティングGB秒最初の400,000 GB秒/月 無料、以降 $0.000016667/GB秒
リクエスト件数最初の100万リクエスト/月 無料、以降 $0.20/100万リクエスト

※全ての価格は2024年6月時点の概算であり、実際の料金はAWS公式サイトでご確認ください。

Amplify Gen2のユースケース

1. スタートアップ向けMVP開発

  • メリット: 短期間かつ少ないリソースで機能性の高いアプリを開発可能
  • 実装例: フルスタックJSフレームワーク(Next.js、Remix等)+ Amplify Gen2でスケーラブルなサービスを迅速に構築

2. エンタープライズアプリケーション

  • メリット: セキュリティとスケーラビリティを維持しながら、モダンなアーキテクチャを採用
  • 実装例: マイクロフロントエンド+GraphQLを活用した大規模アプリケーション

3. モバイルアプリのバックエンド

  • メリット: モバイルに特化した認証、ストレージ、APIを統合的に構築
  • 実装例: React Native + Amplify Gen2でクロスプラットフォームアプリを開発

4. JAMstackウェブサイト

  • メリット: コンテンツ管理と高パフォーマンスな静的サイト生成を組み合わせ
  • 実装例: Astro + Amplifyでブログやマーケティングサイトを構築

Amplify Gen2のベストプラクティス

アプリケーション設計

  1. 環境分離: 開発、テスト、本番環境を分離し、Amplifyのブランチベースのデプロイを活用
  2. インフラストラクチャ・アズ・コード (IaC): amplify/ディレクトリ下のコードで全てのインフラを定義
  3. 段階的な機能追加: 認証→データ→ストレージの順でバックエンドを構築

セキュリティとスケーリング

  1. 認証のカスタマイズ: ビジネス要件に合わせた認証フロー(ソーシャルログイン、MFA等)の構成
  2. きめ細かいアクセス制御: GraphQL APIの認可ルールを慎重に設計
  3. DynamoDBの適切な容量設定: 予想されるトラフィックに基づいたキャパシティの設定
  4. データモデルの最適化: 効率的なクエリを実現するアクセスパターンの設計

パフォーマンス最適化

  1. SSRとStatic Generationの適切な選択: ページの性質に応じたレンダリング方法の選択
  2. CDNキャッシュの活用: Amplify Hostingの組み込みCDNを最大限活用
  3. API呼び出しの最適化: バッチ処理とクエリ最適化でネットワークリクエストを削減
  4. オフライン対応: データの同期とオフラインストレージの実装

CI/CDとデプロイ

  1. 自動テスト: ビルドパイプラインに単体テストと統合テストを組み込む
  2. プレビュー環境の活用: PRごとに自動的に作成されるプレビュー環境でレビュー効率を向上
  3. バックエンド変更の管理: データモデル変更時のマイグレーション戦略を計画
  4. デプロイ後のモニタリング: CloudWatchとアプリケーションパフォーマンスモニタリングの設定

まとめ

AWS Amplify Gen2は、モダンなWeb/モバイルアプリケーション開発を大幅に効率化するフレームワークです。TypeScriptの型安全性、自動生成されるバックエンド、統合されたホスティング環境により、開発者はビジネスロジックに集中できます。

特にGen2における型安全性の強化とパフォーマンスの最適化は、大規模アプリケーション開発においても強力なメリットをもたらします。スタートアップから大企業まで、迅速かつ安全にスケーラブルなアプリケーションを構築したいチームにとって、Amplifyは理想的な選択肢と言えるでしょう。

実は、このブログサイト自体もAmplify Hostingを利用して配信されています。Astroで構築されたJAMstackアーキテクチャとAmplifyのCI/CD機能の組み合わせにより、記事更新からデプロイまでが自動化され、高速で安定したブログ体験を提供しています。このように、Amplifyはさまざまな規模と種類のプロジェクトに柔軟に対応できる、実用的かつパワフルなプラットフォームです。