AWS SAM 정리
AWSSAMServerlessDVA-C02
작성자 : 오예환 | 작성일 : 2026-01-18 | 수정일 : 2026-01-18
1. AWS SAM 개요
🤔 SAM이 뭔가요?
비유로 이해하기: SAM은 서버리스 앱의 설계도 템플릿입니다.
- 집을 지을 때 설계도가 필요하듯이
- Lambda + API Gateway + DynamoDB를 만들 때 간단한 YAML 파일 하나로!
- 복잡한 CloudFormation을 자동으로 생성해줌
SAM = Serverless Application Model
┌─────────────────────────────────────────────────────────────────┐
│ SAM의 역할 │
│ │
│ 기존 방식 (CloudFormation 직접 작성): │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 200줄의 복잡한 YAML... │ │
│ │ Lambda 정의, IAM Role 정의, API Gateway 정의, │ │
│ │ 권한 연결, 이벤트 매핑... │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ SAM 사용: │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 20줄의 간단한 YAML! │ │
│ │ AWS::Serverless::Function 하나면 끝! │ │
│ └────────────────────────────────────────────────────┘ │
│ │ │
│ ↓ 자동 변환 │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 복잡한 CloudFormation 템플릿 자동 생성! │ │
│ └────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘SAM 특징
| 특징 | 설명 | 초보자 설명 |
|---|---|---|
| YAML 기반 | 모든 설정을 YAML로 | 읽기 쉽고 버전 관리 가능 |
| CloudFormation 확장 | CF의 모든 기능 사용 가능 | Outputs, Parameters 등 |
| 로컬 테스트 | 로컬에서 Lambda 실행 | 배포 전 테스트 가능! |
| CodeDeploy 통합 | 안전한 배포 | Canary, Linear 배포 |
SAM이 지원하는 것
| 기능 | 설명 |
|---|---|
| Lambda | 서버리스 함수 |
| API Gateway | REST/HTTP API |
| DynamoDB | NoSQL 데이터베이스 |
| Step Functions | 워크플로우 |
| EventBridge | 이벤트 버스 |
| SQS, SNS | 메시징 |
2. SAM 기본 구조
SAM 템플릿 핵심 요소
# template.yaml
# 1. SAM 템플릿임을 선언 (필수!)
Transform: "AWS::Serverless-2016-10-31"
# 2. 설명
Description: My Serverless Application
# 3. 전역 설정 (선택)
Globals:
Function:
Timeout: 30
Runtime: nodejs18.x
# 4. 리소스 정의 (핵심!)
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
CodeUri: ./src
Events:
ApiEvent:
Type: Api
Properties:
Path: /hello
Method: get
# 5. 출력 (선택)
Outputs:
ApiUrl:
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"SAM 전용 리소스 타입
| 타입 | 설명 | CloudFormation 대응 |
|---|---|---|
AWS::Serverless::Function | Lambda 함수 | Lambda + IAM Role + ... |
AWS::Serverless::Api | API Gateway REST API | API Gateway + Stage + ... |
AWS::Serverless::HttpApi | API Gateway HTTP API | HTTP API + Stage + ... |
AWS::Serverless::SimpleTable | DynamoDB 테이블 | DynamoDB (단순 버전) |
AWS::Serverless::LayerVersion | Lambda Layer | Lambda Layer |
AWS::Serverless::Application | 중첩 애플리케이션 | Nested Stack |
Transform 헤더
# ⚠️ 이 줄이 있어야 SAM 템플릿으로 인식됨!
Transform: "AWS::Serverless-2016-10-31"초보자 설명: 이 줄이 CloudFormation에게 "이건 SAM 템플릿이야, SAM 리소스를 변환해줘"라고 알려줍니다.
3. SAM 배포 과정
🤔 어떻게 배포하나요?
배포 흐름
┌─────────────────────────────────────────────────────────────────┐
│ SAM 배포 과정 │
│ │
│ 1. 빌드 (sam build) │
│ ┌─────────────────┐ │
│ │ SAM Template │ │
│ │ (YAML) │ │
│ │ + 소스 코드 │ │
│ └────────┬────────┘ │
│ │ │
│ ↓ sam build │
│ │
│ 2. 패키지 & 배포 (sam deploy) │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ .aws-sam/ │ │ S3 Bucket │ │
│ │ build/ │────→│ (코드 업로드) │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ↓ transform │ │
│ ┌─────────────────┐ │ │
│ │ CloudFormation │←─────────────┘ │
│ │ Template │ │
│ └────────┬────────┘ │
│ │ │
│ ↓ create/update stack │
│ │
│ 3. CloudFormation 스택 생성 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ CloudFormation Stack │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────────┐ │ │
│ │ │ Lambda │ │ API │ │ DynamoDB │ │ │
│ │ │Function │ │ Gateway │ │ Table │ │ │
│ │ └─────────┘ └─────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘SAM CLI 명령어
# 1. 프로젝트 초기화
sam init
# 2. 빌드 (의존성 설치 + 패키징)
sam build
# 3. 배포 (첫 배포 시 --guided 옵션 추가)
sam deploy --guided
# 4. 이후 배포 (설정 저장됨)
sam deploysam deploy --guided
┌─────────────────────────────────────────────────────────────────┐
│ sam deploy --guided │
│ │
│ 첫 배포 시 대화형으로 설정: │
│ │
│ Stack Name [sam-app]: my-app │
│ AWS Region [us-east-1]: ap-northeast-2 │
│ Confirm changes before deploy [y/N]: y │
│ Allow SAM CLI IAM role creation [Y/n]: Y │
│ Save arguments to configuration file [Y/n]: Y │
│ │
│ → samconfig.toml 파일에 설정 저장됨! │
│ → 다음부터 sam deploy만 실행하면 됨 │
│ │
└─────────────────────────────────────────────────────────────────┘4. SAM Accelerate (sam sync)
🤔 sam sync가 뭔가요?
비유로 이해하기: 핫 리로드와 같습니다.
- 기존: 코드 수정 → sam build → sam deploy → 5분 대기...
- sam sync: 코드 수정 → 몇 초 만에 AWS에 반영!
sam deploy vs sam sync
| 항목 | sam deploy | sam sync |
|---|---|---|
| 방식 | CloudFormation 통해 배포 | 직접 API 호출 |
| 속도 | 느림 (분 단위) | 빠름 (초 단위) |
| 용도 | 프로덕션 배포 | 개발 중 빠른 테스트 |
| 안전성 | 높음 (변경 세트) | 낮음 (직접 업데이트) |
sam sync 옵션들
# 1. 코드 + 인프라 모두 동기화
sam sync
# 2. 코드만 동기화 (CloudFormation 우회, 매우 빠름!)
sam sync --code
# 3. Lambda 함수만 동기화
sam sync --code --resource AWS::Serverless::Function
# 4. 특정 리소스만 동기화
sam sync --code --resource-id HelloWorldLambdaFunction
# 5. 파일 변경 감지 + 자동 동기화 (개발 시 최고!)
sam sync --watchsam sync --watch (개발 필수!)
┌─────────────────────────────────────────────────────────────────┐
│ sam sync --watch │
│ │
│ 터미널: │
│ $ sam sync --watch │
│ Watching for file changes... │
│ │
│ ┌──────────────────────┐ │
│ │ src/index.js 수정 │ │
│ └──────────┬───────────┘ │
│ │ │
│ ↓ 자동 감지! │
│ │
│ 코드만 변경됨 → sam sync --code 자동 실행 │
│ 인프라 변경됨 → sam sync 자동 실행 │
│ │
│ → 저장하면 몇 초 만에 AWS에 반영! │
│ │
└─────────────────────────────────────────────────────────────────┘5. SAM Policy Templates
🤔 Policy Templates가 뭔가요?
비유로 이해하기: 미리 만들어진 권한 세트입니다.
- 직접 IAM 정책 작성하면 복잡하고 실수하기 쉬움
- SAM이 자주 쓰는 권한 조합을 템플릿으로 제공!
자주 쓰는 Policy Templates
| 템플릿 | 설명 | 사용 사례 |
|---|---|---|
S3ReadPolicy | S3 읽기 전용 | 파일 다운로드 |
S3WritePolicy | S3 쓰기 | 파일 업로드 |
S3CrudPolicy | S3 CRUD | 모든 S3 작업 |
DynamoDBReadPolicy | DynamoDB 읽기 | 데이터 조회 |
DynamoDBCrudPolicy | DynamoDB CRUD | 모든 DB 작업 |
SQSPollerPolicy | SQS 폴링 | 메시지 수신 |
SQSSendMessagePolicy | SQS 전송 | 메시지 발송 |
SNSPublishMessagePolicy | SNS 발행 | 알림 전송 |
LambdaInvokePolicy | Lambda 호출 | 다른 Lambda 실행 |
StepFunctionsExecutionPolicy | Step Functions 실행 | 워크플로우 시작 |
사용 예시
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
CodeUri: ./src
# Policy Templates 사용!
Policies:
# S3 버킷 읽기 권한
- S3ReadPolicy:
BucketName: !Ref MyBucket
# DynamoDB 테이블 CRUD 권한
- DynamoDBCrudPolicy:
TableName: !Ref MyTable
# SQS 큐 폴링 권한
- SQSPollerPolicy:
QueueName: !GetAtt MyQueue.QueueName직접 작성 vs Policy Template
# ❌ 직접 IAM 정책 작성 (복잡하고 실수 가능)
Policies:
- Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
- dynamodb:Query
- dynamodb:Scan
Resource: !GetAtt MyTable.Arn
# ✅ Policy Template 사용 (간단!)
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref MyTable6. SAM과 CodeDeploy 통합
🤔 왜 CodeDeploy가 필요한가요?
비유로 이해하기: 점진적 출시와 같습니다.
- 새 버전을 한 번에 모든 사용자에게 배포하면 위험!
- 조금씩 트래픽을 새 버전으로 이동
- 문제 발생 시 자동 롤백
Traffic Shifting (트래픽 전환)
┌─────────────────────────────────────────────────────────────────┐
│ Traffic Shifting 과정 │
│ │
│ 배포 전: │
│ Lambda Alias (LIVE) ──100%──→ Version 1 (기존) │
│ │
│ Canary 배포 시작 (10% 전환): │
│ Lambda Alias (LIVE) ──90%───→ Version 1 (기존) │
│ ──10%───→ Version 2 (신규) │
│ │
│ 문제 없으면 (10분 후): │
│ Lambda Alias (LIVE) ──0%────→ Version 1 (기존) │
│ ──100%──→ Version 2 (신규) │
│ │
│ ⚠️ 문제 발생 시: │
│ CloudWatch Alarm 트리거 → 자동 롤백! │
│ Lambda Alias (LIVE) ──100%──→ Version 1 (원복) │
│ │
└─────────────────────────────────────────────────────────────────┘배포 전략
| 전략 | 설명 | 예시 |
|---|---|---|
| AllAtOnce | 즉시 100% 전환 | 개발/테스트 환경 |
| Canary | X% 먼저, 대기, 나머지 | Canary10Percent5Minutes |
| Linear | 일정 간격으로 X%씩 | Linear10PercentEvery1Minute |
SAM 템플릿 설정
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
CodeUri: ./src
# 자동으로 버전 생성 + Alias 연결
AutoPublishAlias: live
# 배포 설정
DeploymentPreference:
# 배포 전략: 10%로 5분 테스트 후 100%
Type: Canary10Percent5Minutes
# 롤백 조건 (CloudWatch Alarm)
Alarms:
- !Ref MyAlarm
# 배포 전 테스트 함수
Hooks:
PreTraffic: !Ref PreTrafficHook
PostTraffic: !Ref PostTrafficHookHooks (배포 전/후 테스트)
┌─────────────────────────────────────────────────────────────────┐
│ Deployment Hooks │
│ │
│ 1. PreTraffic Hook (트래픽 전환 전) │
│ ├─ 새 버전 함수 테스트 │
│ ├─ DB 마이그레이션 확인 │
│ └─ 테스트 실패 시 배포 중단! │
│ │
│ 2. Traffic Shifting (점진적 전환) │
│ └─ 10% → 20% → ... → 100% │
│ │
│ 3. PostTraffic Hook (전환 완료 후) │
│ ├─ 통합 테스트 실행 │
│ ├─ 성능 테스트 │
│ └─ 테스트 실패 시 롤백! │
│ │
└─────────────────────────────────────────────────────────────────┘Hook 함수 예시
Resources:
# Pre-Traffic Hook Lambda
PreTrafficHook:
Type: AWS::Serverless::Function
Properties:
Handler: preTraffic.handler
Runtime: nodejs18.x
CodeUri: ./hooks
Policies:
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- codedeploy:PutLifecycleEventHookExecutionStatus
Resource: "*"
Environment:
Variables:
NewVersion: !Ref MyFunction.Version// hooks/preTraffic.js
const AWS = require("aws-sdk");
const lambda = new AWS.Lambda();
const codedeploy = new AWS.CodeDeploy();
exports.handler = async event => {
const deploymentId = event.DeploymentId;
const lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;
try {
// 새 버전 Lambda 테스트
const result = await lambda
.invoke({
FunctionName: process.env.NewVersion,
Payload: JSON.stringify({ test: true }),
})
.promise();
// 테스트 성공!
await codedeploy
.putLifecycleEventHookExecutionStatus({
deploymentId,
lifecycleEventHookExecutionId,
status: "Succeeded",
})
.promise();
} catch (error) {
// 테스트 실패 → 배포 중단
await codedeploy
.putLifecycleEventHookExecutionStatus({
deploymentId,
lifecycleEventHookExecutionId,
status: "Failed",
})
.promise();
}
};7. SAM 로컬 테스트
🤔 로컬에서 테스트할 수 있나요?
비유로 이해하기: 배포하기 전에 내 컴퓨터에서 미리 테스트!
- Lambda를 AWS에 배포하지 않고 로컬에서 실행
- API Gateway도 로컬에서 에뮬레이션
로컬 테스트 명령어
1️⃣ Lambda 함수 한 번 실행
# 기본 실행
sam local invoke MyFunction
# 이벤트 데이터와 함께 실행
sam local invoke MyFunction -e events/event.json
# 환경 변수 파일과 함께
sam local invoke MyFunction --env-vars env.json2️⃣ Lambda 로컬 엔드포인트 (지속 실행)
# Lambda 로컬 서버 시작
sam local start-lambda
# 다른 터미널에서 AWS CLI로 호출
aws lambda invoke \
--function-name MyFunction \
--endpoint-url http://127.0.0.1:3001 \
--payload '{"key": "value"}' \
response.json3️⃣ API Gateway 로컬 실행
# API Gateway 로컬 서버 시작
sam local start-api
# 브라우저 또는 curl로 테스트
curl http://127.0.0.1:3000/hello┌─────────────────────────────────────────────────────────────────┐
│ sam local start-api │
│ │
│ $ sam local start-api │
│ Mounting MyFunction at http://127.0.0.1:3000/hello [GET] │
│ Starting local HTTP server... │
│ │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ 브라우저 │─────→│ 로컬 API │ │
│ │ localhost:3000 │ │ Gateway │ │
│ └────────────────┘ └───────┬────────┘ │
│ │ │
│ ↓ │
│ ┌────────────────┐ │
│ │ Docker 컨테이너 │ │
│ │ (Lambda 실행) │ │
│ └────────────────┘ │
│ │
│ ⚠️ Docker가 설치되어 있어야 함! │
│ │
└─────────────────────────────────────────────────────────────────┘4️⃣ 이벤트 생성
# S3 PUT 이벤트 생성
sam local generate-event s3 put --bucket my-bucket --key test.txt
# API Gateway 이벤트 생성
sam local generate-event apigateway aws-proxy --path /hello --method GET
# DynamoDB Stream 이벤트 생성
sam local generate-event dynamodb update
# 이벤트를 Lambda에 바로 전달
sam local generate-event s3 put --bucket my-bucket --key test.txt | \
sam local invoke MyFunction -e -지원하는 이벤트 소스
| 소스 | 명령어 예시 |
|---|---|
| S3 | generate-event s3 put |
| API Gateway | generate-event apigateway aws-proxy |
| SNS | generate-event sns notification |
| SQS | generate-event sqs receive-message |
| DynamoDB | generate-event dynamodb update |
| Kinesis | generate-event kinesis get-records |
| CloudWatch | generate-event cloudwatch scheduled-event |
8. SAM 다중 환경 설정
🤔 개발/운영 환경을 어떻게 나누나요?
samconfig.toml 사용
# samconfig.toml
# 기본 설정 (sam deploy 시 사용)
[default.deploy.parameters]
stack_name = "my-app-prod"
region = "ap-northeast-2"
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
# 개발 환경 설정
[dev.deploy.parameters]
stack_name = "my-app-dev"
region = "ap-northeast-2"
capabilities = "CAPABILITY_IAM"
confirm_changeset = false
parameter_overrides = "Environment=dev"
# 스테이징 환경 설정
[staging.deploy.parameters]
stack_name = "my-app-staging"
region = "ap-northeast-2"
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
parameter_overrides = "Environment=staging"
# 프로덕션 환경 설정
[prod.deploy.parameters]
stack_name = "my-app-prod"
region = "ap-northeast-2"
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
parameter_overrides = "Environment=prod"환경별 배포
# 개발 환경 배포
sam deploy --config-env dev
# 스테이징 환경 배포
sam deploy --config-env staging
# 프로덕션 환경 배포
sam deploy --config-env prod템플릿에서 환경 변수 사용
# template.yaml
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- prod
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
Environment:
Variables:
ENV: !Ref Environment
TABLE_NAME: !Sub "${Environment}-my-table"9. SAM 실전 예시
완전한 SAM 템플릿 예시
# template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: My Serverless API
# 파라미터
Parameters:
Environment:
Type: String
Default: dev
# 전역 설정
Globals:
Function:
Timeout: 30
Runtime: nodejs18.x
MemorySize: 256
Environment:
Variables:
TABLE_NAME: !Ref MyTable
# 리소스
Resources:
# API Gateway
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: !Ref Environment
Cors:
AllowMethods: "'GET,POST,PUT,DELETE,OPTIONS'"
AllowHeaders: "'Content-Type,Authorization'"
AllowOrigin: "'*'"
# Lambda 함수
GetItemsFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/getItems.handler
CodeUri: .
Policies:
- DynamoDBReadPolicy:
TableName: !Ref MyTable
Events:
GetItems:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /items
Method: GET
# CodeDeploy 설정
AutoPublishAlias: live
DeploymentPreference:
Type: Canary10Percent5Minutes
Alarms:
- !Ref GetItemsAlarm
CreateItemFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/createItem.handler
CodeUri: .
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref MyTable
Events:
CreateItem:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /items
Method: POST
# DynamoDB 테이블
MyTable:
Type: AWS::Serverless::SimpleTable
Properties:
TableName: !Sub "${Environment}-items"
PrimaryKey:
Name: id
Type: String
# CloudWatch Alarm
GetItemsAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: GetItems function errors
Namespace: AWS/Lambda
MetricName: Errors
Dimensions:
- Name: FunctionName
Value: !Ref GetItemsFunction
Statistic: Sum
Period: 60
EvaluationPeriods: 1
Threshold: 1
ComparisonOperator: GreaterThanThreshold
# 출력
Outputs:
ApiUrl:
Description: API Gateway URL
Value: !Sub "https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/${Environment}/"
TableName:
Description: DynamoDB Table Name
Value: !Ref MyTable프로젝트 구조
my-sam-project/
├── template.yaml # SAM 템플릿
├── samconfig.toml # 환경별 설정
├── package.json
├── src/
│ └── handlers/
│ ├── getItems.js # GET /items
│ └── createItem.js # POST /items
├── events/
│ ├── getItems.json # 테스트 이벤트
│ └── createItem.json
└── tests/
└── unit/
└── handlers.test.js
핵심 요약
SAM CLI 명령어 요약
| 명령어 | 용도 |
|---|---|
sam init | 프로젝트 초기화 |
sam build | 빌드 |
sam deploy | 배포 (CloudFormation) |
sam sync | 빠른 동기화 (개발용) |
sam sync --watch | 파일 변경 감지 + 자동 동기화 |
sam local invoke | Lambda 로컬 실행 |
sam local start-api | API Gateway 로컬 실행 |
sam local generate-event | 테스트 이벤트 생성 |
sam logs | CloudWatch 로그 조회 |
sam delete | 스택 삭제 |
SAM 리소스 타입
| SAM 타입 | 생성되는 것 |
|---|---|
AWS::Serverless::Function | Lambda + IAM Role |
AWS::Serverless::Api | API Gateway REST API |
AWS::Serverless::HttpApi | API Gateway HTTP API |
AWS::Serverless::SimpleTable | DynamoDB |
배포 전략
| 전략 | 설명 |
|---|---|
| AllAtOnce | 즉시 전환 |
| Canary | X% 먼저, 대기, 나머지 |
| Linear | 일정 간격으로 X%씩 |
시험 포인트 체크리스트
- SAM Transform:
AWS::Serverless-2016-10-31 - SAM은 CloudFormation의 확장 (모든 CF 기능 사용 가능)
-
sam sync --watch: 파일 변경 감지 + 자동 동기화 - Policy Templates: S3ReadPolicy, DynamoDBCrudPolicy 등
- AutoPublishAlias: 자동으로 버전 생성 + Alias 연결
- DeploymentPreference: Canary, Linear, AllAtOnce
-
sam local start-api: API Gateway 로컬 에뮬레이션 -
sam local generate-event: 테스트 이벤트 생성 - samconfig.toml: 환경별 설정 파일
TypeScript/React 개발자를 위한 SAM 활용:
프로젝트 초기화:
sam init --runtime nodejs18.x --app-template hello-world-typescript개발 워크플로우:
# 1. 로컬에서 API 테스트
sam local start-api
# 2. 개발 중 자동 동기화
sam sync --watch --config-env dev
# 3. 프로덕션 배포
sam deploy --config-env prod이 조합으로 빠르고 안전한 서버리스 개발을 할 수 있어요! 🙂