はじめに

この記事は、「AWSに興味はあるけどよく知らない」「資格を持っているけど実際に触ってみたことがない」「何か始めてみたい」という方向けの連載シリーズ⑤です。(④はこちら
「30分で学習できる」をテーマに毎週金曜日に更新します。ぜひ私と一緒に取り組んでみてください!私自身も初めての挑戦となりますので、間違いや補足がありましたら教えていただけると嬉しいです。
※このブログでの作業は全て macOSで行なっています。

サーバレスサービスバックエンド

前回のブログで「ユーザーを管理する」の作成が完了しました。今回から「サーバレスサービスバックエンド」に取り組みます。使用するガイドはこちらです。(モジュール3:サーバレスサービスバックエンド

AWS Lambda と Amazon DynamoDBを使用して、ウェブアプリケーションのリクエストを処理するためのバックエンドプロセスを構築します。これにより、ユーザーはユニコーンを自分の好きな場所に送信するように要求できます。

 

Amazon DynamoDBテーブルを作成する

  1. Amazon DynamoDBコンソールを開き、「テーブル」>「テーブルの作成」を選択します。
    2.「テーブル名」に「Rides」、 「パーティションキー」に「RideId」と入力し、キータイプとして 「文字列」を選択します。大文字と小文字が区別されるので注意しましょう。
    3.「テーブル設定」 で、「デフォルト設定」が選択されていることを確認し、一番下にある「テーブルの作成」を選択します。

4.テーブルの作成が完了するまで待ちます。完了すると、ステータスは 「アクティブ」になります。
5.先ほど作成した「Rides」テーブルを選択します。
6.「設定」タブの 「一般的な情報」の欄にある、「Amazon リソースネーム (ARN)」を選択してコピーし、メモしておきます。
以上で完了です。

 

Lambda関数のIAMロールを作成する

全てのLambdaは、関連づけられたIAMロールを持っています。このIAMロールは、Lambda関数が他のどのAWSサービスとやり取りできるかを定義するものです。今回は、ログをAmazon CloudWatch Logs に書き込むアクセス許可と、項目を DynamoDB テーブルに書き込むアクセス許可を Lambda 関数に付与する IAM ロールを作成する必要があります。

1.IAMを開き、左側のタブから「ロール」>「ロールの作成」を選択します。
2.「信頼されたエンティティタイプで「AWS サービス」を選択。「ユースケース」で 「Lambda」を選択します。
3.次へ」 を選択して進みます。

4.「許可ポリシー」の検索窓に「AWSLambdaBasicExecutionRole」と入力し、一番上に出てきたものにチェックを入れます。下にスクロールして「次へ」で進みます。

5.「ロール名」に「WildRydesLambda」と入力します。他のパラメータはデフォルト設定のままにします。
6.「ロールの作成」を選択します。
7.先ほど作成した「WildRydesLambda」を検索窓に入力し、開きます。
8.「許可」タブの「許可ポリシー」欄右側にある、「許可を追加」>「インラインポリシーを作成」を選択します。

9.「サービスの選択」で検索バーに「DynamoDB」と入力し、DynamoDBを選択します。
10.「アクション許可」の検索窓に 「PutItem」と入力し、表示されたらチェックボックスをオンにします。
11.「リソース」 で、「特定」が選択されていることを確認し、「ARN を追加」を選択します。

12.「テキスト」を選択し、DynamoDBを作成した際にメモしたARNを貼り付けて「次へ」を押します。
13.ポリシー名に「DynamoDBWriteAccess」と入力し、「ポリシーの作成」を選択します。

以上で完了です。

 

リクエスト処理のためにLambda関数を作成する

AWS Lambdaは、アクションやリクエストなどに応じてコードを実行します。ここでは、アプリから注文ボタンが押されたとき、「ユニコーンを手配する」というコードを動かす一番大事なプログラムを作ります。この後の手順で「API Gateway」という入り口を作り、ブラウザからこのプログラムを呼び出せるように繋ぎ合わせることで、アプリの裏側の仕組みが完成します。

1.AWS Lambdaコンソールで、「関数の作成」をクリックします。下記の設定にします。

オプション:一から作成
関数名:「RequestUnicorn」
ランタイム:「Node.js 24.x」 を選択します(2026年4月時点 最新のNode.jsを選択してください。)
※「新しいバージョンの Node.js はこのチュートリアルでは動作しません」とガイドありますが、資料が古いため気にしなくて大丈夫です。
永続実行:なし
アーキテクチャ:x86_64
デフォルト実行ロールの変更:別のロールを使用 検索窓に「WildRydesLambda」と入力して選択

2.「関数を作成」を押し、作成します。
3.コードソースと書いたウィンドウが開かれます。「index.mjs」の中身を全て削除して、下記に置き換えます。Node.jsのバージョンの関係で、公式チュートリアルに記載のコードでは動きませんので必ずこちらからコピーお願いします

import { randomBytes } from 'crypto';
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";

// リージョンは自動取得するように設定
const client = new DynamoDBClient({});
const ddb = DynamoDBDocumentClient.from(client);

const fleet = [
{ Name: 'Angel', Color: 'White', Gender: 'Female' },
{ Name: 'Gil', Color: 'White', Gender: 'Male' },
{ Name: 'Rocinante', Color: 'Yellow', Gender: 'Female' },
];

export const handler = async (event, context) => {
if (!event.requestContext.authorizer) {
return errorResponse('Authorization not configured', context.awsRequestId);
}

const rideId = toUrlString(randomBytes(16));
const username = event.requestContext.authorizer.claims['cognito:username'];
const requestBody = JSON.parse(event.body);
const pickupLocation = requestBody.PickupLocation;
const unicorn = findUnicorn(pickupLocation);

try {
// ここでDynamoDBに保存します
await ddb.send(new PutCommand({
TableName: 'Rides',
Item: {
RideId: rideId, // ← ここがテーブルの「パーティションキー」と一致している必要があります
User: username,
Unicorn: unicorn,
UnicornName: unicorn.Name,
RequestTime: new Date().toISOString(),
},
}));

return {
statusCode: 201,
body: JSON.stringify({
RideId: rideId,
Unicorn: unicorn,
Eta: '30 seconds',
Rider: username,
}),
headers: {
'Access-Control-Allow-Origin': '*',
},
};
} catch (err) {
console.error(err);
return errorResponse(err.message, context.awsRequestId);
}
};

function findUnicorn(pickupLocation) {
return fleet[Math.floor(Math.random() * fleet.length)];
}

function toUrlString(buffer) {
return buffer.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}

function errorResponse(errorMessage, awsRequestId) {
return {
statusCode: 500,
body: JSON.stringify({
Error: errorMessage,
Reference: awsRequestId,
}),
headers: {
'Access-Control-Allow-Origin': '*',
},
};
}
 

4.コードを全て貼り付けたら、「Deploy」を押します。
以上で完了です。

実装をテストする

1.先ほどのLambda関数の画面から「テスト」タブを開き、下記設定をします。
イベントアクションをテスト:保存されたイベントを編集
呼び出しタイプ:同期
イベント名:「TestRequestEvent」

2.イベントJSONに下記コードを貼り付けます。こちらは公式チュートリアルと同じものです。

{
    "path": "/ride",
    "httpMethod": "POST",
    "headers": {
        "Accept": "*/*",
        "Authorization": "eyJraWQiOiJLTzRVMWZs",
        "content-type": "application/json; charset=UTF-8"
    },
    "queryStringParameters": null,
    "pathParameters": null,
    "requestContext": {
        "authorizer": {
            "claims": {
                "cognito:username": "the_username"
            }
        }
    },
    "body": "{\"PickupLocation\":{\"Latitude\":47.6174755835663,\"Longitude\":-122.28837066650185}}"
}

3.右上の「保存」を押します。
4.右上の「テスト」を押してテストを開始します。
5.テストが成功すると、「実行中の関数:成功」と緑色の画面が表示されます。詳細の内容が画像のようになっていれば成功です。

実行に失敗した場合

失敗した場合は、Lambda関数やテストイベントのコードが間違っている、Lambdaの実行ロールの設定が間違っているなどの可能性があります。エラーメッセージをコピーして検索することで、原因がわかることが多いです。

 

成功したものの、詳細の中身が違う場合

詳細の中身が下記のようになってしまっている場合

"statusCode": 500,
"body": "{\"Error\":\"One or more parameter values were invalid: Missing the key Rideld in the item\",\"Reference\":\"2941eb53-38a0-4316-9b46-f54595232513\"}"

DynamoDBのパーティションキーが間違っています。DynamoDBの画面に戻り、「I(アイ)」と「l(エル)」の間違いや、抜けている文字がないか確認してみてください。間違いを発見したら、DynamoDBを作り直しましょう。

成功ログを表示させることができたでしょうか。これで「モジュール 3: サーバレスサービスバックエンド」の全項目が完了しました。お疲れ様でした!
次回は「モジュール 4: RESTful API をデプロイする」を進めていきます。いよいよ完成です。次回4/24(金)の更新をお楽しみに!