배경

AWS SAM이란 Serverless Application Model이다.

간단하게 설명하면 AWS CloudFormation을 확장하여 Lambda, API Gateway, Step Functions와 같은 Serverless Application을 정의하고 Build, Test, Deploy할 수 있도록 도와주는 도구이다.

주요 파일

주요 구조는 다음과 같다.

projects/
- samconfig.toml
- template.yaml
- src/

SAM에서 기본적으로 사용하는 Template 이름은 template.yaml이다. 다른 이름을 사용한다면 --template-file을 통해 별도로 지정해야한다.

samconfig.toml

samconfig.toml은 자원 정보나 CloudFormation Stack을 정의하는 파일이 아니라 SAM CLI 명령에서 사용할 기본 설정을 저장하는 파일이다.

sam deploy --guided에서 입력한 Stack Name, Region, S3/ECR 설정, Change Set 확인 여부 등을 저장한다.

version = 0.1
 
[default.global.parameters]
stack_name = "example-sam-app"
 
[default.build.parameters]
cached = true
parallel = true
 
[default.deploy.parameters]
region = "ap-northeast-2"
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
resolve_s3 = true

template.yaml

해당 파일에서는 생성할 Serverless 자원들을 정의한다. Lambda, CloudFront, API Gateway 등을 정의한다. 일반 CloudFormation 자원도 같이 정의할 수 있다.

Transform: AWS::Serverless-2016-10-31을 선언하면 AWS::Serverless::Function, AWS::Serverless::Api와 같은 SAM 자원을 CloudFormation 자원으로 변환한다.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
 
Resources:
  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: app.handler
      Runtime: python3.13
      Architectures:
        - x86_64

Template 작성이 완료되었다면 아래 명령어로 문법과 CloudFormation Rule을 확인할 수 있다.

sam validate --lint

사용법

주요 파일들에 대한 생성이 완료되었다면 sam build를 진행한다.

sam build

이 때, 중요한 점은 Lambda를 생성할 때 Runtime과 Build 도구가 필요할 수 있다는 점이다.

설치되어 있지 않거나 Lambda와 동일한 환경에서 Build가 필요하다면 아래의 Image 형식으로도 Build가 가능하다. 하지만 이를 위해 Docker와 같이 Container Image를 실행할 수 있는 환경이 필요하다.

sam build --use-container --build-image public.ecr.aws/sam/build-python3.13:1.136.0

Image를 직접 지정하지 않고 sam build --use-container만 사용하면 SAM에서 Runtime에 맞는 기본 Build Image를 선택한다. 특정 Version의 Image가 필요할 때만 --build-image를 사용한다.

이후, 경로를 확인해보면 새로운 .aws-sam 폴더가 추가된 것을 확인할 수 있다.

project/
├── .aws-sam/
│   └── build/
│       ├── template.yaml
│       └── HelloFunction/
├── samconfig.toml
└── template.yaml

.aws-sam/build에는 변환된 Template과 배포할 파일들이 생성된다. 해당 폴더의 내용물을 통해 배포를 진행하게 된다.

이후, 배포를 한다. 첫 배포라면 --guided를 사용하여 설정을 저장해두는 것이 편하다.

sam deploy --guided
sam deploy
sam deploy --profile [PROFILE]

Profile을 통해 AWS Config에 등록된 Profile을 이용하여 어떤 계정에 어떤 Role로 배포할 수 있는지 확인해서 배포가능하다.

--profile은 AWS CLI에 등록된 Credential과 Region을 선택하는 역할을 한다. 실제 배포 권한은 해당 IAM User 또는 AssumeRole 대상 Role의 Policy에 따라 결정된다. 배포 전에는 아래 명령어로 계정을 확인하는 것이 안전하다.

aws sts get-caller-identity --profile [PROFILE]

sam deploy는 생성된 파일을 S3 또는 ECR에 올리고 CloudFormation Change Set을 통해 Stack으로 배포한다.

기본 설정에서는 배포 중 오류가 발생하면 CloudFormation이 마지막 정상 상태로 Rollback한다. 실패한 자원을 그대로 두고 원인을 확인하고 싶다면 아래의 Option을 사용할 수 있다.

sam deploy --disable-rollback
# 신규 stack 생성 실패 동작을 명시할 때
sam deploy --on-failure DO_NOTHING

--disable-rollback--on-failure는 동시에 사용할 수 없다. 실패한 자원과 비용이 남을 수 있기 때문에 장애 원인을 확인하는 용도로만 사용하는 것이 좋다.

개인적인 생각

업데이트를 하고 SAM을 지속적으로 사용하면서 드는 생각은… 조금 별로라는 생각이 많이 든다.

Terraform과는 많이 다른 점이라고 친다면 CloudFormation의 기본 Rollback 동작이다.

급하게 자원을 생성해야하는 시점에서 자원이 여러개 있다면 하나라도 생성에 실패하게 되면 Stack이 마지막 정상 상태로 Rollback된다. 필요하다면 앞에서 정리한 Option으로 Rollback을 끌 수 있다.

Terraform은 Apply 중 실패해도 이미 적용된 자원을 자동으로 되돌리지 않고 State에 반영한다. 그런 점에서 관대한 것 같지만, 다음 Plan과 Apply에서 부분 적용 상태를 정리해야한다. 결국 두 도구가 실패를 처리하는 방식이 다른 것이다. 그리고 무엇보다도… 문법이 정말 별로다.

SAM은 Lambda 중심 Application의 Build, Local Test, CloudFormation 배포를 하나의 도구로 처리할 수 있다는 장점이 있다. 하지만 개인적으로는 아직 Terraform HCL보다 SAM과 CloudFormation YAML이 더 복잡하게 느껴진다.

참고 자료