はじめに
このガイドでは、AWS Lambda と API Gateway を使用した翻訳 Web API の構築方法を、AWS マネジメントコンソールでの手動設定と AWS CDK を使用したコードによる設定の両方から解説します。両方のアプローチを比較することで、それぞれの対応関係を理解できます。
AWS CDK (Cloud Development Kit) を使用する最大の利点は、インフラストラクチャをコードとして管理できることです。これにより、設定変更の履歴が Git などのバージョン管理システムで追跡でき、開発環境からステージング環境、本番環境まで一貫した設定を維持できます。また、コードレビューやテストを通じて、インフラの変更を安全に管理することも可能になります。
AWS CDK の準備と初期設定
前提条件
CDK を使用するには、以下のツールが必要です:
- Node.js (バージョン 14.x 以上)
- AWS CLI (設定済み)
- AWS アカウントの認証情報
AWS CDK のインストール
AWS CDK は npm を使用してグローバルにインストールします:
npm install -g aws-cdk
インストールが完了したら、バージョンを確認します:
cdk --version
CDK プロジェクトの初期化
新しいディレクトリを作成し、CDK プロジェクトを初期化します:
# 新しいディレクトリを作成
mkdir translate-api-cdk
cd translate-api-cdk
# JavaScript を使用した CDK プロジェクトを初期化
cdk init app --language javascript
これにより、基本的な CDK プロジェクト構造が作成されます:
translate-api-cdk/
├── bin/ # CDK アプリのエントリーポイント
│ └── translate-api-cdk.js
├── lib/ # CDK スタック定義
│ └── translate-api-cdk-stack.js
├── test/
├── cdk.json # CDK の設定ファイル
├── package.json # プロジェクトの依存関係定義
└── package-lock.json
AWS 環境の準備(ブートストラップ)
CDK を使用するには、AWS 環境を「ブートストラップ」する必要があります。これは CDK がデプロイに使用するリソース(S3 バケットなど)を作成するプロセスです:
cdk bootstrap
この操作は AWS アカウントとリージョンごとに一度だけ実行する必要があります。
AWS コンソールでの対応操作
AWS コンソールには CDK プロジェクトの初期化に直接対応する操作はありません。CDK はローカル開発環境でインフラストラクチャをコードとして定義し、それを AWS CloudFormation を通じてデプロイするツールです。
コンソールでは、CloudFormation スタックとして CDK のデプロイ結果を確認できます:
- AWS マネジメントコンソールにログイン
- CloudFormation サービスに移動
- スタック一覧で「CDKToolkit」というスタックが表示されていれば、ブートストラップは成功しています
Lambda 関数の作成と設定
AWS コンソールでの設定
AWS マネジメントコンソールでは、Lambda 関数を作成するために以下の手順を実行します:
- Lambda コンソールにアクセスし、「関数の作成」ボタンをクリック
- 「一から作成」を選択
- 関数名に「TranslateFunction」を入力
- ランタイムとして「Node.js 18.x」を選択
- 実行ロールとして「基本的な Lambda アクセス権限で新しいロールを作成」を選択
- 「関数の作成」ボタンをクリック
作成後、Lambda 関数の設定画面で以下の項目を設定します:
- 「設定」タブから「一般設定」を選択し、メモリを 256MB に、タイムアウトを 10 秒に変更
- 「アクセス権限」タブで実行ロールを選択し、「ポリシーをアタッチ」から「TranslateFullAccess」ポリシーを追加
CDK での設定
CDK プロジェクトでは、必要なモジュールをインストールします:
npm install aws-cdk-lib constructs
次に、lib/translate-api-cdk-stack.js
ファイルを編集して Lambda 関数を定義します:
const { Stack, Duration } = require('aws-cdk-lib');
const lambda = require('aws-cdk-lib/aws-lambda');
const iam = require('aws-cdk-lib/aws-iam');
const path = require('path');
class TranslateApiCdkStack extends Stack {
constructor(scope, id, props) {
super(scope, id, props);
// Lambda 関数の IAM ロールを作成
const lambdaRole = new iam.Role(this, 'TranslateLambdaRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
iam.ManagedPolicy.fromAwsManagedPolicyName('TranslateFullAccess')
]
});
// Lambda 関数を作成
const translateFunction = new lambda.Function(this, 'TranslateFunction', {
runtime: lambda.Runtime.NODEJS_18_X,
handler: 'translate.handler',
code: lambda.Code.fromAsset(path.join(__dirname, '../lambda')),
memorySize: 256,
timeout: Duration.seconds(10),
role: lambdaRole
});
}
}
module.exports = { TranslateApiCdkStack }
対応関係の解説
コンソールと CDK の対応関係を見ていきましょう:
- 関数名:
- コンソール: 直接「TranslateFunction」と入力
- CDK:
'TranslateFunction'
という論理 ID を指定 - 実際の AWS リソース名: `TranslateApiCdkStack-TranslateFunction-A1B2C3D4E5F6`` のように、CDK スタック名とランダムな識別子が付加される
例えば、CDK で 'TranslateFunction'
という ID を指定した場合、AWS コンソールでは TranslateApiCdkStack-TranslateFunction-A1B2C3D4E5F6
のような名前で表示されます。これは CDK が一意のリソース名を生成するためです。
- ランタイム: コンソールでは「Node.js 18.x」を選択、CDK では
lambda.Runtime.NODEJS_18_X
を指定 - 実行ロール: コンソールでは自動作成後に権限を追加、CDK では iam.Role を作成して
managedPolicies
に権限を指定 - メモリ: コンソールでは設定画面で 256MB を選択、CDK では
memorySize: 256
を指定 - タイムアウト: コンソールでは設定画面で 10 秒を選択、CDK では
timeout: Duration.seconds(10)
を指定 - コード: コンソールではエディタで直接入力またはアップロード、CDK では code:
lambda.Code.fromAsset()
でローカルディレクトリを指定
Lambda 関数のコードと依存関係管理
Lambda 関数のコードは、実際に実行される処理を定義する部分です。今回は日本語テキストを英語に翻訳する機能を実装しています。
AWS コンソールでの設定
AWS コンソールでは、Lambda 関数のコードエディタに直接コードを入力するか、ZIP ファイルとしてアップロードします。コードエディタで以下のようなコードを入力します:
const AWS = require('aws-sdk');
const translate = new AWS.Translate();
exports.handler = async (event) => {
console.log('イベント:', JSON.stringify(event));
try {
// クエリパラメータから入力テキストを取得
const inputText = event.queryStringParameters?.inputText || 'こんにちは';
const params = {
Text: inputText,
SourceLanguageCode: 'ja',
TargetLanguageCode: 'en'
};
// Amazon Translate を呼び出し
const response = await translate.translateText(params).promise();
const outputText = response.TranslatedText;
return {
statusCode: 200,
body: outputText,
headers: {
'Content-Type': 'text/plain'
},
isBase64Encoded: false
};
} catch (error) {
console.error('エラー:', error);
return {
statusCode: 500,
body: JSON.stringify({ error: error.message }),
headers: {
'Content-Type': 'application/json'
},
isBase64Encoded: false
};
}
};
Node.js 18.x ランタイムでは AWS SDK v2 が組み込まれていないため、依存関係を含めるには「レイヤー」を追加するか、依存関係を含めたデプロイパッケージをアップロードする必要があります。
CDK での設定とディレクトリ構成
CDK プロジェクトでは、以下のようなディレクトリ構成を作成します:
translate-api-cdk/
├── bin/ # CDK アプリのエントリーポイント
│ └── translate-api-cdk.js
├── lib/ # CDK スタック定義
│ └── translate-api-cdk-stack.js
├── lambda/ # Lambda 関数のコードと依存関係
│ ├── translate.js # 関数のメインコード
│ ├── package.json # 関数の依存関係定義
│ └── node_modules/ # 関数の依存関係(自動生成)
├── node_modules/ # CDK プロジェクトの依存関係(自動生成)
├── cdk.json # CDK の設定ファイル
├── package.json # CDK プロジェクトの依存関係定義
└── package-lock.json # 依存関係のバージョンロック(自動生成)
この構造では、CDK プロジェクト自体の依存関係と Lambda 関数の依存関係が明確に分離されています。これは AWS Lambda のデプロイモデルに合わせた標準的なアプローチです。
Lambda 関数のコードと依存関係を設定するには、以下の手順を実行します:
# lambda ディレクトリを作成
mkdir lambda
cd lambda
# package.json を初期化
npm init -y
# AWS SDK v3 の Translate クライアントをインストール
npm install @aws-sdk/client-translate
そして、lambda/translate.js
ファイルを作成し、以下のコードを記述します:
const { Translate } = require('@aws-sdk/client-translate');
const translate = new Translate({ region: process.env.AWS_REGION });
exports.handler = async (event) => {
console.log('イベント:', JSON.stringify(event));
try {
// クエリパラメータから入力テキストを取得
const inputText = event.queryStringParameters?.inputText || 'こんにちは';
const params = {
Text: inputText,
SourceLanguageCode: 'ja',
TargetLanguageCode: 'en'
};
// Amazon Translate を呼び出し
const response = await translate.translateText(params);
const outputText = response.TranslatedText;
return {
statusCode: 200,
body: outputText,
headers: {
'Content-Type': 'text/plain'
},
isBase64Encoded: false
};
} catch (error) {
console.error('エラー:', error);
return {
statusCode: 500,
body: JSON.stringify({ error: error.message }),
headers: {
'Content-Type': 'application/json'
},
isBase64Encoded: false
};
}
};
CDK スタックでは、このコードを含むディレクトリを Lambda 関数のコードとして指定します:
code: lambda.Code.fromAsset(path.join(__dirname, '../lambda'))
Lambda 関数のテスト
CDK でデプロイする前に、Lambda 関数が正しく動作するかを確認することができます。これには、以下の方法があります:
-
CDK を使用して Lambda 関数のみをデプロイ
// lib/translate-api-cdk-stack.js の一部だけを実装 const lambdaRole = new iam.Role(this, 'TranslateLambdaRole', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'), iam.ManagedPolicy.fromAwsManagedPolicyName('TranslateFullAccess') ] }); const translateFunction = new lambda.Function(this, 'TranslateFunction', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'translate.handler', code: lambda.Code.fromAsset(path.join(__dirname, '../lambda')), memorySize: 256, timeout: Duration.seconds(10), role: lambdaRole });
そして、npx cdk deploy を実行して Lambda 関数をデプロイします。デプロイ後、AWS コンソールから Lambda 関数をテストできます。
-
AWS SAM CLI を使用してローカルでテスト
AWS SAM CLI をインストールしている場合、ローカル環境で Lambda 関数をテストできます。まず、簡単な SAM テンプレートを作成します:# template.yaml AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: TranslateFunction: Type: AWS::Serverless::Function Properties: CodeUri: ./lambda Handler: translate.handler Runtime: nodejs18.x Timeout: 10 MemorySize: 256 Environment: Variables: AWS_REGION: ap-northeast-1
そして、以下のコマンドでローカルテストを実行します:
# テストイベントを作成 echo '{"queryStringParameters": {"inputText": "こんにちは"}}' > event.json # ローカルで Lambda 関数を実行 sam local invoke TranslateFunction -e event.json
ただし、この方法では AWS の認証情報が必要で、実際に AWS Translate サービスを呼び出します。
-
モックを使用したユニットテスト:
AWS SDK をモック化して、ユニットテストを作成することもできます。これには Jest などのテストフレームワークを使用します:# lambda ディレクトリで実行 npm install --save-dev jest
そして、translate.test.js ファイルを作成します:
// translate.test.js const { handler } = require('./translate'); // AWS SDK をモック化 jest.mock('@aws-sdk/client-translate', () => { return { Translate: jest.fn().mockImplementation(() => { return { translateText: jest.fn().mockResolvedValue({ TranslatedText: 'Hello' }) }; }) }; }); test('translates text correctly', async () => { const event = { queryStringParameters: { inputText: 'こんにちは' } }; const response = await handler(event); expect(response.statusCode).toBe(200); expect(response.body).toBe('Hello'); });
package.json にテストスクリプトを追加します:
"scripts": { "test": "jest" }
そして、テストを実行します:
npm test
これらのテスト方法を使用することで、API Gateway との統合前に Lambda 関数が正しく動作することを確認できます。特にモックを使用したユニットテストは、実際の AWS サービスを呼び出さずに関数のロジックをテストできるため、CI/CD パイプラインでの自動テストに適しています。
対応関係の解説
Lambda 関数のコード管理における AWS コンソールと CDK の主な違いは以下の通りです:
-
コードの管理場所
- コンソール: AWS コンソール上のエディタで直接編集するか、ZIP ファイルをアップロード
- CDK: ローカルファイルシステム上でコードを管理し、CDK デプロイ時に自動的にアップロード
-
依存関係の管理
- コンソール: 依存関係を含む ZIP ファイルをアップロードするか、Lambda レイヤーを使用
- CDK: node_modules ディレクトリを含むローカルディレクトリ全体をデプロイパッケージとして使用
-
AWS SDK のバージョン
- コンソール: 古いランタイム(Node.js 14.x 以前)では AWS SDK v2 が組み込まれている
- CDK: 明示的に依存関係をインストールし、AWS SDK v3 の最新機能を活用可能
CDK を使用することで、コードと依存関係をローカル環境で管理し、バージョン管理システムで追跡できるため、チーム開発や継続的インテグレーション/継続的デプロイ(CI/CD)パイプラインとの統合が容易になります。
API Gateway の作成と設定
API Gateway は、クライアントからのリクエストを受け付け、Lambda 関数に転送するためのエンドポイントを提供します。ここでは、API Gateway の作成と設定方法を AWS コンソールと CDK の両方で説明します。
AWS コンソールでの設定
AWS マネジメントコンソールで API Gateway を作成する手順は以下の通りです:
- API Gateway コンソールにアクセスし、「API を作成」ボタンをクリック
- 「REST API」を選択し、「構築」ボタンをクリック
- 「新しい API を作成」を選択
- API 名に「TranslateAPI」を入力
- エンドポイントタイプは「リージョン」を選択
- 「API の作成」ボタンをクリック
API が作成されたら、リソースとメソッドを追加します:
- 「リソース」タブで、ルートリソース「/」を選択
- 「アクション」ボタンをクリックし、「リソースの作成」を選択
- リソース名に「translate」を入力
- 「リソースの作成」ボタンをクリック
- 作成した「/translate」リソースを選択
- 「アクション」ボタンをクリックし、「メソッドの作成」を選択
- ドロップダウンから「GET」を選択し、チェックマークをクリック
- 統合タイプとして「Lambda 関数」を選択
- 「Lambda プロキシ統合の使用」にチェックを入れる
- Lambda 関数に「TranslateFunction」を入力
- 「保存」ボタンをクリック
- Lambda 関数に権限を追加することを確認するポップアップが表示されたら「OK」をクリック
次に、クエリパラメータの設定を行います:
- 「メソッドリクエスト」をクリック
- 「URL クエリ文字列パラメータ」を展開
- 「クエリ文字列の追加」をクリック
- 名前に「inputText」と入力
- 「必須」にチェックを入れる
- チェックマークをクリックして保存
最後に、API をデプロイします:
- 「アクション」ボタンをクリックし、「API のデプロイ」を選択
- 「デプロイのステージ」で「[新しいステージ]」を選択
- ステージ名に「dev」と入力
- 「デプロイ」ボタンをクリック
デプロイが完了すると、ステージエディタが表示され、API のエンドポイント URL が表示されます。この URL に「?inputText=こんにちは」を追加してブラウザでアクセスすると、翻訳結果が表示されます。
CDK での設定
CDK では、API Gateway の設定を以下のようにコードで表現します。まず、必要なモジュールをインストールします:
npm install aws-cdk-lib/aws-apigateway
次に、lib/translate-api-cdk-stack.js
ファイルに API Gateway の定義を追加します:
const { Stack, Duration, CfnOutput } = require('aws-cdk-lib');
const lambda = require('aws-cdk-lib/aws-lambda');
const apigateway = require('aws-cdk-lib/aws-apigateway');
const iam = require('aws-cdk-lib/aws-iam');
const path = require('path');
class TranslateApiCdkStack extends Stack {
constructor(scope, id, props) {
super(scope, id, props);
// Lambda 関数の IAM ロールを作成
const lambdaRole = new iam.Role(this, 'TranslateLambdaRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
iam.ManagedPolicy.fromAwsManagedPolicyName('TranslateFullAccess')
]
});
// Lambda 関数を作成
const translateFunction = new lambda.Function(this, 'TranslateFunction', {
runtime: lambda.Runtime.NODEJS_18_X,
handler: 'translate.handler',
code: lambda.Code.fromAsset(path.join(__dirname, '../lambda')),
memorySize: 256,
timeout: Duration.seconds(10),
role: lambdaRole
});
// API Gateway を作成
const api = new apigateway.RestApi(this, 'TranslateApi', {
restApiName: 'Translate API',
description: 'API for translating text from Japanese to English'
});
// /translate リソースを作成
const translateResource = api.root.addResource('translate');
// GET メソッドを追加し、Lambda 関数と統合
translateResource.addMethod('GET', new apigateway.LambdaIntegration(translateFunction, {
proxy: true
}), {
requestParameters: {
'method.request.querystring.inputText': true
}
});
// API Gateway のエンドポイント URL を出力
const apiUrl = `${api.url}translate?inputText=${encodeURIComponent('こんにちは')}`;
// CDK 出力に API URL を追加
new CfnOutput(this, 'TranslateApiUrl', {
value: apiUrl,
description: 'URL for the Translate API (example with "こんにちは")'
});
}
}
module.exports = { TranslateApiCdkStack }
このコードを保存した後、CDK アプリをデプロイします:
npx cdk deploy
デプロイが完了すると、コンソールに API Gateway のエンドポイント URL が表示されます。この URL にアクセスして API をテストできます。
対応関係の解説
API Gateway の設定における AWS コンソールと CDK の対応関係は以下の通りです:
-
API の作成
- コンソール: 「API を作成」ボタンをクリックし、名前とエンドポイントタイプを設定
- CDK:
new apigateway.RestApi()
コンストラクタで API を作成し、restApiName
とdescription
を設定
-
リソースの作成
- コンソール: 「リソースの作成」を選択し、リソース名を入力
- CDK:
api.root.addResource('translate')
でリソースを作成
-
メソッドの作成
- コンソール: 「メソッドの作成」を選択し、HTTP メソッドと統合タイプを設定
- CDK:
translateResource.addMethod('GET', new apigateway.LambdaIntegration())
でメソッドを作成
-
Lambda プロキシ統合
- コンソール: 「Lambda プロキシ統合の使用」にチェックを入れる
- CDK:
new apigateway.LambdaIntegration(translateFunction, { proxy: true })
で設定
-
クエリパラメータの設定
- コンソール: 「メソッドリクエスト」から「URL クエリ文字列パラメータ」を設定
- CDK:
requestParameters: { 'method.request.querystring.inputText': true }
で設定
-
API のデプロイ
- コンソール: 「API のデプロイ」を選択し、ステージを設定
- CDK: CDK アプリのデプロイ時に自動的に API がデプロイされる
-
エンドポイント URL の取得
- コンソール: ステージエディタで URL を確認
- CDK:
api.url
プロパティで URL を取得し、CfnOutput
で出力
CDK を使用すると、API Gateway の設定をコードとして管理できるため、設定の再現性が高まり、環境間の一貫性を保つことができます。また、リソースやメソッドの追加・変更・削除も簡単に行えます。
API のテストと動作確認
API がデプロイされたら、実際に動作するかテストしましょう。
ブラウザでのテスト
最も簡単なテスト方法は、ブラウザで API のエンドポイント URL にアクセスすることです:
https://xxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/translate?inputText=こんにちは
正しく設定されていれば、ブラウザに「Hello」と表示されるはずです。
curl を使用したテスト
コマンドラインから API をテストする場合は、curl コマンドを使用できます:
curl "https://xxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/translate?inputText=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF"
注意: URL 内の日本語は URL エンコードする必要があります。
Postman を使用したテスト
より高度なテストには、Postman などの API テストツールを使用できます:
- Postman を起動
- 新しいリクエストを作成
- HTTP メソッドを「GET」に設定
- URL に API のエンドポイント URL を入力
- 「Params」タブで「inputText」キーに「こんにちは」値を設定
- 「Send」ボタンをクリック
レスポンスとして「Hello」が返ってくれば、API は正しく機能しています。
CloudWatch Logs の確認
API の動作に問題がある場合は、CloudWatch Logs で Lambda 関数のログを確認できます:
- AWS マネジメントコンソールで CloudWatch サービスに移動
- 左側のナビゲーションペインで「ログ」→「ロググループ」を選択
- /aws/lambda/TranslateApiCdkStack-TranslateFunction-XXXX という名前のロググループを探す
- 最新のログストリームをクリックしてログを確認
ログには、Lambda 関数の実行状況やエラーメッセージが記録されています。
まとめ
このガイドでは、AWS Lambda と API Gateway を使用した翻訳 Web API の構築方法を、AWS マネジメントコンソールでの手動設定と AWS CDK を使用したコードによる設定の両方から解説しました。