1. はじめに
AWS Summitに向けて、スマホをかざすだけで自分のポートフォリオが開く「NFC搭載のデジタル名刺」を作成しました。
普段AWSやJavaをメインに学習していることから、「せっかくなら裏側で動的な処理を持たせたWebアプリケーションにしたい!」と考えました。
とはいえ、個人開発のポートフォリオでEC2などのサーバーを常時稼働させると、お財布へのダメージが無視できません。
そこで今回は、コストを抑えつつ要件を満たすために、「S3 + CloudFront + API Gateway + Lambda」の構成で、サーバーレスな動的サイトを組み込んでデジタル名刺を内製化しました。
静的サイトの構築手順についてはumitsuさんの記事を参考にさせていただきました。
手順がわかりやすくスムーズに構築することができました。(ありがとうございます!)
本記事では、Java×サーバーレス環境の構築手順をはじめ、「裏側で何がおこっているのか?」や、構築を進めるうえでハマったポイントについて解説します。
2. 全体像と各サービスの役割
構築に入る前に、今回利用するリソースたちの役割分担を整理します。
- Amazon S3 : 名刺の「見た目(HTML/CSS/JSなど)」を置いておく場所
- AWS Lambda + API Gateway :リクエストが来た時だけ瞬時に立ち上がり、処理を行う
- Amazon CloudFront: 世界中に配置され、ユーザーのアクセス先に応じて、S3(見た目)とLambda(頭脳)へ正しく案内を振り分ける
これらがどのような順番で連携していくのか、ステップごとに見ていきましょう。
※ドメインの取得についてはこちらの記事で詳しく解説しています。
3. 構築のステップ
Step 1: バックエンドの配備(Lambda + API Gateway)
JavaプログラムをAWS上にデプロイし、外部からアクセスできるAPIの入り口を作成します。
なお、今回はビルドツールにMavenを採用しました。
① ランタイム選定とライブラリの追加
Javaランタイムの選定およびビルド定義(pom.xml)に追加する必須ライブラリについては、以下の公式ドキュメントを参考にしました。
② pom.xml へのパッケージング設定(Fat JAR化)
Javaコードを書くだけでなく、依存ライブラリをすべて1つのJARファイルに梱包(Fat JAR化)するための maven-shade-plugin が必要です。
既存の <dependencies> とは別に、<build> セクションへ追加しておきます。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
なぜパッケージング設定が必要?
Javaのデフォルトビルドでは自分のコードしかJARに入りません。
そのため、Lambda環境にデプロイした際に「ライブラリが見つからない(ClassNotFoundException)」というエラーを吐いて落ちてしまうのを防ぐためです。
③ Lambda関数の作成とデプロイ
「ランタイム選定とライブラリの追加」に添付したAWS公式サイトの「Java 関数を作成するには」を参考に、Lambda関数を作成し、上記でビルドした Fat JAR をアップロードします。
④ API Gatewayとの接続
Lambdaを外部からWeb経由で呼び出せるように、API Gatewayをトリガーとして設定します。
以下のように設定することで、「このURLにGETリクエストが来たら、Lambdaを呼び出す」というシンプルなルーティングが完成します。
ポイント
今回は、インフラコストを最小限に抑えつつ、デフォルトの自動デプロイ機能によってステージ管理を最もシンプルに完結できるため、REST APIではなく HTTP API を選定しました。
Step 2: フロントエンドの配備(Amazon S3)
次に、ユーザーの目に触れる画面(ポートフォリオサイト)を準備します。
① S3バケットの作成とファイルのアップロード
S3バケットを作成し、HTMLやCSS、画像ファイルなどを格納します。
今回はAIエージェントと協力して自作してみました。
② OAC(Origin Access Control)によるアクセス制限
S3バケット自体は「非公開(パブリックアクセスブロック)」のままにしておきます。
OACとは?
S3への直接アクセスを禁止し、後述するCloudFrontを通ってきたアクセスだけを特別に許可するための機能。
Step 3: 身分証の準備(ACM + Route 53)
作成したフロントエンドとバックエンドを、自分だけの「独自ドメイン」で安全に配信するための準備をします。
① 証明書のリクエスト (ACM)
AWS Certificate Managerで、取得したドメインに対するパブリック証明書をリクエストします。
※CloudFrontに紐付けるため、必ず「バージニア北部 (us-east-1)」で作成します
② DNS検証 (Route 53)
「このドメインは間違いなく私のものです」と証明するために、Route 53に指定されたCNAMEレコードを追加して審査をパスします。
Step 4: 配信とルーティングの統合(CloudFront + Route 53)
バラバラに作ったフロント(S3)とバックエンド(Lambda)を「1つの受付係(CloudFront)」の裏側に統合し、独自ドメインで世界中へ配信します。
① CloudFrontディストリビューションの作成
- オリジンの追加: S3とAPI Gatewayの2つをオリジン(裏側の案内先)として登録
-
【重要】OACの有効化: S3オリジンを追加する際、画面に表示される
Grant CloudFront access to origin(オリジンへのアクセスを許可する)を【Yes】に設定
→これにより、S3を非公開にしたままCloudFrontと安全に繋ぐOACの設定が自動的に組み込まれます。 - 証明書の紐付け: Step 3で作成したACM証明書をセットし、独自ドメインでのHTTPS通信を有効化
② ビヘイビア(Behavior)の経路設定
CloudFrontの設定画面で、以下のようにルーティングルールを最初から定義します。
-
デフォルト (*)のアクセス ➔ S3へ転送(画面を表示) -
/api/*のアクセス ➔ API Gatewayへ転送(Javaの動的処理を呼び出す)
③ Aレコードの開通 (Route 53)
最後にRoute 53に戻り、「自分のドメインにアクセスが来たら、CloudFrontへ案内する」というエイリアスレコードを作成します。
この構成の最大のメリット:CORSの壁を先回り撃破
画面とAPIをCloudFrontの下で「1つの同じ独自ドメイン」に統合したことで、「ドメインが異なるせいでブラウザに通信をブロックされるエラー(CORS問題)」をインフラ側で最初から発生させない設計になっています。
4.NFCカードへの書き込み
AWS上のインフラが完成したら、最後に物理カード(NFCタグ)へURLを書き込みます。
NFCカードはこちらを購入しました。
スマホアプリの「NFC Tools」を使用し、手順はこちらを参考にしました。
カードを「Lock(読み取り専用)」にする
NFCアプリには、悪意のある第三者によるデータの「上書き」を防ぐための「Lock」機能が備わっています。
デジタル名刺を安心して持ち歩くためにも、最終的にはこのLockをかけておくと安全性を高めることができます。
しかし、一度Lockをかけると、NFCタグの物理的な仕様として二度と上書きができなくなります。
そのため、書き込み直後はあえてLockせず、「手持ちのスマホだけでなく、家族や友人のスマホなど複数台で完全な動作確認を行う➔ 100%問題ないと確信してから最後にLockをかける」という2ステップを踏むと良いと思います。
5. おわりに
「S3 + CloudFront + API Gateway + Lambda」の構成でサーバーレスな動的サイトを作成し、デジタル名刺を内製化することができました。
「なぜその設定が必要なのか」というインフラの全体像さえ頭に入っていれば、半日ほどで、全世界に高速配信されるセキュアな動的インフラから手元の物理カードへの実装までが完結します。
この記事が、少しリッチなポートフォリオサイトやデジタル名刺を作りたいエンジニアの参考になれば幸いです。




