【AWS】SAMを使ってみよう （セットアップ編）

# はじめに

こんにちは。最近SAMを使い始めて、魅了されています。
興味がある方の参考になればと思い投稿します。
今回は、「SAMのセットアップ〜AWSへのデプロイの一連の流れ」のセットアップ編になります。
下記の悩みを持っている方は是非、見てください。

-  SAMって聞いたことあるけど、触ったことない
-  APIGateway、Lambdaなどサーバレスアーキテクチャーは構築したことはあるが、AWSコンソール上で作成しており、一元管理できていない。ローカル開発をしてgit管理しながらデプロイしたい



# SAMってなに？
AWS SAM（Serverless Application Model）は、サーバーレスアプリケーションを簡単に構築、テスト、デプロイするためのフレームワークです。AWS SAMは、API Gateway、AWS Lambda、DynamoDBなどのAWSサービスを使用したサーバーレスアプリケーションの定義を簡素化するためのテンプレート仕様を提供し、開発者はインフラストラクチャの管理を最小限に抑えつつ、迅速にアプリケーションを開発・展開できます。

自分が感じる主要なメリットは下記です。
##### 1. 各リソースを一元管理できる (template.yaml)
##### 2. ローカル開発/git管理ができる
##### 3. TypeScriptが使える (Node環境のため、GUI上だとJavaScript)

です。

[AWS公式ドキュメント（SAM）](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/what-is-sam.html)

# 事前準備
1. Dockerのインストール [公式](https://www.docker.com/ja-jp/)
2. sam cliのインストール
```zsh
brew tap aws/tap
brew install aws-sam-cli
```

# ローカルセットアップ、開発
##### 1.  下記コマンドでセットアップ
2025年1月現在使用できるランタイムは下記。
```
1 - dotnet8
2 - dotnet6
3 - go (provided.al2)
4 - go (provided.al2023)
5 - graalvm.java11 (provided.al2)
6 - graalvm.java17 (provided.al2)
7 - java21
8 - java17
9 - java11
10 - java8.al2
11 - nodejs20.x
12 - nodejs18.x
13 - nodejs16.x
14 - python3.9
15 - python3.8
16 - python3.12
17 - python3.11
18 - python3.10
19 - ruby3.3
20 - ruby3.2
21 - rust (provided.al2)
22 - rust (provided.al2023)
```
今回は、自分の大好きなnode(Typescript)で進めていきます。
```
sam init --runtime nodejs20.x
```
色々聞かれますが、今回の設定は下記です。

```zsh
Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - GraphQLApi Hello World Example
        3 - Hello World Example with Powertools for AWS Lambda
        4 - Multi-step workflow
        5 - Standalone function
        6 - Scheduled task
        7 - Data processing
        8 - Serverless API
        9 - Full Stack
        10 - Lambda Response Streaming
Template: 1

Based on your selections, the only Package type available is Zip.
We will proceed to selecting the Package type as Zip.

Based on your selections, the only dependency manager available is npm.
We will proceed copying the template using npm.

Select your starter template
        1 - Hello World Example
        2 - Hello World Example TypeScript
Template: 2

Would you like to enable X-Ray tracing on the function(s) in your application?  
[y/N]: n

Would you like to enable monitoring using CloudWatch Application Insights?
For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html 
[y/N]: n

Would you like to set Structured Logging in JSON format on your Lambda functions?  [y/N]: n

Project name [sam-app]: sample-sam
```
以上を実施しすると、下記のファイルが自動で作成されます

```
.
└── sample-sam
    ├── README.md
    ├── events
    │   └── event.json
    ├── hello-world
    │   ├── app.ts //ここがエンドポイント
    │   ├── jest.config.ts
    │   ├── package.json
    │   ├── tests
    │   │   └── unit
    │   │       └── test-handler.test.ts
    │   └── tsconfig.json
    ├── samconfig.toml //samの設定ファイル
    └── template.yaml //リソースの設定ファイル（≒ cloudFormation）
```


#### 2.  Dockerの立ち上げ（samがDockerコンテナで起動するため）

#### 3. プロジェクト（今回はsample-sam）直下に移動してから、下記コマンドでsamの立ち上げ
```
sam build
sam local start-api
```
※「sam build」はLambda関数のコードとその依存関係をパッケージ化し、デプロイ可能な形に整えるプロセスです。

#### 4.localhots:3000/helloにアクセス
下記が参照できれば無事ローカルで立ち上げ完了！！
![quita-sam1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983223/cf74bcfb-dc14-014b-4d3a-d05d2f7d8dee.png)

#### 5.lambda関数を編集してみる
app.tsのファイルを下記のように編集

```
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';

/**
 *
 * Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
 * @param {Object} event - API Gateway Lambda Proxy Input Format
 *
 * Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
 * @returns {Object} object - API Gateway Lambda Proxy Output Format
 *
 */

export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
    try {
        return {
            statusCode: 200,
            body: JSON.stringify({
                // message: 'hello world', //旧
                message: 'hello from lambda', //新
            }),
        };
    } catch (err) {
        console.log(err);
        return {
            statusCode: 500,
            body: JSON.stringify({
                message: 'some error happened',
            }),
        };
    }
};
```

#### 6. 一度サーバーを落として(ctr + c)、再度3コマンドを実施して、localhostへアクセス
下記のように反映されていたら、無事成功！！
![スクリーンショット 2025-01-11 21.45.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983223/b50c7854-4abe-83e2-809b-dda8c89bbd55.png)


# まとめ
ここまで、読んでくださりありがとうございます。
SAMを導入することで、サーバーレスアーキテクチャーを一元管理できて且つ、ローカルで開発できます。そうです、ローカルでテストだって書くことができます。
設定も簡単ですぐにプロジェクトが始められるのも魅力の一つです。是非、一度SAMを触ってみてください。少しでも興味を持って頂けたら幸いです。

# 関連記事（投稿後、リンクを追加します）
- [SAMを使ってみよう（デプロイ編）](https://qiita.com/baison_/items/5f0351f00f1014a8f34c)
- SAMを使ってみよう（ローカル開発・3層アーキテクチャ編）　未