【TypeScript】AWS CDKv2でサクッとLambda関数を作る

先日AWS CDK v2がstableになり、一層便利に使えるようになったので、TypeScriptでLambda関数をサクッと作ってみました。
リポジトリは公開していますので、よかったらご参考ください :bow: 

https://github.com/tokku5552/cdk-lambda-typescript

### 環境

- macOS Monterey バージョン12.0.1 (Intel)
- node -v
    - v16.13.0
- npm -v
    - 8.1.4

```json:package.json(一部)
  "devDependencies": {
    "@types/jest": "^26.0.10",
    "@types/node": "10.17.27",
    "jest": "^26.4.2",
    "ts-jest": "^26.2.0",
    "aws-cdk": "2.2.0",
    "ts-node": "^9.0.0",
    "typescript": "~3.9.7"
  },
  "dependencies": {
    "aws-cdk-lib": "2.2.0",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.16"
  }
```

# AWS CDKv2 TypeScriptクイックスタート
初期構築を詳細に知りたい方は以下をご参考ください。

https://qiita.com/tokkun5552/items/2563c21259950beef330

以下のコマンドを入力します。

```shell:
% npm install -g aws-cdk
% mkdir cdk-lambda-typescript
% cd cdk-lambda-typescript
% cdk init --language typescript
```

VSCodeで開くと、以下のように必要なファイルとフォルダが作られています。
![スクリーンショット 2021-12-18 22.56.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/b367412d-39f4-41d8-c0f0-c3e6985fbe24.png)

## CDKのスタック

作られたフォルダの`lib`の下に実際のスタックを定義していきます。
今回はできるだけ簡単に実装したかったので、1ファイルにすべて書いています。

```typescript:lib/cdk-lambda-typescript-stack.ts
import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import { Function, Runtime, AssetCode } from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';

export class CdkLambdaTypescriptStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new Function(this, 'HelloWorld', {
      functionName: 'HelloWorld',
      handler: "handler.handler",
      runtime: Runtime.NODEJS_14_X,
      code: new AssetCode(`./src`),
      memorySize: 512,
      timeout: Duration.seconds(10),
    });
  }
}
```

実際はAPI Gatewayや他のサーバーレスサービスと併用することがほとんどかと思いますが、Lambdaだけ定義するのであれば上記だけで事足ります。
`AssetCode`のところで、プロジェクト内のlambda関数がおいてある場所を指定することで、CDK側がいい感じにlambda関数もデプロイしてくれます。

## lambda関数
今回は`src`というフォルダの下に関数を作ることにしたので、`src`フォルダの下にlambda関数の本体である`handler.ts`と`TypeScript`ビルド用の`package.json`をおいています。

関数本体は以下のように何のリクエストが来てもHello Worldを返す単純な関数です。

```typescript:src/handler.ts
export const handler = async function (event: any, context: any) {
    return {
        statusCode: 200,
        headers: {},
        body: { message: 'Hello World!' }
    };
};
```

# デプロイ

`npm run build`でビルドしてから、`cdk`コマンドでデプロイを行います。
プロジェクトで初めてデプロイするときは、先に`cdk bootstrap`を実施しておきます。これで必要なIAMロールなどを自動で生成してくれます。

```
cdk bootstrap
cdk deploy
```

デプロイするとCloudFormationのスタックでUPDATEがかかります。
エラーが発生したときも、イベントを確認すると原因を探りやすいかと思います。
![スクリーンショット 2021-12-19 0.07.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/302c5269-d947-492a-1a89-2f09d9ecef35.png)

Lambdaの方でテストしてみると、正常に動いていることが確認できました
![スクリーンショット 2021-12-19 0.07.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141823/879cbfc1-fd43-d2e4-0b04-a5c19e10dcdb.png)

# まとめ
サーバーレスなAWSリソースをコードベースで作成するツールとしては他に`SAM`や`Serverless Framework`などがありますが、その中でも`AWS CDK`はよりアプリケーションエンジニアにわかりやすい構文としてかけそうだなと感じました。`Serverless Framework`は定義ファイルを`TypeScript`で定義することもできるのですが、結局yamlで書いているのとほとんど同じように記載する必要があって、`TypeScript`で書いている感じはあまりしないというのが感想です。
その点、`CDK`を使ったサーバーレス構成というのは今後ますます流行りそうだなという感触でした。

### 参考

- [aws-cdk-examples/typescript/lambda-api-ci at master · aws-samples/aws-cdk-examples](https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/lambda-api-ci)
- [aws-cdk-lib.aws_lambda module · AWS CDK](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html)
- [AWS CDKにLambda関数を数秒でデプロイするhotswap deployments機能が追加されました](https://zenn.dev/intercept6/articles/eed5b5cef89eb2)