Lamda→DynamoDBへ接続した際のエラー解決方法

今回は、同じリージョンにあるLamdaからDynamoDBへ接続し、データを挿入できたらゴールとなります。

その中で、LamdaからDynamoDBへの接続に手間取ったので解決方法を記載します。

- [開発環境](#開発環境)
- [使用していたコード](#使用していたコード)
- 発生したエラー
    - [require→importへの変更](#require→importへの変更)
    - [aws-sdkの使用](#aws-sdkの使用)
    - [exportsの変更](#exportsの変更)
- [Lamda関数のIAMロールにDynamoDBへの適切なアクセス権限がアタッチされているか](#Lamda関数のIAMロールにDynamoDBへの適切なアクセス権限がアタッチされているか)


# 開発環境

- Lamda
    - ランタイム：Node.js 18
- DynamoDB

# 使用していたコード

```jsx
let doc = require('dynamodb-doc');
let dynamo = new doc.DynamoDB();
exports.handler = function(event, context) {
  // TODOL: テーブル名を確認してください
  let tableName = "test";
  let item = {
    ID: event.ID,
    Message: event.message,
  };
  let params = {
    TableName: tableName,
    Item: item
  };
  dynamo.putItem(params, context.done);
};
```

こちらの記事を参考にしていました。↓↓↓

https://qiita.com/stpete_ishii/items/7d5d7f1a6f82cc2c3b58

今回は、ランタイムにNode.js 18を使用しているため、上記処理だといくつかエラーになる箇所があります。

# 発生したエラー

## require→importへの変更


```require is not defined in ES module scope, you can use import instead```


- .mjsでは、ESモジュール導入されているため、require関数が使用できない
- requireをimportへ変更する

## aws-sdkの使用

- `dynamodb-doc`パッケージは古い方法であり、DynamoDBへアクセスするためには`aws-sdk`を使用するのが推奨されている。そのためaws-sdkの`DynamoDB`(V2)または`DynamoDBClient`(V3)を使用する。

```jsx
// CommonJS (以前の方法)
// let doc = require('dynamodb-doc');
// let dynamo = new doc.DynamoDB();

// ESモジュール
import { DynamoDB } from 'aws-sdk'; //←V2
import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; //←V3
```

## exportsの変更

```errorMessage: exports is not defined in ES module scope```

exportsがESモジュールでは使用できないために発生しているみたい。

ESモジュールでは、基本`export`と`import`を使用するとのこと。

どうやら、CommonJSのシンタックスが`require`とか`exports`のようで、.mjsの拡張子はESモジュールとして認識されるためこのエラーが表示されている。

# 最終的なコード

```jsx
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { PutCommand } from "@aws-sdk/lib-dynamodb";

// DynamoDBのクライアントを作成
const dynamo = new DynamoDBClient({ region: "ap-northeast-1" });

export const handler = async function(event) {

  const tableName = "test";
  const item = {
    ID: Number(event.ID),  // IDを数値に変換
    Message: event.Message,
  };

  const params = {
    TableName: tableName,
    Item: item
  };

  try {
    // データをDynamoDBに挿入するコマンドを作成
    const command = new PutCommand(params);
    
    // コマンドを実行して、DynamoDBにデータを挿入
    await dynamo.send(command);
    
    return {
      statusCode: 200,
      body: JSON.stringify('Item successfully inserted!')
    };
  } catch (error) {
    console.error('Error inserting item:', error);
    return {
      statusCode: 500,
      body: JSON.stringify('Error inserting item')
    };
  }
};
```

# Lamda関数のIAMロールにDynamoDBへの適切なアクセス権限がアタッチされているか

こちらはエラーではありませんが、上記処理にして、テストを実行してもDBにデータが挿入されなかったため、色々調べていたところLamda関数に対しての権限付与が必要だったので記載しました。

## IAMロール設定手順

1. IAM>ロールから今回使用するLamda関数の名前にアクセスをする
![スクリーンショット 2024-10-20 16.21.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2597943/0b0f8da2-f808-4871-9e2c-13ca896baf10.png)
2. 許可ポリシーから、「許可を追加」を選択
3. 「ポリシーをアタッチ」を選択
4. 「Dynamo」に関するポリシーを検索
![スクリーンショット 2024-10-20 16.24.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2597943/b0b7aa7d-b894-129e-37b6-c1b624414b18.png)

5. チェックボックスにチェックをし、許可を追加

Lamda関数にポリシーをアタッチすることで、テストを実行したところ、Dynamo DBに対してデータの挿入ができるようになりました。