はじめに
Webアプリケーションを開発する際、フロントエンドとバックエンドが異なるドメインに配置されていると、CORS(クロスオリジンリソースシェアリング)の問題が発生し、ブラウザによるリクエストが制限されます。このCORS問題を解決するためには、特定のポリシーを設定する必要がありますが、これが予想以上に複雑で、設定ミスやセキュリティリスクを招くこともあります。
このような問題を避けるため、AWSのCloudFront、S3、API Gatewayを利用して、フロントエンドとバックエンドを同じドメインでデプロイする方法があります。このアプローチを使えば、CORSの設定を不要にし、セキュリティやパフォーマンスの向上、運用の簡素化など、実務上でも多くの利点が得られます。
実務における同じドメインでのデプロイの有用性
-
CORSの問題を避けられる
異なるドメイン間での通信はCORSの設定が必要になりますが、同じドメインに統合することで、この設定が不要となり、エラーを減らし、実装が簡素化されます。 -
セキュリティの強化
同じドメインでの運用は、セッション管理やCookieの処理が容易になります。例えば、認証済みのユーザー情報やセッションの共有が同じドメインで行われるため、セキュリティリスクを減らすことができます。また、CSRF(クロスサイトリクエストフォージェリ)の防御も簡単に行えます。 -
パフォーマンスの向上
CloudFrontを利用することで、世界中のユーザーに最適化された配信が可能です。さらに、フロントエンドとバックエンドが同じドメインであるため、キャッシュ管理やリクエストのルーティングが効率化され、応答時間が短縮されます。 -
運用の簡素化
ドメインを統一することで、DNS設定や証明書管理が一元化されます。また、インフラ構成も簡素化され、複数のドメインやサブドメインの管理に関する手間を削減できます。
この記事では、Next.jsをフロントエンドとして使用し、API Gatewayをバックエンドとするアーキテクチャで、CloudFrontを活用してフロントエンドとAPIを同じドメインで統合する手法を解説します。
Next.jsのサンプルプロジェクト作成
まずは、Next.jsのプロジェクトを作成します。Next.jsはReactをベースにしたフレームワークで、簡単にWebアプリケーションを作成できます。このセクションでは、サンプルプロジェクトを作成し、開発環境で確認するところまでを解説します。
Next.jsのインストールとプロジェクト作成
-
Node.jsのインストール
Next.jsを動かすには、Node.jsが必要です。Node.jsはサーバーサイドでJavaScriptを実行するための環境で、Next.jsアプリの動作にも使います。
まだインストールしていない場合は、以下の手順でインストールしましょう。- Node.jsの公式サイトにアクセスします。
- 推奨バージョン(LTS)のダウンロードリンクをクリックし、ガイドに従ってインストールします。
(インストール時は、デフォルト設定で問題ありません)
インストールが完了したら、以下のコマンドでNode.jsが正しくインストールされているか確認します。
node -v
このコマンドでバージョンが表示されれば、Node.jsのインストールが成功しています。
-
Next.jsアプリの作成
次に、create-next-app
というコマンドを使って、Next.jsプロジェクトを自動で作成します。これは、プロジェクトのひな形を生成してくれるコマンドです。以下のコマンドをターミナルに入力します。
npx create-next-app@latest my-next-app
このコマンドを実行すると、Next.jsのプロジェクトがmy-next-appという名前のフォルダ内に作成されます(他の名前にしたい場合は、
my-next-app
部分を変更してください)。注意:
npx
はNode.jsと一緒にインストールされるツールで、コマンドを簡単に実行するために使います。特に設定は必要ありません。 -
開発サーバーの起動
プロジェクトが作成できたら、そのディレクトリに移動して、開発サーバーを起動しましょう。cd my-next-app npm run dev
このコマンドを実行すると、Next.jsの開発サーバーが起動し、http://localhost:3000 でアプリケーションを確認できるようになります。ブラウザを開き、このURLにアクセスすると、サンプルページが表示されるはずです。
補足:
npm run dev
は開発中のアプリケーションをすぐに確認できるコマンドです。ファイルを変更すると自動的にリロードされるので、プログラムを書きながらその動作をすぐに確認できます。 -
プロジェクトのカスタマイズ
次に、プロジェクトのカスタマイズです。**pages/index.js
**というファイルが、現在表示されているホームページの内容です。このファイルを編集して、自分の好きなコンテンツに変更してみましょう。例えば、以下のように編集してみます。
export default function Home() { return ( <div> <h1>こんにちは、Next.js!</h1> <p>これはあなたの新しいNext.jsアプリケーションです。</p> </div> ); }
編集を保存すると、ブラウザが自動的にリロードされ、変更が即座に反映されることが確認できます。これでフロントエンド部分を自由にカスタマイズできます。カスタマイズした内容は、後にS3にデプロイし、公開します。
フロントエンドでのユーザー操作の流れ
Next.jsで作成したアプリケーションでは、ユーザーがログインし、API Gatewayを通じてデータベースのユーザー情報を操作します。このセクションでは、Next.jsアプリがどのようにしてAPI Gatewayと連携し、ユーザー情報のCRUD操作を実現するかを説明します。
1. URLに接続してログイン
ユーザーがフロントエンドアプリケーションのURLにアクセスすると、ログインページにリダイレクトされ、ユーザーは認証を行います。認証に成功すると、セッションが開始され、ログイン状態が保持されます。
ログイン処理の流れ
/login
ページにアクセスし、認証情報を入力します。- フロントエンドは、API Gatewayを通じてバックエンドに認証リクエストを送信します。
- 認証が成功すると、トークンが発行され、ユーザーが次のページにリダイレクトされます。
2. ユーザーを指定し、情報を表示
ログイン後、ユーザーはユーザー一覧ページにリダイレクトされます。ここで、すべてのユーザー情報が表示され、特定のユーザーをクリックすると、そのユーザーの詳細情報が表示されます。
情報表示の流れ
/users
ページで、すべてのユーザーが表示されます。- 任意のユーザーを選択すると、
/users/{id}
に遷移し、ユーザーの詳細情報が表示されます。 - このとき、フロントエンドは
GET /api/users/{id}
エンドポイントにリクエストを送り、指定されたユーザー情報を取得します。
3. ユーザー情報の操作(CRUD)
ユーザー情報の作成、更新、削除の操作もフロントエンドで行えます。各操作に対応したAPIエンドポイントにリクエストが送られ、データベースが更新されます。
CRUD操作のフロー
- 新規ユーザー作成:
/api/users
にPOST
リクエストを送信します。 - ユーザー情報の更新:
/api/users/{id}
にPUT
リクエストを送信します。 - ユーザー削除:
/api/users/{id}
にDELETE
リクエストを送信します。
これらの操作に成功すると、フロントエンド上に変更が反映され、ページがリロードされるか、該当ユーザーの情報が更新されます。
CloudFront、S3、API Gatewayの概要
次に、AWSのサービスを使用してフロントエンド(Next.js)とバックエンド(API Gateway)を同じドメインで統合し、CORSの問題を回避する方法を説明します。今回は、既に構築済みのAPIがあり、データベース内のユーザー情報をCRUD操作できるAPIがAPI Gatewayで提供されていることを前提に進めます。このAPIをフロントエンドから操作できるように統合する方法を紹介します。
CloudFront
CloudFrontはAWSのコンテンツ配信ネットワーク(CDN)サービスで、静的コンテンツや動的APIリクエストを世界中に高速に配信することができます。CloudFrontを使うことで、S3の静的ファイル(Next.jsのフロントエンド)とAPI GatewayのバックエンドAPIを同じドメインで統合できます。
CloudFrontのメリット
-
CORSの問題を回避 フロントエンドとAPIを同じドメインでホスティングすることで、異なるドメインでのリクエストに関連するCORSの設定を避けることができます。
-
キャッシュの活用 静的コンテンツのキャッシュを効率的に行い、レスポンス速度を向上させます。
-
パフォーマンスの最適化 グローバルなエッジロケーションからユーザーに最適なパフォーマンスでコンテンツを提供できます。
S3
S3はAWSのオブジェクトストレージサービスで、静的なWebサイトやアプリケーションをホスティングするのに適しています。今回の構成では、Next.jsでビルドした静的ファイル(HTML、CSS、JavaScript)をS3にアップロードし、CloudFrontを通じて世界中に配信します。
S3の役割
-
静的ファイルのホスティング Next.jsでビルドされた静的なアセット(ページ、スタイル、スクリプト)がS3に保存され、ユーザーに配信されます。
-
クラウドストレージの信頼性 AWSのS3は高い耐久性と可用性を持ち、大量のトラフィックにも対応可能です。
API Gateway
API GatewayはAWSのマネージドサービスで、RESTfulなAPIを作成し、HTTPリクエストをバックエンドサービスにルーティングする役割を果たします。今回は、ユーザー情報のCRUD操作が可能なAPIがAPI Gateway上にすでに構築されている前提で進めます。
API Gatewayの役割
-
CRUD操作 既存のAPIは、ユーザーの作成(Create)、読み取り(Read)、更新(Update)、削除(Delete)を行います。例えば以下のようなエンドポイントが用意されていると想定します。
POST /api/users
- 新しいユーザーの作成GET /api/users/{id}
- 特定のユーザー情報を取得PUT /api/users/{id}
- ユーザー情報の更新DELETE /api/users/{id}
- ユーザーの削除
-
CloudFrontとの統合 CloudFrontを経由して、フロントエンドからこれらのAPIエンドポイントにアクセスできるようにします。これにより、フロントエンドとバックエンドが同じドメインで統合され、CORSの問題を回避できます。
CloudFrontとAPI Gatewayを組み合わせることで、静的コンテンツとAPIリクエストを同じドメインで処理し、エンドユーザーが直感的に操作できるインターフェースを提供します。Next.jsで作成されたフロントエンドからは、API Gatewayのエンドポイントに対してユーザー情報のCRUD操作を行います。
S3での静的サイトホスティング
Next.jsでビルドした静的ファイルをS3にホスティングするための手順を説明します。今回は、Next.jsの 静的サイト生成(SG: Static Generation) という機能を使用して、生成された静的ファイルをS3にアップロードし、公開します。
静的サイト生成(SG)とは?
Next.jsでは、アプリケーションをビルドする際に、ページを事前に生成して、静的なHTMLファイルとして出力することが可能です。これを 静的サイト生成(SG: Static Generation) と呼びます。
なぜ静的ファイルなのか?
-
パフォーマンスの向上
静的ファイルは、事前に生成されるため、ユーザーがアクセスしたときにサーバー側でリアルタイムにページを生成する必要がありません。これにより、リクエストに対する応答時間が短縮され、パフォーマンスが向上します。 -
スケーラビリティ
静的ファイルは、特定のサーバーに依存せず、S3のようなストレージに配置することで、世界中のどこからでも高速に配信することができます。大量のアクセスが発生しても、静的ファイルなら容易にスケールできるため、特にトラフィックが多いサイトに適しています。 -
コスト効率
サーバーサイドで動的にページを生成する場合、リソースが必要ですが、静的ファイルの場合、S3に保存して配信するだけで済むため、コストを抑えることができます。
Next.jsのビルド
まず、プロジェクトが完成したら、次に静的ファイルを生成します。Next.jsでは、npm run build
コマンドでアプリケーションをビルドし、npm run export
で静的ファイルを生成します。
npm run build
npm run export
このコマンドを実行すると、out
というディレクトリに静的ファイルが生成されます。out
ディレクトリには、HTMLファイルや関連するアセット(CSSやJavaScript)が保存されます。このファイルは、すでにページごとのコンテンツが埋め込まれた状態で出力されているため、サーバー側で追加の処理を必要としません。
S3バケットの作成と設定
次に、AWSのS3を使用して、この静的ファイルをホスティングします。S3は、オブジェクトストレージサービスとして、多数の静的ファイルを配信するのに最適なプラットフォームです。
-
S3バケットの作成 AWSコンソールで新しいS3バケットを作成し、静的ウェブサイトホスティングを有効にします。これにより、S3バケットにアップロードされたファイルが、ウェブ経由でアクセス可能な状態になります。
-
静的ファイルのアップロード 生成された静的ファイルをS3にアップロードします。以下のコマンドを使用して、
out
ディレクトリの内容をS3にアップロードします。aws s3 sync ./out s3://your-s3-bucket-name
-
パブリックアクセスの設定 バケットポリシーを設定して、静的ウェブサイトホスティング用のファイルに対してパブリックアクセスを許可します。これにより、一般のユーザーがブラウザを通じてアクセスできるようになります。
API Gatewayの設定
次に、API Gatewayを使用してバックエンドAPIを設定します。今回は、データベース内のユーザー情報をCRUD操作できるAPIを前提に、API Gatewayの設定を行い、フロントエンドからユーザー情報を操作するためのエンドポイントを公開します。
API Gatewayとは?
API Gatewayは、AWSが提供するマネージドサービスです。RESTfulなAPIやWebSocket APIを簡単に作成・管理でき、リクエストを受け付けてバックエンドサービスにルーティングする役割を果たします。APIのアクセス制御や認証機能も備わっています。
API GatewayでのAPI作成手順
まず、AWS API Gatewayのコンソールを使用して、新しいAPIを作成します。ここでは、CRUD操作が可能なエンドポイントを例にして、設定の手順を詳しく説明します。
-
新しいAPIの作成 AWSマネジメントコンソールで「API Gateway」に移動し、新しいAPIを作成します。APIタイプはREST APIを選択します。
- API名に「UserCRUDAPI」などのわかりやすい名前を付けます。
- エンドポイントタイプは「Regional」を選択します。これは、APIリクエストを特定のAWSリージョンで処理する設定です。
-
リソースとメソッドの作成 API Gatewayでは、リクエストを処理する「リソース」と「メソッド」を設定します。今回は、
/api/users
エンドポイントを作成し、GET、POST、PUT、DELETEリクエストを受け付けるように設定します。-
リソースの作成 「アクション」から「リソースの作成」を選び、
/users
というリソースパスを入力します。 -
メソッドの作成 GET、POST、PUT、DELETEの各メソッドを作成します。それぞれのメソッドに対して、バックエンドにリクエストをルーティングする設定を行います。
-
エンドポイントの設定
次に、作成したAPIのエンドポイントに対して、リクエストがどのように処理されるかを設定します。バックエンドとしてLambda関数や他のAWSサービス(例えば、DynamoDBなど)と統合することが可能です。
Lambda関数と統合する場合
-
Lambda関数との連携 API Gatewayは、リクエストをLambda関数に転送して処理することができます。これにより、リクエストを受け取り、ユーザー情報のCRUD操作を行うバックエンド処理を実装できます。各メソッド(GET、POST、PUT、DELETE)に対して、適切なLambda関数を割り当てます。
GET /api/users
で、特定のユーザー情報を取得するLambda関数を指定します。POST /api/users
で、新しいユーザーをデータベースに追加するLambda関数を指定します。PUT /api/users/{id}
で、指定したユーザーIDの情報を更新するLambda関数を指定します。DELETE /api/users/{id}
で、指定したユーザーIDの情報を削除するLambda関数を指定します。
-
統合レスポンスの設定 各エンドポイントのレスポンスを設定します。レスポンスのフォーマットはJSON形式で統一し、フロントエンドに返すデータを整えます。例えば、ユーザー情報の取得が成功した場合は、200ステータスコードと共にユーザーのデータを返すように設定します。
DynamoDBと直接統合する場合(オプション)
場合によっては、Lambda関数を使わずにDynamoDBと直接API Gatewayを統合し、データベースにアクセスすることも可能です。この場合、API Gatewayがリクエストを受け取り、DynamoDBに対して直接CRUD操作を行います。
-
DynamoDBテーブルの設定 DynamoDBにユーザーデータを保存するテーブルを作成し、API Gatewayと統合します。
-
リクエストとレスポンスの設定 API Gatewayを使って、ユーザーのCRUD操作(Create、Read、Update、Delete)をDynamoDBテーブルに対して行うための設定を行います。
認証とセキュリティの設定
APIを外部に公開する際は、適切な認証とアクセス制御が必要です。API Gatewayでは、以下の認証方法を使用できます。
- AWS IAM認証を使って、APIへのアクセス制限を行います。
- APIキーの設定を使って、特定のユーザーにのみAPIを使用させることができます。
- Cognitoユーザープールを使い、ユーザー認証を行います。これにより、認証済みのリクエストのみを許可できます。
CloudFrontのセットアップと統合
フロントエンドとAPIを同じドメインでホスティングするために、CloudFrontを使用します。CloudFrontを使えば、S3とAPI Gatewayを1つのドメインで統合し、CORSの問題を回避できます。
CloudFrontディストリビューションの作成
CloudFrontで新しいディストリビューションを作成し、オリジンとしてS3バケットを指定します。これにより、Next.jsの静的ファイルがCloudFrontを通じて配信されます。
API Gatewayのルーティング設定
CloudFrontの設定で、/api/*
のパスに対してAPI Gatewayを別のオリジンとして追加します。これにより、https://your-domain.com/api/*
のリクエストがAPI Gatewayに転送されるようになります。
キャッシュポリシーの設定
静的ファイルとAPIリクエストに対するキャッシュポリシーを適切に設定することで、パフォーマンスの向上が図れます。S3から配信される静的コンテンツはキャッシュされ、APIリクエストはキャッシュしないように設定します。
カスタムドメインの設定
次に、カスタムドメインを設定して、ユーザーがhttps://example.com
のようなわかりやすいURLでフロントエンドとAPIにアクセスできるようにします。
Route 53でドメインを設定
AWS Route 53でカスタムドメインを登録し、CloudFrontディストリビューションと紐付けます。
SSL証明書の取得と設定
AWS Certificate Manager(ACM)を使用して、SSL証明書を取得し、CloudFrontディストリビューションに適用します。これにより、HTTPS経由で安全に通信できます。
デプロイと運用
最後に、Next.jsアプリをビルドし、S3とAPI Gatewayにデプロイします。
Next.jsのビルドとS3へのアップロード
ローカルでNext.jsアプリをビルドし、S3にアップロードします。これにより、S3とCloudFrontを経由して静的ファイルが配信されます。
APIの動作確認
CloudFront経由でAPI Gatewayが正しく動作することを確認します。https://your-domain.com/api/users
のようにアクセスして、APIレスポンスが正常に返されるか確認します。
運用のための最適化
-
キャッシュの最適化
CloudFrontのキャッシュ設定をチューニングして、S3の静的ファイルを効率的に配信します。APIリクエストに対してはキャッシュを無効化し、常に最新のデータを取得できるように設定します。
-
モニタリング
CloudWatchを使用して、APIリクエストやS3のアクセスログをモニタリングします。これにより、トラフィックやパフォーマンスをリアルタイムで把握できます。
まとめ
AWSのCloudFront、S3、API Gatewayを使って、フロントエンドとAPIを同じドメインでホスティングすることで、CORSの問題を回避しつつ、シンプルでスケーラブルなWebアプリケーションのデプロイが可能になります。この方法は、パフォーマンスの向上や運用の効率化にもつながり、特にサーバーレスアーキテクチャとの相性が良いです。AWSの強力なエコシステムを活用して、効率的なWebアプリケーションの開発を進めましょう。
参考リンク
【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。
「フリーランスエンジニア」
近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。
「成功する人とそうでない人の違いは何か?」
私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。
比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。
多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、
エンベーダー編集部
エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。
関連記事
2020.02.25
完全未経験からエンジニアを目指す爆速勉強法
USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
- キャリア・学習法
- エンジニア
2023.08.30
Terraformの組み込み関数とは?elementやlookupなどの基本構文と使用例を学ぶ
こちらの記事では、Terraformの組み込み関数についての基本的な構文と使用例について解説します。
- インフラエンジニア
- AWS
2023.10.19
インフラエンジニアの仕事内容について解説
こちらはEnvaderの記事になります。
- インフラエンジニア
- ネットワーク
- AWS
2024.09.29
JavaScriptのライブラリ、Axiosを理解しよう
この記事では、Axiosの基本的な使い方と便利な機能について解説します。サーバーとのデータのやり取りは、Web開発において必須のスキルですので、ぜひ一緒に学んでいきましょう!
- JavaScript
- フロントエンド