【SSTことはじめ】SST（Serverless Stack）のLive Lambda Devで、ローカルでも動作確認できるAWS Lambda開発を体感してみる

## SST（Serverless Stack）ってなに？

SST（Serverless Stack）は、モダンなフルスタックアプリケーションをAWSにデプロイする便利なフレームワークだよ。SSTには２つの側面があって、

1. CDKを内包しており、CDKを上回る簡潔さでAWSのインフラをコードで定義できるIaCツールとしての側面
2. Live Lambda DevやSSTコンソールによる開発支援ツールとしての側面

の２つの機能を有しているんだ。

https://github.com/serverless-stack/sst

今回は後者の `Live Lambda DevやSSTコンソールによる開発支援ツールとしての側面` を体験すべく、SSTの雛形アプリを動かしてみるよ。

## 筆者プロフィール

Kenpal株式会社でITエンジニアとして色々いじってる faable01 です。

https://www.kenpalinc.com/

ものづくりが好きで、学生時代から創作仲間と小説を書いたりして楽しんでいたのですが、当時はその後自分がIT技術者になるとはつゆ程も思っていませんでした。紆余曲折あり、20代の半ばを過ぎた頃に初めてこの業界と出会った形です。

趣味は「技術記事を口語で書くこと」です。

個人サイトにもSSTのことをいくらか記事にしているから読んでね。

https://signote.link/

それから、業務日報SaaS **「RevisNote」** を運営しています。リッチテキストでの日報と、短文SNS感のある分報を書けるのが特徴で、組織に所属する人数での従量課金制です。アカウント開設後すぐ使えて、無料プランもあるから、気軽にお試しください。

https://revisnote.com?202403150825

## SST（Serverless Stack）を触る前に用意しておきたい前提条件

- AWS CLIをインストール済み
- aws configureでデフォルトのアカウントを設定済み

## まずは雛形のSSTアプリを作成する

まずは雛形となるSSTアプリを作成するよ。create-sstコマンドを実行すればごく単純なAPI Gatewayを定義したSSTアプリケーションを構築できる。

```zsh
npx create-sst@2.0.2 my-sst-app
cd my-sst-app
npm i
```

これで「ごく単純なAPI Gateway」を定義したSSTアプリケーションが作成された。

せっかくだからリージョンだけ東京リージョンに変えておこうね。

```diff:sst.config.ts 
 import { SSTConfig } from "sst";
 import { API } from "./stacks/MyStack";
 import { Api } from "sst/constructs";
 
 export default {
   config(_input) {
     return {
       name: "my-sst-app",
-      region: "us-east-1",
+      region: "ap-northeast-1", 
     };
   },
   stacks(app) {
     app.stack(API);
   },
 } satisfies SSTConfig;
```

雛形のSSTアプリの作成はこれで完了！

## Live Lambda Dev + SSTコンソールを体感してみる

ここまでできたら、さっそくLive Lambda Devを開始してみるよ。Live Lambda Devっていうのが何かってことについては後で説明するからね。

```zsh
# なおこの時デプロイされるアカウントはaws configureのデフォルト設定アカウントである
npx sst start
```

これだけでLive Lambda Devが開始する。なお初回実行時には下記のようにステージ名を尋ねられるよ。ここでいうステージとは、各開発者が使うLive Lambda Devごとのステージ名だから、基本的にはユーザー名を入力するといいよ。AWS CLIで設定したユーザー名のままで良ければそのままENTERを押せばいいからね。

```zsh
# 詳しくは https://docs.sst.dev/quick-start#pick-a-stage 参照
Look like you’re running sst for the first time in this directory.
Please enter a stage name you’d like to use locally.
Or hit enter to use the one based on your AWS credentials (sig):
```

npx sst startの初回実行が完了すると、ターミナルにはこんな表示が出ているはず。

