SST v3でサーバーレス開発を簡単に！LambdaとS3を活用したシンプルな構築例

# **はじめに**

はじめまして。9月にバックエンドエンジニアとしてジョインした[@yasuyasu002d](https://qiita.com/yasuyasu002d)です。

AWSを使ったサーバーレスアーキテクチャは、その効率性とスケーラビリティから多くの企業や開発者に採用されています。しかし、インフラコードの管理やリアルタイム開発が課題になることもあります。  
**Serverless Stack (SST)** は、これらの課題を解決し、効率的にサーバーレスアプリケーションを構築できるフレームワークです。

本記事では、Serverless Stack (SST) v3 を使って、簡単にサーバーレスシステムを構築する方法をご紹介します。

1. SSTを使ったプロジェクトのセットアップ
2. AWS LambdaとS3を利用したサーバーレスシステム構築
3. SSTのリアルタイム開発機能「Live Lambda Debugging」の体験

## **SST とは**

### **Serverless Stack (SST) の概要**

**Serverless Stack (SST)** は、AWS上でサーバーレスアプリケーションを簡単に構築できるフレームワークです。**SST v3** では、新たに **Plumi** を基盤として、従来のAWS CDKベースから進化しました。

#### **SSTの特長**
1. **シンプルで直感的にクラウド構築**  
   IaCツールである [pulumi](https://www.pulumi.com/) をベースのため軽量で簡潔なコードが記述が可能。(v2 までは AWS CDK利用していました）

2. **フロントエンド統合が容易**  
   Next.jsといったモダンフレームワークと統合可能で、`sst.aws.StaticSite`や`sst.aws.Nextjs`を活用して簡単にホスティングができます。

3. **リアルタイム開発**  
   Lambda関数をデプロイせずにデバッグ可能な「Live Lambda Debugging」機能を搭載し、開発効率を大幅に向上。

#### **SSTの活用例**
- Next.jsでのフロントエンドとバックエンドAPI開発の統合開発
- イベント駆動型アーキテクチャの構築 (例: EventBridgeとの連携)

## **システム構成**
以下は、LambdaからS3にJSON形式のデータをアップロードする構成を示しています。Lambda関数は現在時刻を取得し、その結果をS3に保存します。


```mermaid
graph TD
    B[AWS Lambda]
    B -->|"PutObject(json)"| C[Amazon S3]
```

# **実装例**
* 事前準備としてNode.js、AWSCliをセットアップが必要です。

## **1. プロジェクトのセットアップ**
SSTの公式テンプレートを利用して、プロジェクトをセットアップします。


githubから[テンプレート](https://github.com/sst/monorepo-template)を `git clone` し `npm install` します

(テンプレート利用については以下を参考にしてください)

https://guide.sst.dev/chapters/create-an-sst-app.html

 
### IaC定義の確認

`sst.config.ts` 

* 設定情報、リソース定義を行います。

```typescript
export default $config({
  // アプリ設定情報
  app(input) {
    return {
      name: "monorepo-template",
      removal: input?.stage === "production" ? "retain" : "remove",
      home: "aws",
    };
  },
  // リソース定義
  async run() {
    await import("./infra/storage");
    const api = await import("./infra/api");

    return {
      api: api.myApi.url,
    };
  },
});
```

* `./infra/storage` , `./infra/api` にそれぞれ作成するS3バケット、Lambdaのリソース定義がされています。

  * infra/api.ts : Lambda function
    ```typescript
    export const myApi = new sst.aws.Function("MyApi", {
      url: true,
      link: [bucket],
      handler: "packages/functions/src/api.handler"
    });
    ```

  * infra/storage.ts : s3バケット

    ```typescript
    export const bucket = new sst.aws.Bucket("MyBucket");
    ```

### 設定変更
* アプリ名を"monorepo-template"→"sst-example"に変更します。

```diff_typescript
 export default $config({
   app(input) {
     return {
-      name: "monorepo-template", <-- app 名
+      name: "sst-example",
       removal: input?.stage === "production" ? "retain" : -- 
```

### デプロイ
* デプロイ実行してみます。ターミナル上で AWSクレデンシャルをexportし、コマンド実行

 ```bash
 $ npx sst deploy --stage <stage名>
 ```

* Completeと表示されればデプロイ完了です。

```
npx sst deploy --stage dev
SST 3.3.44  ready!

➜  App:        sst-example
   Stage:      dev

~  Deploy
✓  Complete
   MyApi: https://xxx.lambda-url.ap-northeast-1.on.aws/
   ---
   api: https://xxx.lambda-url.ap-northeast-1.on.aws/
```

* AWSコンソールで確認するとLambdaとS3が「sst-example-dev-MyApiFunction」「sst-example-dev-mybucket-xxxxx」でそれぞれ作成されています。

* Lambda関数をテスト実行すると、関連するバケット名が出力されます

```json
{
  "statusCode": 200,
  "body": "Hello, world! Linked to sst-example-dev-mybucket-xxx."
}
```

## 2.コード修正(LambdaからS3へファイルアップロード)
* セットアップできたので、[SST Live機能](https://sst.dev/docs/live/)を利用してS3アップロード変更をローカルで確認してみます。

### 開発用環境の構築
* `sst dev` コマンドで開発者環境を構築します。(詳細は [公式ドキュメント](https://sst.dev/docs/workflow#dev) 参照)

```bash
$ npx sst dev
```

* ターミナルがSST開発モードに切り替わります。

![sst_dev](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489685/cafc2a5a-a740-cf5d-c2cd-5f320e899861.png)

* Functions にするとLambdaログ出力されます
![sst_dev_functions](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489685/33efa37a-fade-14b4-a720-1e919d58ae5d.png)

### コード修正
* `packages/functions/src/api.ts`

```diff_typescript
export const handler: Handler = async (_event) => {
  
+  const s3 = new S3Client();
+
+  const data = {
+    date: new Date()
+  }
+
+  await s3.send(new PutObjectCommand({
+    Key: "sample.json",
+    Body: JSON.stringify(data),
+    Bucket: Resource.MyBucket.name, // SST が自動注入
+    ContentType: "application/json"
+  }));
+
+  console.log(`S3 upload`)
```

### テスト

* AWSコンソール上から Lambdaをテスト実行させInvokeするとローカルにプロキシされローカルのソースコードが実行されます

```bash
|  Build       MyApi
|  Invoke      MyApi
|  +218ms      S3 upload
|  Done        took +414ms
```

* S3にもjson保存されていること確認できます

```
$ aws s3 ls sst-example-pc-name-mybucket-xxxxx
2024-12-09 14:09:43         35 sample.json
```

* ローカルでの検証ができたので `sst deploy`で デプロイを実施し今回のシステムは完了です。

# **まとめ**

今回の記事では、SSTを活用してシンプルなサーバーレスシステムを構築しました。SSTは簡潔なコードと便利なデバッグ機能で、AWSリソースの構築を効率化します。サーバーレスアーキテクチャを学び、応用していく第一歩として、ぜひこのシステムを試してみてください！

最後に、トレブレは、技術を通じて価値を生み出すことを目指し、成長し続けるチームです。新たな挑戦を共に進める仲間をお待ちしています！  

https://hrmos.co/pages/trail-blazer/jobs

---
# 参考サイト
* https://sst.dev/docs
* https://sst.dev/docs/set-up-a-monorepo
* https://guide.sst.dev/chapters/create-an-sst-app.html
* [PulumiベースのSST(v3)でサーバーレスアプリケーションをデプロイする](https://developer.mamezou-tech.com/blogs/2024/03/10/sst-v3-intro/)