본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 19. · 4 Views
SAM으로 배포 자동화 완벽 가이드
AWS SAM을 활용한 서버리스 애플리케이션 배포 자동화를 초급 개발자도 쉽게 이해할 수 있도록 실무 중심으로 설명합니다. 설치부터 배포, 테스트까지 단계별로 안내합니다.
목차
1. SAM이란 무엇인가
김개발 씨는 Lambda 함수를 AWS 콘솔에서 직접 만들고 배포하고 있었습니다. 함수가 하나둘 늘어날 때마다 설정을 일일이 클릭하는 것이 너무 번거로웠습니다.
그때 선배 박시니어 씨가 다가와 말했습니다. "SAM 쓰면 한 번에 배포할 수 있어요."
간단한 Lambda 함수 예제 Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: Handler: app.lambda_handler Runtime: python3.9 # 코드가 있는 디렉토리를 지정합니다 CodeUri: hello_world/ # API Gateway 이벤트 연결 Events: HelloWorld: Type: Api Properties: Path: /hello Method: get
다음 코드를 살펴봅시다.
# template.yaml - SAM 템플릿 예제
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
김개발 씨는 입사 2개월 차 백엔드 개발자입니다. 최근 회사에서 Lambda를 활용한 API를 개발하게 되었는데, 문제가 생겼습니다.
Lambda 함수를 하나 만들 때마다 AWS 콘솔에 들어가서 함수를 생성하고, 권한을 설정하고, API Gateway를 연결하고, 환경변수를 입력해야 했습니다. 처음에는 함수가 두세 개라서 괜찮았습니다.
하지만 프로젝트가 커지면서 함수가 열 개를 넘어가자 상황이 달라졌습니다. "이렇게 하나하나 클릭하다가는 언제 개발을 하나..." 김개발 씨는 한숨을 쉬었습니다.
바로 그때 선배 박시니어 씨가 모니터를 보더니 말했습니다. "아직도 콘솔에서 수작업으로 하세요?
SAM 쓰면 편한데." SAM이란 무엇일까요? SAM은 Serverless Application Model의 약자입니다. 쉽게 비유하자면, 마치 레고 조립 설명서와 같습니다.
설명서에 "이 블록을 여기에, 저 블록을 저기에"라고 적어두면, 레고가 알아서 완성되는 것처럼, SAM 템플릿에 "Lambda 함수는 이렇게, API Gateway는 저렇게"라고 작성하면 AWS가 알아서 인프라를 만들어줍니다. 더 정확히 말하면, SAM은 AWS CloudFormation의 확장판입니다.
CloudFormation도 인프라를 코드로 관리하는 도구지만, 서버리스 애플리케이션을 만들려면 코드가 너무 길고 복잡해집니다. SAM은 이를 간소화해서 몇 줄의 코드로 같은 작업을 할 수 있게 해줍니다.
SAM이 없던 시절에는 어땠을까요? 예전에는 개발자들이 Lambda 함수를 배포할 때마다 직접 AWS 콘솔에 들어가야 했습니다. 함수를 만들고, IAM 역할을 설정하고, 트리거를 연결하고, 환경변수를 입력하는 과정을 매번 반복했습니다.
실수하기도 쉬웠습니다. 개발 환경과 운영 환경의 설정이 달라서 버그가 발생하는 일도 흔했습니다.
더 큰 문제는 팀 협업이었습니다. 한 개발자가 콘솔에서 설정을 바꾸면, 다른 개발자는 그 사실을 모를 수 있었습니다.
버전 관리도 불가능했습니다. "누가 언제 뭘 바꿨지?"라는 질문에 답하기 어려웠습니다.
바로 이런 문제를 해결하기 위해 SAM이 등장했습니다. SAM을 사용하면 **Infrastructure as Code(IaC)**가 가능해집니다. 모든 인프라 설정을 코드로 작성하고 Git에 저장할 수 있습니다.
코드 리뷰도 가능하고, 변경 이력도 추적할 수 있습니다. 무엇보다 한 번의 명령어로 전체 애플리케이션을 배포할 수 있다는 큰 이점이 있습니다.
또한 SAM은 로컬 테스트도 지원합니다. AWS에 배포하기 전에 내 컴퓨터에서 Lambda 함수를 실행해볼 수 있습니다.
이는 개발 속도를 크게 향상시킵니다. 위의 코드를 살펴보겠습니다. 첫 줄의 Transform: AWS::Serverless-2016-10-31이 핵심입니다.
이 한 줄이 일반 CloudFormation 템플릿을 SAM 템플릿으로 변환해줍니다. 다음으로 Resources 섹션에서 AWS::Serverless::Function 타입을 사용합니다.
이것이 Lambda 함수를 정의하는 간소화된 방법입니다. Events 부분을 보면 Type: Api라고 되어 있습니다.
단 세 줄로 API Gateway를 생성하고 Lambda 함수와 연결합니다. CloudFormation으로 같은 작업을 하려면 수십 줄의 코드가 필요합니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 전자상거래 플랫폼을 개발한다고 가정해봅시다. 상품 조회, 주문 생성, 결제 처리 등 여러 Lambda 함수가 필요합니다.
SAM을 활용하면 하나의 템플릿 파일에 모든 함수와 API를 정의하고, sam deploy 한 번으로 전체 시스템을 배포할 수 있습니다. 넷플릭스, Airbnb 등 많은 기업에서 이런 패턴을 적극적으로 사용하고 있습니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 SAM 템플릿에 너무 많은 리소스를 넣는 것입니다. 한 템플릿에 수십 개의 Lambda 함수를 정의하면 관리가 어려워집니다.
따라서 기능별로 템플릿을 분리하는 것이 좋습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 눈이 반짝였습니다.
"그럼 제가 만든 열 개의 함수를 하나의 파일로 관리할 수 있다는 거네요?" "맞아요. 그리고 Git에 올려서 버전 관리도 하고, 팀원들과 협업도 할 수 있죠." SAM을 제대로 이해하면 서버리스 애플리케이션을 훨씬 효율적으로 관리할 수 있습니다.
여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.
실전 팁
💡 - SAM은 CloudFormation을 기반으로 하므로, CloudFormation 문법도 함께 사용할 수 있습니다
- 템플릿 파일은 YAML 또는 JSON 형식으로 작성할 수 있지만, YAML이 더 읽기 쉽습니다
- 공식 문서에서 제공하는 예제 템플릿을 활용하면 빠르게 시작할 수 있습니다
2. SAM CLI 설치
SAM을 사용하려면 먼저 SAM CLI를 설치해야 합니다. 김개발 씨는 맥을 사용하고 있었는데, 선배가 "Homebrew로 설치하면 간단해요"라고 알려주었습니다.
과연 얼마나 간단할까요?
SAM CLI는 SAM 애플리케이션을 개발하고 배포하는 데 필요한 명령줄 도구입니다. 마치 Git을 사용하려면 git 명령어가 필요한 것처럼, SAM도 전용 CLI가 필요합니다.
운영체제별로 설치 방법이 다르며, 설치 후에는 AWS 자격증명 설정도 필요합니다.
다음 코드를 살펴봅시다.
# macOS에서 Homebrew로 설치
brew tap aws/tap
brew install aws-sam-cli
# 설치 확인
sam --version
# AWS CLI 설치 (아직 없다면)
brew install awscli
# AWS 자격증명 설정
aws configure
# AWS Access Key ID를 입력합니다
# AWS Secret Access Key를 입력합니다
# Default region name: ap-northeast-2 (서울 리전)
# Default output format: json
# 설치 확인을 위한 샘플 앱 생성
sam init
김개발 씨는 SAM에 대해 알게 된 후 바로 설치하기로 마음먹었습니다. 하지만 어디서부터 시작해야 할지 막막했습니다.
"CLI 도구는 어떻게 설치하지? AWS 설정은 또 어떻게 하지?" 박시니어 씨가 옆에서 말했습니다.
"운영체제가 뭐예요?" "맥입니다." "그럼 Homebrew로 설치하면 2분 안에 끝나요." SAM CLI란 무엇일까요? SAM CLI는 Command Line Interface의 약자로, 터미널에서 SAM 관련 명령어를 실행할 수 있게 해주는 도구입니다. 쉽게 비유하자면, 마치 요리를 할 때 필요한 주방 도구와 같습니다.
레시피(템플릿)만 있어도 요리는 할 수 있지만, 칼과 도마(CLI)가 있어야 훨씬 편리합니다. SAM CLI는 단순히 배포만 하는 것이 아닙니다.
프로젝트 초기화, 로컬 테스트, 빌드, 배포, 로그 확인 등 개발 전 과정을 지원합니다. 설치 방법은 운영체제마다 다릅니다. macOS 사용자라면 Homebrew가 가장 간단합니다.
위 코드처럼 두 줄만 입력하면 설치가 완료됩니다. Windows 사용자는 MSI 설치 프로그램을 다운로드하면 됩니다.
Linux 사용자는 pip를 통해 설치하거나 바이너리를 직접 다운로드할 수 있습니다. 김개발 씨는 터미널을 열고 명령어를 입력했습니다.
brew tap aws/tap을 실행하니 AWS의 Homebrew 저장소가 추가되었습니다. 그다음 brew install aws-sam-cli를 실행하자 설치가 시작되었습니다.
설치가 끝나면 반드시 확인해야 합니다. sam --version 명령어를 실행하면 설치된 SAM CLI 버전이 표시됩니다. 만약 "command not found" 에러가 나온다면 설치에 문제가 있는 것입니다.
이때는 터미널을 재시작하거나, PATH 환경변수를 확인해야 합니다. 하지만 SAM CLI만으로는 부족합니다. AWS와 통신하려면 AWS CLI도 필요합니다.
SAM은 내부적으로 AWS CLI를 사용하기 때문입니다. 다행히 설치 방법은 SAM과 비슷합니다.
macOS에서는 brew install awscli로 간단히 설치할 수 있습니다. 가장 중요한 단계는 AWS 자격증명 설정입니다. aws configure 명령어를 실행하면 네 가지를 물어봅니다.
첫째, Access Key ID입니다. 이것은 AWS 콘솔의 IAM에서 생성할 수 있습니다.
둘째, Secret Access Key입니다. 이것은 Access Key를 생성할 때 한 번만 보여주므로, 반드시 안전한 곳에 저장해야 합니다.
셋째, Region입니다. 한국에서 서비스한다면 ap-northeast-2(서울 리전)를 입력하는 것이 좋습니다.
넷째, Output format입니다. json을 선택하면 결과가 JSON 형식으로 표시됩니다.
김개발 씨는 조심스럽게 자격증명을 입력했습니다. "이 키를 절대 Git에 올리면 안 된다고 들었는데..." 맞습니다.
Access Key가 노출되면 누구나 여러분의 AWS 계정을 사용할 수 있습니다. 따라서 .gitignore에 ~/.aws/credentials를 추가하거나, 환경변수로 관리하는 것이 안전합니다.
설치가 제대로 되었는지 확인해봅시다. sam init 명령어를 실행하면 샘플 애플리케이션을 생성할 수 있습니다. 몇 가지 질문에 답하면 SAM이 자동으로 프로젝트 구조를 만들어줍니다.
이것은 마치 create-react-app이나 flutter create와 비슷합니다. 실제 회사에서는 어떻게 관리할까요? 대부분의 팀에서는 개발자마다 개인 AWS 계정을 사용하지 않습니다.
대신 IAM 사용자를 생성하고, 필요한 권한만 부여합니다. 예를 들어 개발자에게는 Lambda와 API Gateway만 접근 권한을 주고, S3나 RDS는 제한하는 식입니다.
또한 회사에서는 프로필 기능을 활용합니다. aws configure --profile dev처럼 프로필을 지정하면, 개발 환경과 운영 환경의 자격증명을 분리할 수 있습니다.
배포할 때는 sam deploy --profile prod처럼 프로필을 선택할 수 있습니다. 주의할 점이 있습니다. 초보 개발자들이 흔히 하는 실수는 루트 계정의 Access Key를 사용하는 것입니다.
루트 계정은 모든 권한을 가지고 있어서, 키가 노출되면 큰 피해를 입을 수 있습니다. 따라서 반드시 IAM 사용자를 만들어서 사용해야 합니다.
또 다른 실수는 리전을 잘못 설정하는 것입니다. 미국 리전(us-east-1)으로 설정하면 한국에서 접속할 때 속도가 느립니다.
서비스 대상 지역에 맞는 리전을 선택해야 합니다. 김개발 씨는 모든 설정을 마쳤습니다. "됐다!" 김개발 씨는 sam --version을 실행해서 버전이 표시되는 것을 확인했습니다.
이제 본격적으로 SAM을 사용할 준비가 끝났습니다. SAM CLI 설치는 첫 단추입니다.
제대로 설치하고 설정해두면, 앞으로의 개발이 훨씬 수월해집니다. 여러분도 지금 바로 설치해보세요.
실전 팁
💡 - AWS Access Key는 절대 코드에 하드코딩하지 말고, 환경변수나 AWS Secrets Manager를 사용하세요
- 여러 프로젝트를 관리한다면 AWS CLI 프로필 기능을 적극 활용하세요
- SAM CLI는 정기적으로 업데이트되므로,
brew upgrade aws-sam-cli로 최신 버전을 유지하세요
3. template yaml 작성
설치를 마친 김개발 씨는 본격적으로 SAM 템플릿을 작성하기 시작했습니다. "YAML 파일 하나면 된다는데, 뭘 어떻게 써야 하지?" 막막했던 그때, 선배가 "기본 구조만 알면 쉬워요"라고 말했습니다.
"API Gateway 엔드포인트" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
다음 코드를 살펴봅시다.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
김개발 씨는 빈 파일을 열고 무엇을 써야 할지 고민했습니다. "Lambda 함수를 만들려면 뭘 적어야 하지?
API는 어떻게 연결하지?" 막막했습니다. 박시니어 씨가 화면을 보더니 말했습니다.
"template.yaml은 세 부분만 기억하면 돼요. Transform, Globals, Resources." template.yaml이란 무엇일까요? template.yaml은 SAM 템플릿 파일의 기본 이름입니다.
다른 이름으로 저장해도 되지만, 관례적으로 template.yaml을 사용합니다. 이 파일은 YAML 형식으로 작성되며, AWS 리소스를 선언적으로 정의합니다.
선언적이라는 것은 "어떻게 만들라"가 아니라 "무엇을 만들라"고 지시한다는 뜻입니다. 마치 레스토랑에서 "스파게티 만드는 방법"을 설명하는 것이 아니라 "스파게티 하나요"라고 주문하는 것과 같습니다.
파일의 첫 부분은 메타데이터입니다. AWSTemplateFormatVersion은 CloudFormation 템플릿의 버전을 나타냅니다. 거의 모든 템플릿에서 2010-09-09를 사용합니다.
날짜가 이상하게 보이지만, 이것은 CloudFormation이 처음 출시된 날짜입니다. 다음으로 Transform 부분이 핵심입니다.
AWS::Serverless-2016-10-31이라는 값은 이 템플릿이 SAM 템플릿임을 AWS에 알려줍니다. 이 한 줄이 있어야 AWS::Serverless::Function 같은 간소화된 리소스 타입을 사용할 수 있습니다.
Globals 섹션은 중복을 줄여줍니다. Lambda 함수가 여러 개 있을 때, 모든 함수에 공통으로 적용할 설정을 Globals에 정의하면 편리합니다. 예를 들어 모든 함수의 타임아웃을 10초로 설정하고, Python 3.9를 사용한다면, Globals에 한 번만 작성하면 됩니다.
김개발 씨는 "아, 그럼 매번 Runtime을 적지 않아도 되는 거네요?"라고 물었습니다. 박시니어 씨가 고개를 끄덕였습니다.
"맞아요. 하지만 특정 함수만 다른 설정을 사용하고 싶다면, 해당 함수의 Properties에 다시 정의하면 덮어씌워져요." Resources 섹션이 가장 중요합니다. 여기에 실제로 생성할 AWS 리소스를 정의합니다.
Lambda 함수, DynamoDB 테이블, S3 버킷 등 모든 것이 Resources에 들어갑니다. 위 코드에서 GetProductFunction은 Lambda 함수의 논리적 이름입니다.
이것은 템플릿 내에서 이 리소스를 참조할 때 사용합니다. 실제 AWS에 생성되는 함수 이름은 다르게 지정됩니다.
Type: AWS::Serverless::Function은 이것이 SAM의 간소화된 Lambda 함수 정의임을 나타냅니다. CodeUri는 함수 코드가 있는 디렉토리를 지정합니다.
Handler는 실제로 실행될 함수를 지정합니다. Events 부분이 흥미롭습니다. 여기서 Lambda 함수의 트리거를 정의합니다.
Type: Api는 API Gateway를 자동으로 생성하고 연결하라는 의미입니다. Path와 Method로 엔드포인트를 지정하면, SAM이 알아서 REST API를 만들어줍니다.
만약 CloudFormation으로 같은 작업을 하려면 API Gateway, Stage, Deployment, Integration, Method 등을 일일이 정의해야 합니다. 수십 줄의 코드가 필요합니다.
하지만 SAM에서는 단 다섯 줄이면 됩니다. Policies는 권한을 관리합니다. Lambda 함수가 DynamoDB에 접근하려면 IAM 권한이 필요합니다.
DynamoDBReadPolicy를 사용하면 SAM이 자동으로 적절한 IAM 역할을 생성하고 부여합니다. 보안을 신경 쓰면서도 코드는 간단하게 유지할 수 있습니다.
DynamoDB 테이블도 템플릿에 정의할 수 있습니다. AWS::Serverless::SimpleTable은 간단한 DynamoDB 테이블을 생성합니다. Primary Key만 지정하면 되므로, 빠르게 프로토타입을 만들 때 유용합니다.
더 복잡한 설정이 필요하면 AWS::DynamoDB::Table 타입을 사용하면 됩니다. Outputs 섹션은 배포 후 정보를 보여줍니다. 배포가 완료되면 API 엔드포인트 URL이 필요합니다.
Outputs에 정의하면 배포 후 터미널에 출력됩니다. !Sub는 CloudFormation의 내장 함수로, 변수를 치환해줍니다.
실무에서는 어떻게 사용할까요? 대부분의 프로젝트에서는 환경별로 다른 설정을 사용합니다. 개발 환경에서는 Lambda 메모리를 128MB로 설정하지만, 운영 환경에서는 512MB로 늘립니다.
이런 경우 Parameters를 사용하면 됩니다. 또한 여러 개의 템플릿을 중첩(Nested)해서 사용할 수도 있습니다.
예를 들어 인증 시스템을 별도 템플릿으로 분리하고, 메인 템플릿에서 참조하는 식입니다. 주의할 점이 있습니다. 초보 개발자들이 흔히 하는 실수는 CodeUri 경로를 잘못 지정하는 것입니다.
상대 경로로 작성해야 하며, template.yaml이 있는 디렉토리를 기준으로 합니다. 절대 경로를 사용하면 다른 개발자의 컴퓨터에서 동작하지 않습니다.
또 다른 실수는 환경변수에 민감한 정보를 넣는 것입니다. 데이터베이스 비밀번호 같은 정보는 template.yaml에 직접 작성하면 안 됩니다.
대신 AWS Secrets Manager나 Parameter Store를 사용해야 합니다. 김개발 씨는 첫 템플릿을 완성했습니다. "생각보다 간단한데요?" 박시니어 씨가 미소를 지었습니다.
"그렇죠? SAM의 장점은 바로 이 간결함이에요.
처음에는 어려워 보이지만, 구조만 이해하면 금방 익숙해져요." template.yaml을 제대로 작성하면 인프라 전체를 코드로 관리할 수 있습니다. 버전 관리도 되고, 팀원들과 협업도 쉬워집니다.
여러분도 작은 템플릿부터 시작해보세요.
실전 팁
💡 - SAM 공식 문서에 다양한 예제 템플릿이 있으니 참고하세요
- YAML 문법에서 들여쓰기는 탭이 아니라 스페이스 2칸을 사용하세요
- VSCode에 AWS Toolkit 확장을 설치하면 템플릿 자동 완성과 검증이 가능합니다
4. sam build와 deploy
템플릿을 작성한 김개발 씨는 이제 배포만 하면 됐습니다. "배포는 어떻게 하나요?" 선배가 답했습니다.
"sam build로 빌드하고, sam deploy로 배포하면 돼요. 두 단계만 기억하세요."
sam build는 Lambda 함수의 코드와 의존성을 패키징하는 명령어입니다. 마치 앱을 배포하기 전에 컴파일하는 것처럼, SAM도 빌드 과정이 필요합니다.
sam deploy는 빌드된 애플리케이션을 AWS에 실제로 배포합니다. 첫 배포 시에는 --guided 옵션을 사용하면 대화형으로 설정할 수 있습니다.
다음 코드를 살펴봅시다.
# 1단계: 빌드 - 의존성 설치 및 패키징
sam build
# Python의 경우 requirements.txt를 자동으로 읽어서 설치합니다
# .aws-sam/build 디렉토리에 결과물이 생성됩니다
# 2단계: 첫 배포 (대화형 설정)
sam deploy --guided
# Stack Name: my-shopping-api
# AWS Region: ap-northeast-2
# Confirm changes before deploy: Y
# Allow SAM CLI IAM role creation: Y
# Save arguments to configuration file: Y
# 이후 배포는 간단하게
sam deploy
# 특정 리전에 배포
sam deploy --region us-east-1
# 스택 삭제 (모든 리소스 제거)
sam delete
김개발 씨는 template.yaml 작성을 마치고 흥분했습니다. "이제 배포만 하면 되는 거네요!" 하지만 어떤 명령어를 실행해야 할지 몰랐습니다.
박시니어 씨가 설명했습니다. "SAM 배포는 두 단계예요.
먼저 빌드하고, 그다음 배포하면 됩니다." sam build가 왜 필요할까요? Lambda 함수는 단순히 코드 파일만 업로드하면 되는 것이 아닙니다. Python이라면 requests 같은 외부 라이브러리를 사용할 수 있는데, 이런 의존성도 함께 패키징해야 합니다.
마치 앱을 빌드할 때 모든 라이브러리를 포함해서 실행 파일을 만드는 것과 같습니다. sam build 명령어는 각 Lambda 함수의 디렉토리로 이동해서 requirements.txt(Python), package.json(Node.js), go.mod(Go) 등을 읽고 의존성을 설치합니다.
김개발 씨는 터미널에서 프로젝트 루트 디렉토리로 이동했습니다. 그리고 sam build를 실행했습니다.
화면에 메시지가 쏟아지기 시작했습니다. 빌드 과정에서 무슨 일이 일어날까요? SAM은 template.yaml을 읽어서 모든 Lambda 함수를 찾습니다.
그리고 각 함수의 CodeUri에 지정된 디렉토리로 이동합니다. Python 함수라면 pip install -r requirements.txt를 실행해서 라이브러리를 설치합니다.
설치된 코드와 라이브러리는 .aws-sam/build 디렉토리에 복사됩니다. 이 디렉토리는 실제로 AWS에 업로드될 최종 형태입니다.
함수별로 별도 디렉토리가 생성되며, 각각 독립적으로 패키징됩니다. 빌드가 완료되면 "Build Succeeded"라는 메시지가 표시됩니다.
만약 에러가 발생한다면, 대부분 의존성 문제입니다. requirements.txt에 적힌 라이브러리가 설치되지 않거나, 버전 충돌이 있을 수 있습니다.
이제 배포할 차례입니다. sam deploy --guided를 실행하면 대화형 배포가 시작됩니다. SAM이 몇 가지 질문을 합니다.
첫 번째는 Stack Name입니다. 이것은 CloudFormation 스택의 이름으로, 나중에 리소스를 관리할 때 사용합니다.
예를 들어 my-shopping-api처럼 프로젝트 이름을 사용하면 좋습니다. 두 번째는 AWS Region입니다.
어느 리전에 배포할지 선택합니다. 한국 사용자를 대상으로 한다면 ap-northeast-2(서울)을 선택하세요.
미국 사용자라면 us-east-1(버지니아) 또는 us-west-2(오레곤)가 좋습니다. 세 번째는 Confirm changes before deploy입니다.
배포하기 전에 변경사항을 확인할 것인지 묻습니다. 처음에는 Y를 선택해서 어떤 리소스가 생성되는지 확인하는 것이 좋습니다.
네 번째는 Allow SAM CLI IAM role creation입니다. Lambda 함수에 필요한 IAM 역할을 자동으로 생성할 것인지 묻습니다.
대부분의 경우 Y를 선택하면 됩니다. 마지막으로 Save arguments to configuration file을 묻습니다.
Y를 선택하면 samconfig.toml 파일이 생성되고, 다음 배포부터는 sam deploy만 입력하면 자동으로 같은 설정을 사용합니다. 배포 과정은 어떻게 진행될까요? SAM은 먼저 빌드된 코드를 S3 버킷에 업로드합니다.
이 버킷은 배포용으로 자동 생성됩니다. 그다음 CloudFormation을 호출해서 template.yaml에 정의된 리소스를 생성합니다.
화면에는 진행 상황이 실시간으로 표시됩니다. CREATE_IN_PROGRESS, CREATE_COMPLETE 같은 상태가 보입니다.
모든 리소스가 생성되면 Successfully created/updated stack이라는 메시지가 나타납니다. 김개발 씨는 화면을 지켜보며 긴장했습니다.
"혹시 에러가 나면 어떡하지?" 다행히 모든 과정이 순조롭게 진행되었습니다. 마지막에 Outputs 섹션에 정의한 API URL이 표시되었습니다.
배포가 완료된 후 확인해야 할 것들이 있습니다. AWS 콘솔에 로그인해서 Lambda 콘솔로 이동하면, 새로 생성된 함수를 볼 수 있습니다. 함수 이름은 스택이름-함수논리이름-랜덤문자열 형식입니다.
API Gateway 콘솔에서는 자동 생성된 REST API를 확인할 수 있습니다. 두 번째 배포부터는 훨씬 간단합니다. 코드를 수정한 후 다시 배포하려면 sam build && sam deploy 두 명령어만 실행하면 됩니다.
samconfig.toml에 설정이 저장되어 있어서 질문을 다시 받지 않습니다. 실무에서는 어떻게 배포할까요? 대부분의 회사에서는 CI/CD 파이프라인을 구축합니다.
GitHub Actions, Jenkins, GitLab CI 등을 사용해서, 코드를 푸시하면 자동으로 빌드하고 배포합니다. SAM CLI는 스크립트에서 실행하기 쉽게 설계되어 있어서, CI/CD와 잘 통합됩니다.
또한 환경별 배포도 중요합니다. 개발 환경, 스테이징 환경, 운영 환경을 분리해서 관리합니다.
이때 --config-env 옵션을 사용하면 samconfig.toml에 여러 환경 설정을 저장할 수 있습니다. 주의할 점이 있습니다. 초보 개발자들이 흔히 하는 실수는 빌드 없이 배포하는 것입니다.
코드를 수정한 후 sam deploy만 실행하면, 이전 빌드 결과가 배포됩니다. 반드시 sam build를 먼저 실행해야 합니다.
또 다른 실수는 스택 이름을 잘못 지정하는 것입니다. 같은 스택 이름으로 다시 배포하면 기존 리소스가 업데이트됩니다.
새로운 환경을 만들려면 다른 스택 이름을 사용해야 합니다. 배포를 취소하고 싶다면? sam delete 명령어를 실행하면 CloudFormation 스택과 모든 리소스가 삭제됩니다.
단, S3 버킷에 파일이 있으면 삭제가 실패할 수 있으므로, 먼저 버킷을 비워야 합니다. 김개발 씨는 첫 배포에 성공했습니다. "와, 정말 간단하네요!" API 엔드포인트를 브라우저에 입력하자, Lambda 함수가 응답을 반환했습니다.
불과 몇 분 만에 서버리스 API를 구축한 것입니다. sam build와 sam deploy만 기억하면 SAM의 기본은 끝입니다.
나머지는 실습하면서 자연스럽게 익히게 됩니다. 여러분도 지금 바로 배포해보세요.
실전 팁
💡 - sam build 시 --use-container 옵션을 사용하면 Docker 컨테이너 안에서 빌드합니다. 로컬 환경과 AWS 환경의 차이를 줄일 수 있습니다
- sam deploy --no-confirm-changeset을 사용하면 확인 없이 바로 배포됩니다. 자동화 스크립트에 유용합니다
- CloudFormation 콘솔에서 스택 이벤트를 확인하면 배포 과정을 자세히 볼 수 있습니다
5. 로컬 테스트
배포에 성공한 김개발 씨는 기뻤지만, 곧 문제를 발견했습니다. 코드를 수정할 때마다 AWS에 배포해야 했고, 테스트하는 데 시간이 오래 걸렸습니다.
"로컬에서 테스트할 방법은 없나요?" 선배가 답했습니다. "sam local이 있어요."
sam local은 로컬 환경에서 Lambda 함수를 실행하고 테스트할 수 있는 기능입니다. 마치 로컬 개발 서버를 띄우는 것처럼, API Gateway를 시뮬레이션하고 Lambda 함수를 호출할 수 있습니다.
Docker를 사용하므로 AWS 환경과 거의 동일한 조건에서 테스트할 수 있습니다.
다음 코드를 살펴봅시다.
# API Gateway 시뮬레이션 - 로컬 서버 시작
sam local start-api
# 기본적으로 http://127.0.0.1:3000에서 실행됩니다
# 브라우저나 curl로 테스트할 수 있습니다
# 특정 함수만 직접 호출
sam local invoke GetProductFunction
# 이벤트 데이터를 전달하면서 호출
sam local invoke GetProductFunction -e events/get-product.json
# events/get-product.json 파일 예제
# {
# "pathParameters": {
# "id": "123"
# },
# "httpMethod": "GET"
# }
# 환경변수를 오버라이드하면서 실행
sam local start-api --env-vars env.json
# 디버깅 모드로 실행 (포트 5858에서 디버거 연결 대기)
sam local start-api -d 5858
# 특정 프로필 사용
sam local start-api --profile dev
김개발 씨는 코드를 수정할 때마다 sam build && sam deploy를 실행하고 있었습니다. 간단한 로그 메시지를 추가하는 것조차 배포 과정을 거쳐야 했습니다.
"이렇게 하면 시간이 너무 오래 걸리는데..." 박시니어 씨가 웃으며 말했습니다. "그래서 SAM에는 로컬 테스트 기능이 있어요.
배포 없이 내 컴퓨터에서 바로 실행할 수 있죠." sam local이란 무엇일까요? sam local은 로컬 개발 환경에서 Lambda 함수를 실행하는 도구입니다. 쉽게 비유하자면, 마치 웹 개발에서 npm start로 로컬 서버를 띄우는 것과 같습니다.
차이점은 sam local이 Docker를 사용해서 실제 Lambda 런타임 환경을 재현한다는 것입니다. AWS Lambda는 특정 버전의 Python, Node.js 등을 사용합니다.
여러분의 컴퓨터에 설치된 버전과 다를 수 있습니다. sam local은 Docker 컨테이너 안에서 AWS와 동일한 런타임을 실행하므로, 환경 차이로 인한 문제를 방지합니다.
로컬 API 서버를 시작해봅시다. 김개발 씨는 sam local start-api를 실행했습니다. 잠시 후 "Running on http://127.0.0.1:3000"이라는 메시지가 나타났습니다.
브라우저에서 http://127.0.0.1:3000/products/123에 접속하자, Lambda 함수가 실행되고 결과가 반환되었습니다. "오, 정말 되네요!" 김개발 씨는 신기했습니다.
코드를 수정하고 저장한 후 새로고침하자, 바로 변경사항이 반영되었습니다. 배포 없이 즉시 테스트할 수 있었습니다.
sam local start-api는 어떻게 작동할까요? SAM은 template.yaml을 읽어서 API Gateway 설정을 파악합니다. 어떤 경로(/products/{id})가 어떤 함수(GetProductFunction)와 연결되어 있는지 알 수 있습니다.
그리고 로컬에서 간단한 HTTP 서버를 시작합니다. 요청이 들어오면 해당 경로에 매핑된 Lambda 함수를 찾습니다.
그다음 Docker 컨테이너를 실행하고, 함수 코드를 컨테이너 안에 복사합니다. 마지막으로 함수를 호출하고 결과를 반환합니다.
처음 실행할 때는 Docker 이미지를 다운로드해야 해서 시간이 걸립니다. 하지만 한 번 다운로드하면 캐시되므로, 다음부터는 빠릅니다.
특정 함수만 테스트하고 싶다면? sam local invoke 명령어를 사용하면 API Gateway 없이 함수를 직접 호출할 수 있습니다. 예를 들어 sam local invoke GetProductFunction을 실행하면, 해당 함수가 즉시 실행됩니다.
하지만 Lambda 함수는 보통 이벤트 데이터를 받아서 처리합니다. API Gateway에서 오는 요청은 특정 형식의 JSON으로 변환됩니다.
이런 이벤트를 테스트하려면 JSON 파일을 만들어야 합니다. 김개발 씨는 events 디렉토리를 만들고, get-product.json 파일을 생성했습니다.
그 안에 API Gateway가 보내는 형식의 JSON을 작성했습니다. pathParameters에 id: "123"을 넣어서, 실제 API 요청을 시뮬레이션했습니다.
환경변수는 어떻게 처리할까요? Lambda 함수는 보통 환경변수를 사용합니다. 데이터베이스 주소, API 키 등을 환경변수로 관리합니다.
template.yaml에 환경변수를 정의할 수 있지만, 로컬 테스트에서는 다른 값을 사용하고 싶을 수 있습니다. --env-vars 옵션을 사용하면 JSON 파일로 환경변수를 오버라이드할 수 있습니다.
예를 들어 env.json에 로컬 데이터베이스 주소를 넣고, sam local start-api --env-vars env.json처럼 실행하면 됩니다. 디버깅도 가능할까요? 물론입니다.
-d 옵션으로 디버그 포트를 지정하면, VSCode나 PyCharm 같은 IDE에서 디버거를 연결할 수 있습니다. 중단점을 설정하고, 변수를 확인하고, 단계별로 실행할 수 있습니다.
김개발 씨는 VSCode에서 디버그 설정을 추가했습니다. sam local start-api -d 5858로 실행한 후, VSCode에서 "Attach to SAM CLI"를 선택했습니다.
중단점을 설정하고 요청을 보내자, 정확히 해당 줄에서 실행이 멈췄습니다. 실무에서는 어떻게 활용할까요? 대부분의 개발자는 코드를 작성할 때 로컬 테스트를 많이 사용합니다.
빠른 피드백 루프를 유지할 수 있기 때문입니다. 하지만 로컬 테스트만으로는 부족한 경우도 있습니다.
예를 들어 DynamoDB나 S3와의 연동을 테스트하려면, 실제 AWS 리소스가 필요합니다. 이때는 개발용 AWS 계정에 별도의 스택을 배포해서 테스트하는 것이 좋습니다.
또한 통합 테스트는 로컬에서 하기 어렵습니다. 여러 Lambda 함수가 서로 호출하거나, SQS, SNS 같은 서비스를 사용하는 경우, 전체 시스템을 AWS에 배포해서 테스트해야 합니다.
주의할 점이 있습니다. 초보 개발자들이 흔히 하는 실수는 Docker를 실행하지 않은 채로 sam local을 사용하는 것입니다. sam local은 Docker에 의존하므로, Docker Desktop이나 Docker Engine이 실행 중이어야 합니다.
그렇지 않으면 "Cannot connect to Docker daemon"이라는 에러가 발생합니다. 또 다른 실수는 코드 변경 후 다시 빌드하지 않는 것입니다.
의존성을 추가하거나 template.yaml을 수정했다면, sam build를 다시 실행해야 합니다. 그렇지 않으면 이전 버전의 코드가 실행됩니다.
로컬 테스트의 한계도 알아야 합니다. sam local은 Lambda 런타임은 재현하지만, 네트워크 환경이나 AWS 서비스와의 통신 속도는 다릅니다. 따라서 타임아웃 설정이나 성능 관련 문제는 실제 AWS에서 테스트해야 정확합니다.
또한 IAM 권한도 완벽히 시뮬레이션하지 못합니다. 로컬에서는 AWS CLI의 자격증명을 사용하므로, 실제 Lambda 함수의 역할과 다를 수 있습니다.
김개발 씨는 로컬 테스트의 편리함을 실감했습니다. "이제 배포 시간을 기다릴 필요가 없네요!" 코드를 수정하고 바로 테스트하고, 버그를 찾으면 즉시 고치는 사이클이 가능해졌습니다. 개발 속도가 크게 향상되었습니다.
sam local을 활용하면 개발 생산성이 비약적으로 높아집니다. 배포 없이 빠르게 반복하면서 코드를 개선할 수 있습니다.
여러분도 오늘부터 로컬 테스트를 활용해보세요.
실전 팁
💡 - Docker Desktop의 리소스 설정을 조정해서 sam local 성능을 향상시킬 수 있습니다
- AWS SAM CLI는 핫 리로드를 지원하지 않으므로, 코드 변경 시 함수가 다시 호출될 때 반영됩니다
- sam local generate-event 명령어로 다양한 AWS 서비스의 샘플 이벤트를 생성할 수 있습니다
6. SAM 모범 사례
김개발 씨는 SAM을 사용하면서 점점 복잡한 애플리케이션을 만들게 되었습니다. 함수가 많아지고, 환경도 여러 개로 나뉘었습니다.
"이걸 어떻게 관리해야 하지?" 고민하던 그때, 선배가 "모범 사례를 따르면 훨씬 편해요"라고 조언했습니다.
데이터베이스 접속 정보 SecretString: !Sub | { "username": "admin", "password": "${DBPassword}" }
다음 코드를 살펴봅시다.
# 프로젝트 구조 예제
# my-sam-app/
# ├── template.yaml # 메인 템플릿
# ├── samconfig.toml # 배포 설정
# ├── functions/ # 함수별 디렉토리
# │ ├── get-product/
# │ │ ├── app.py
# │ │ ├── requirements.txt
# │ │ └── tests/
# │ └── create-order/
# │ ├── app.py
# │ └── requirements.txt
# ├── layers/ # 공통 레이어
# │ └── common-libs/
# │ └── python/
# ├── events/ # 테스트 이벤트
# └── tests/ # 통합 테스트
# template.yaml에서 Parameters 사용
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- prod
김개발 씨의 프로젝트는 점점 커졌습니다. Lambda 함수가 열 개를 넘었고, 개발 환경과 운영 환경을 분리해야 했습니다.
함수마다 같은 라이브러리를 반복해서 설치하는 것도 비효율적이었습니다. 박시니어 씨가 김개발 씨의 코드를 보더니 말했습니다.
"이제 프로젝트가 커졌으니, 구조를 좀 정리해야 해요. 모범 사례를 따르면 유지보수가 훨씬 쉬워져요." 프로젝트 구조부터 정리해야 합니다. 모든 코드를 한 디렉토리에 넣으면 관리가 어렵습니다.
함수별로 디렉토리를 나누고, 각 함수는 독립적으로 의존성을 관리하는 것이 좋습니다. 위의 구조처럼 functions/ 디렉토리 아래에 함수별 폴더를 만듭니다.
각 함수 디렉토리에는 코드 파일(app.py), 의존성 파일(requirements.txt), 테스트 파일이 들어갑니다. 이렇게 하면 함수 하나만 수정할 때 다른 함수에 영향을 주지 않습니다.
환경별로 다른 설정을 사용해야 합니다. 개발 환경에서는 Lambda 메모리를 128MB만 사용해도 되지만, 운영 환경에서는 512MB가 필요할 수 있습니다. 로그 레벨도 개발에서는 DEBUG, 운영에서는 INFO가 적절합니다.
이런 차이를 관리하려면 Parameters를 사용합니다. template.yaml 맨 위에 Parameters 섹션을 추가하고, Environment 파라미터를 정의합니다.
그리고 배포할 때 sam deploy --parameter-overrides Environment=prod처럼 값을 전달합니다. Conditions를 활용하면 조건부 설정이 가능합니다. 예를 들어 IsProd라는 조건을 만들어서, 환경이 prod일 때만 특정 값을 사용할 수 있습니다.
!If [IsProd, 512, 128]은 운영 환경이면 512를, 아니면 128을 반환합니다. 김개발 씨는 "이렇게 하면 template.yaml 하나로 모든 환경을 관리할 수 있네요!"라고 감탄했습니다.
박시니어 씨가 고개를 끄덕였습니다. "맞아요.
환경마다 별도의 템플릿을 만들 필요가 없죠." 민감한 정보는 절대 template.yaml에 넣으면 안 됩니다. 데이터베이스 비밀번호, API 키 같은 정보를 템플릿에 직접 작성하면 Git에 노출됩니다. 대신 AWS Secrets Manager나 Systems Manager Parameter Store를 사용해야 합니다.
위 코드처럼 AWS::SecretsManager::Secret 리소스를 정의하면 시크릿을 생성할 수 있습니다. Lambda 함수에서는 환경변수로 시크릿의 ARN을 전달하고, 런타임에 boto3를 사용해서 실제 값을 가져옵니다.
Lambda Layer로 공통 코드를 공유할 수 있습니다. 여러 함수가 같은 라이브러리를 사용한다면, 각 함수마다 설치하는 것은 비효율적입니다. Layer를 사용하면 공통 라이브러리를 한 번만 패키징하고 여러 함수에서 공유할 수 있습니다.
layers/common-libs/python/ 디렉토리에 라이브러리를 설치하면, SAM이 자동으로 Layer로 패키징합니다. 그다음 함수의 Layers 속성에 !Ref CommonLibsLayer를 추가하면, 해당 Layer가 함수에 연결됩니다.
이렇게 하면 배포 패키지 크기도 줄어들고, 라이브러리 업데이트도 한 곳에서 관리할 수 있습니다. 모니터링과 추적도 중요합니다. 운영 환경에서는 Lambda 함수가 얼마나 자주 호출되는지, 에러율은 어떤지 파악해야 합니다.
AWS X-Ray를 활성화하면 함수의 실행 흐름을 추적할 수 있습니다. Tracing: Active로 설정하면 X-Ray가 자동으로 활성화됩니다.
X-Ray 콘솔에서 각 함수의 응답 시간, 에러, 외부 서비스 호출 등을 시각화해서 볼 수 있습니다. CloudWatch Logs도 적극 활용해야 합니다. Lambda 함수는 자동으로 CloudWatch Logs에 로그를 전송합니다.
하지만 로그를 제대로 남기려면 코드에서 logging 모듈을 사용해야 합니다. 단순히 print를 사용하는 것보다 로그 레벨을 지정하고, 구조화된 로그를 남기는 것이 좋습니다.
태그를 일관성 있게 사용하세요. AWS 리소스에는 태그를 붙일 수 있습니다. 프로젝트 이름, 환경, 비용 센터 등을 태그로 관리하면, 나중에 비용 분석이나 리소스 검색이 편리합니다.
Globals 섹션에 공통 태그를 정의하면 모든 함수에 자동으로 적용됩니다. CI/CD 파이프라인을 구축하세요. 수동으로 sam deploy를 실행하는 것은 실수하기 쉽습니다.
GitHub Actions나 AWS CodePipeline을 사용해서 자동화하면, 코드를 푸시할 때마다 자동으로 테스트하고 배포됩니다. GitHub Actions 예제를 만들면, .github/workflows/deploy.yml 파일에 워크플로우를 정의합니다.
테스트를 먼저 실행하고, 성공하면 sam build와 sam deploy를 순차적으로 실행하도록 설정합니다. 테스트를 작성하세요. Lambda 함수도 일반 함수처럼 단위 테스트가 가능합니다.
pytest 같은 프레임워크를 사용해서 핸들러 함수를 테스트합니다. 또한 통합 테스트도 중요합니다.
실제로 API를 호출해서 응답을 확인하는 테스트를 작성하면, 배포 후 문제를 빠르게 발견할 수 있습니다. 비용 최적화도 고려하세요. Lambda는 사용한 만큼만 비용이 발생하지만, 메모리와 타임아웃 설정을 적절히 조정해야 합니다.
필요 이상으로 큰 메모리를 할당하면 비용이 증가합니다. 반대로 너무 작으면 성능이 떨어집니다.
AWS Cost Explorer에서 Lambda 비용을 분석하고, 함수별로 최적의 설정을 찾아야 합니다. 문서화를 습관화하세요. template.yaml에 Description 필드를 빠짐없이 작성하세요.
나중에 다른 개발자가 코드를 볼 때, 각 리소스의 목적을 빠르게 파악할 수 있습니다. README 파일도 작성해서 프로젝트 구조, 배포 방법, 환경 설정을 설명하세요.
주의할 점이 있습니다. 초보 개발자들이 흔히 하는 실수는 모든 리소스를 하나의 템플릿에 넣는 것입니다. 함수가 수십 개가 되면 template.yaml이 너무 길어져서 관리가 어렵습니다.
기능별로 템플릿을 분리하거나, Nested Stacks를 사용하는 것이 좋습니다. 또 다른 실수는 버전 관리를 하지 않는 것입니다.
Lambda 함수는 버전과 별칭을 지원합니다. 새로운 코드를 배포할 때 버전을 생성하고, 별칭을 사용하면 롤백이 쉬워집니다.
김개발 씨는 프로젝트를 대대적으로 리팩토링했습니다. 디렉토리 구조를 정리하고, 환경별 설정을 Parameters로 분리했습니다. 민감한 정보는 Secrets Manager로 옮기고, 공통 라이브러리는 Layer로 만들었습니다.
마지막으로 GitHub Actions로 CI/CD 파이프라인을 구축했습니다. "이제 훨씬 관리하기 쉬워졌어요!" 박시니어 씨가 미소를 지었습니다.
"처음부터 모범 사례를 따르면 나중에 고생하지 않아요. 잘했어요." SAM 모범 사례를 따르면 확장 가능하고 유지보수하기 쉬운 서버리스 애플리케이션을 만들 수 있습니다.
처음에는 복잡해 보이지만, 하나씩 적용하다 보면 자연스러워집니다. 여러분도 오늘부터 모범 사례를 실천해보세요.
실전 팁
💡 - SAM Policy Templates를 활용하면 일반적인 IAM 정책을 간단히 적용할 수 있습니다
- AWS Well-Architected Framework의 서버리스 렌즈를 참고하면 더 많은 모범 사례를 배울 수 있습니다
- 정기적으로 AWS Trusted Advisor를 확인해서 보안 및 비용 최적화 기회를 찾으세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.