```zsh
my-sst-app % npx sst start

Please enter a name you’d like to use for your personal stage. Or hit enter to use sig: 
Warning: sst start has been renamed to sst dev
✔ Deploying bootstrap stack, this only needs to happen once
SST v2.0.2  ready!

➜  App:     my-sst-app
   Stage:   sig
   Console: https://console.sst.dev/my-sst-app/sig

|  API api/Api AWS::ApiGatewayV2::Api CREATE_COMPLETE 
|  API api/LogGroup AWS::Logs::LogGroup CREATE_COMPLETE 
|  API api/Api/DefaultStage AWS::ApiGatewayV2::Stage CREATE_COMPLETE 
|  API api/Parameter_url AWS::SSM::Parameter CREATE_COMPLETE 
|  API api/Lambda_GET_--/ServiceRole AWS::IAM::Role CREATE_COMPLETE 
|  API CustomResourceHandler/ServiceRole AWS::IAM::Role CREATE_COMPLETE 
|  API CustomResourceHandler AWS::Lambda::Function CREATE_COMPLETE 
|  API api/Lambda_GET_--/ServiceRole/DefaultPolicy AWS::IAM::Policy CREATE_COMPLETE 
|  API api/Lambda_GET_-- AWS::Lambda::Function CREATE_COMPLETE 
|  API api/Route_GET_--/Integration_GET_-- AWS::ApiGatewayV2::Integration CREATE_COMPLETE 
|  API api/Lambda_GET_--/EventInvokeConfig AWS::Lambda::EventInvokeConfig CREATE_COMPLETE 
|  API api/Route_GET_-- AWS::ApiGatewayV2::Route CREATE_COMPLETE 
|  API api/Route_GET_-- AWS::Lambda::Permission CREATE_COMPLETE 
|  API AWS::CloudFormation::Stack CREATE_COMPLETE 

✔  Deployed:
   API
   ApiEndpoint: https://aidxa5qpl4.execute-api.ap-northeast-1.amazonaws.com
```

ターミナルに出力された２つのURLを列挙すると、こうだね。

```zsh
# SST（Serverless Stack）のコンソール。
# Live Lambda Devのリクエストやレスポンスを確認できる。
# その他にもさまざまな機能が用意されており、開発効率化に役立つ。
Console: https://console.sst.dev/my-sst-app/sig

# Live Lambda Devで動作させているAPI Gatewayのエンドポイント
ApiEndpoint: https://aidxa5qpl4.execute-api.ap-northeast-1.amazonaws.com
```

コメントに書いた通り、前者はSSTコンソールのURL、後者はLive Lambda Devで動作させているAPI Gatewayのエンドポイントなんだ。SSTコンソールは、Live Lambda Devのリクエストやレスポンスをブラウザ上から確認したり、デプロイされたスタックやリソースを参照したりといった、開発に役立つさまざまな機能を提供してくれるよ。

そういうわけでSSTコンソールを開いた上で、実際にAPI Gatewayのエンドポイントにリクエストを投げてみると...

![スクリーンショット 2023-02-08 11.57.43.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267156/1e8504e0-5b76-3024-7c44-3600c7ae50f8.jpeg)

こんな風にリアルタイムでリクエスト・レスポンスをSSTのコンソール上から確認できる。

**Live Lambda Devのすごく便利な点はここから。**

まずはローカルでLambdaのコードを書き換えてみる。

```diff
 import { ApiHandler } from "sst/node/api";
 import { Time } from "@my-sst-app/core/time";
 
 export const handler = ApiHandler(async (_evt) => {
   return {
-    body: `Hello world. The time is ${Time.now()}`,
+    body: 'Hi!',
   };
 });
```

書き換えたら、API Gatewayのエンドポイントにアクセスしてみる。

すると……

![スクリーンショット 2023-02-08 12.00.20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267156/a51a9673-fa9d-57da-8006-0509b3679900.jpeg)

**Lambdaなのにローカルの変更が直ちに反映された！！**

もちろん、SSTコンソールもその変更後のコードへのリクエスト・レスポンスをリアルタイムで表示できている。


## Live Lambda DevでローカルのVSCodeからデバッグしてみる

Live Lambda Devはローカルからデバッグすることも可能だよ。実行中の `npx sst start` コマンドをいったん終了させてから、VSCodeの「実行とデバッグ」メニューから `Debug SST Start` を開始してみよう。

するとnpx sst startをコマンドで実行した時と同じくSSTコンソールとLive Lambda Devのエンドポイントが表示される。この状態で、Lambdaのコードにブレイクポイントを配置して動かしてみよう。すると……

![スクリーンショット 2023-02-08 19.25.05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267156/cc58f5e5-bf14-a8cf-7e0f-42a6f409beb0.jpeg)

こんな風にVSCode上ですぐに処理をデバッグすることができる。

※VSCode用のデバッグ構成は、`.vscode/launch.json`に記述されている。create-sstで雛形アプリケーションを作成したときに、このファイルも最初から作成されているから、特に手を加えることなくLive Lambda Devのデバッグを試せるよ。

## あらためて、Live Lambda Devってなに？

というわけで、改めて『Live Lambda Devってなに？』ということについて端的に説明すると

- Live Lambda Devは、**AWS Lambdaをローカルで動作確認・デバッグできるSSTの機能**

ということになるね。

**『Lambdaを模した別物』ではなく、『本物のAWS Lambdaなのにローカルのコードで動く存在』** だから、AWS上にあるその他のサービスからトリガーされることも、IAMによるアクセス制御を行うことも可能だよ。

Live Lambda Devを用いない既存のアプローチでは、 **「AWS上にデプロイしてみないと検証できない」** がために開発効率が悪かったり品質の低下を招いたりするけれど、SSTのLive Lambda Devを用いればこういった難点を解消できるわけだね。

ちなみに、Live Lambda Devの仕組みについては公式ドキュメントでこんな風に書かれているよ。WebSocket経由でAWS IoTを利用して、ローカルPCとAWS上のLambdaを繋いでいるみたいだね。

> SST uses AWS IoT over WebSocket to communicate between your local machine and the remote Lambda function. Every AWS account comes with a AWS IoT Core endpoint by default. You can publish events and subscribe to them.

https://docs.sst.dev/live-lambda-development#how-live-lambda-is-different

## Live Lambda Dev の料金

Live Lambda Devは、公式ドキュメントの言葉を借りるなら『かなり安く』使えるようになっているよ。

> AWS IoT that powers Live Lambda is completely serverless. So you don't get charged when it's not in use.
> It's also pretty cheap. With a free tier of 500k events per month and roughly $1.00 per million for the next billion messages. You can [check out the details here](https://aws.amazon.com/jp/iot-core/pricing/).
> As a result this approach works great even when [there are multiple developers on your team](https://docs.sst.dev/working-with-your-team).

https://docs.sst.dev/live-lambda-development#cost

AWS IoTもLambdaのようにサーバーレスなサービスで、課金の仕組みが基本的に「使った分だけ」で請求されるようになっているみたいだね。AWS IoTの無料枠もあることだし、チーム開発でもコストを抑えながら開発効率を上げることができるよ。

## まとめ

- SST（Serverless Stack）には２つの側面がある
  1. CDKを内包しており、CDKを上回る簡潔さでAWSのインフラをコードで定義できるIaCツールとしての側面
  2. Live Lambda DevやSSTコンソールによる開発支援ツールとしての側面
- SSTコンソールはLive Lambda Devのリクエストとレスポンスをリアルタイムで監視したり、その他さまざまな開発効率化の機能を提供してくれる
- Live Lambda Devはローカルで動確とデバッグ可能なLambda。SSTがAWS IoTとWebSocketで実現している

SSTのLive Lambda Devを使えば、Lambdaの開発でありがちな **「デプロイしないと動作確認できない」** という難点を解決できる。開発効率を上げるにはすっごくおすすめだから、Lambdaで何か作りたい人はぜひ触ってみてね。

____________

## 【おまけ1】 Live Lambda Devではなく、本番用にSSTアプリケーションをデプロイする

ステージ名を指定してデプロイするよ。今度はLive Lambda Devは開発者ごとにユーザー名でステージを作るのを推奨したけど、本番環境や検証環境なら、prodやdevといった名前をつけるのが一般的だね。今回は本番デプロイを想定して、prodという名前のステージでデプロイするよ。

```zsh
npx sst deploy --stage prod
```

あとは数分ほど待っていればいいよ。コマンドがエラーなく終わればデプロイ成功！

```
my-sst-app %   npx sst deploy --stage prod
SST v2.0.2

➜  App:     my-sst-app
   Stage:   prod
   Region:  ap-northeast-1
   Account: 123456789012

✔  Building...

|  API api/Api AWS::ApiGatewayV2::Api CREATE_COMPLETE 
|  API api/LogGroup AWS::Logs::LogGroup CREATE_COMPLETE 
|  API api/Api/DefaultStage AWS::ApiGatewayV2::Stage CREATE_COMPLETE 
|  API api/Parameter_url AWS::SSM::Parameter CREATE_COMPLETE 
|  API CustomResourceHandler/ServiceRole AWS::IAM::Role CREATE_COMPLETE 
|  API api/Lambda_GET_--/ServiceRole AWS::IAM::Role CREATE_COMPLETE 
|  API CustomResourceHandler AWS::Lambda::Function CREATE_COMPLETE 
|  API api/Lambda_GET_--/ServiceRole/DefaultPolicy AWS::IAM::Policy CREATE_COMPLETE 
|  API api/Lambda_GET_-- AWS::Lambda::Function CREATE_COMPLETE 
|  API api/Route_GET_--/Integration_GET_-- AWS::ApiGatewayV2::Integration CREATE_COMPLETE 
|  API api/Route_GET_-- AWS::ApiGatewayV2::Route CREATE_COMPLETE 
|  API api/Route_GET_-- AWS::Lambda::Permission CREATE_COMPLETE 
|  API AWS::CloudFormation::Stack CREATE_COMPLETE 

✔  Deployed:
   API
   ApiEndpoint: https://wtl6i92x6a.execute-api.ap-northeast-1.amazonaws.com

my-sst-app %  
```

最後に表示されたエンドポイントのURLをコールすると、デプロイしたAPI Gatewayの応答を得ることができるはずだよ。

## 【おまけ2】 デプロイしたリソースの破棄

今回は下記のリソースを作成したね。

 1. Live Lambda Dev用のSSTアプリケーション
 2. 本番環境用のprodステージのSSTアプリケーション（おまけ1にて作成）

これらを削除するよ。

```zsh
# stageオプションなしならLive Lambda Dev用にデプロイした自分のステージを削除する
npx sst remove

# 上記以外を削除するならstageオプションを明示する
npx sst remove --stage prod

# ---- 補足 ----
# stageなどのグローバルオプションは下記参照
# https://docs.sst.dev/packages/sst#global-options
```

これでデプロイしたリソースは全て削除できたはずだよ。

ただ、今回の雛形SSTアプリケーションは単純なAPI Gatewayだから考慮不要だけど、S3やDynamo DBといったリソースをSSTアプリケーションに含めている場合はその限りではないからね。S3等のリソースは、デフォルトではsst removeを実行しても消えないんだ。これらリソースの削除時の振る舞いを変更するには、Removal Policyの設定が必要だよ。

Removal Policyというのは、CDKを普段から使っている人はよく知ってるかもしれないね。SSTにおけるRemoval Policyは下記ドキュメントで解説しているから、必要な人は読んでおくといいよ。

https://docs.sst.dev/advanced/removal-policy

## 【おまけ3】 CDKのことを知ってる人向け補足

SST（Serverless Stack）はAWS CDKを内包していて、いろいろなことがCDKをそのまま使うよりも簡単にできるようになっているよ。

例えばCDKを使うならデプロイ前にcdk bootstrapを明示的に行う必要があるけど、SSTならnpx sst start等のコマンドを実行したときに、必要に応じて勝手にbootstrapをやっといてくれるんだ。便利だよね。

CDKとどう違うのかについてはここに書いてあるから、興味のある人は読んでみてね。

https://docs.sst.dev/migrating/cdk