AWS Lambda는 "코드를 올리면 AWS가 알아서 실행한다"는 한 문장으로 요약되지만, 실제 운영에서는 콜드 스타트, 메모리·타임아웃, VPC 연결, 동시성 제한, IAM 분리, 패키징 형식 등 알고 있어야 할 디테일이 많습니다. 이 문서는 Lambda를 처음 도입하거나 깊이 이해하고 싶은 개발자를 위해 핵심 개념·트레이드오프·유의점·실습 흐름을 한 자리에 정리합니다.
1. Lambda란 무엇인가
이벤트 기반 서버리스 함수 실행 서비스
AWS Lambda는 코드를 업로드하면 AWS가 필요한 만큼만 실행 환경을 만들고, 끝나면 회수해주는 서버리스 컴퓨트 서비스입니다. 사용자는 인스턴스나 컨테이너를 직접 띄우지 않고, "함수 + 트리거"만 정의합니다. 실제 실행된 시간(밀리초)과 메모리 사이즈로 과금되며, 호출이 없을 때는 비용이 0입니다.
핵심 특성
- 이벤트 기반 — HTTP(API Gateway), 큐(SQS), 스토리지(S3), 스트림(Kinesis/DynamoDB), 직접 invoke 등 트리거가 호출 단위
- 자동 스케일 — 동시에 들어오는 요청만큼 인스턴스를 자동 확장 (계정/리전 한도 내)
- stateless — 호출 간 메모리 상태가 보존되지 않음 (단, 재사용된 컨테이너에서는 일부 캐시 가능)
- microVM 격리 — Firecracker microVM에서 실행되어 멀티테넌트 환경에서도 강한 격리
- 최대 15분 실행 — 그 이상은 ECS/Fargate, Step Functions 등 다른 서비스가 필요
2. 실행 모델 (Cold/Warm Start, 동시성)
한 번의 호출이 어떻게 실행되는가
실행 환경 라이프사이클
- INIT: microVM 부팅 → 런타임 로드 → 패키지 압축 해제 → 핸들러 외부 코드 실행 (콜드 스타트의 본체)
- INVOKE: 핸들러 함수 호출 (이 시간만 청구)
- FREEZE/THAW: 호출 종료 후 컨테이너는 잠시 동결, 재호출 시 깨워서 재사용 → 웜 스타트
- SHUTDOWN: 일정 시간 호출 없거나 코드 변경되면 종료
즉, 핸들러 바깥(모듈 최상위)에 둔 코드는 컨테이너 1개당 1번 실행되며, 핸들러 안 코드는 호출마다 실행됩니다. DB 클라이언트·SDK 등은 가능하면 핸들러 바깥에 두어 재사용하세요.
동시성(Concurrency)
- 1 컨테이너 = 1 동시 실행: Lambda는 한 컨테이너에서 동시에 여러 호출을 처리하지 않습니다
- 더 많은 동시 호출이 들어오면 추가 컨테이너가 자동 생성 → 콜드 스타트 누적
- 계정 기본 동시 실행 한도: 리전당 1,000 (증액 가능)
- Reserved Concurrency: 특정 함수에 동시성 한도 고정 (다른 함수 보호)
- Provisioned Concurrency: 워밍 컨테이너를 미리 띄워 콜드 스타트 제거 (별도 과금)
3. 호출 방식 (Invocation Types)
동기 / 비동기 / 스트림
| 방식 | SDK 파라미터 | 특징·예시 |
|---|---|---|
| 동기 | RequestResponse | 호출자가 응답을 기다림. API Gateway, ALB, 직접 SDK 호출 |
| 비동기 | Event | 큐에 적재 후 즉시 응답(202). S3, SNS, EventBridge. 실패 시 재시도(2회) + DLQ |
| 스트림 (Poll-based) | Event Source Mapping | SQS·Kinesis·DynamoDB Streams를 Lambda가 폴링. 배치 처리 |
⚠ 호출 방식 선택 기준
- 응답을 사용자에게 즉시 돌려줘야 한다 → 동기
- 처리 결과를 기다릴 필요 없다 (이메일 발송, 후처리) → 비동기
- 비동기 호출은 자동 재시도가 있어 idempotent하게 작성 필수
- 대량 이벤트 처리는 SQS + 배치 size를 활용해 콜드 스타트 분산
4. 패키징 형식
Zip / Container Image / Layer
| 형식 | 특징·언제 |
|---|---|
| Zip | 기본 형식. 50 MB 직접 업로드 / 250 MB 압축 해제 한도. 가벼운 함수에 적합 |
| Container Image (ECR) | 최대 10 GB 이미지 지원. ML 모델·바이너리·시스템 의존성 많을 때. ECR에 push |
| Layer | 공유 라이브러리(공통 SDK, 의존성)를 별도 레이어로 분리. 함수 zip 크기 절감, 다중 함수 공유 |
⚠ 형식 선택 가이드
- 의존성이 작고 단순하면 Zip이 콜드 스타트·운영 측면에서 가장 유리
- 네이티브 바이너리·대형 의존성(ML 모델 등)이면 Container Image
- 여러 함수가 공통 의존성을 가지면 Layer로 분리해 빌드·배포 시간 절감
- Container Image는 콜드 스타트가 zip보다 길어질 수 있어 베이스 이미지 최소화 중요
5. 권한 모델 (IAM)
Execution Role과 Resource-based Policy의 분리
| 정책 | 담당 |
|---|---|
| Execution Role | Lambda 함수가 실행되면서 다른 AWS 리소스를 호출할 때 쓰는 권한 (S3 read, DynamoDB write, KMS Decrypt 등) |
| Resource-based Policy | 누가 이 Lambda를 호출할 수 있는지 정의 (API Gateway, S3, EventBridge, 다른 계정 등) |
호출자(예: ECS Task)는 자기 IAM Role에 lambda:InvokeFunction 권한이 있어야 하고, 동시에 Lambda의 Resource Policy에서 그 Principal을 허용해야
합니다 (양쪽 합집합 평가). 이 분리 덕분에 민감 권한(KMS, HSM)은 Lambda Execution Role에만 두고, 호출자는 "호출만 가능"하게 좁힐 수 있습니다.
6. 네트워크 (VPC / VPC Endpoint)
기본 외부망 / VPC 연결 / PrivateLink
- 기본: Lambda는 AWS가 관리하는 네트워크에서 실행되며, 인터넷·다른 AWS API(S3, DynamoDB 등)와 통신 가능
- VPC 연결: RDS·ElastiCache 등 VPC 내부 자원에 접근하려면 함수에 서브넷·SG 부여. 이 경우 Lambda는 ENI를 붙이며, 인터넷 접근에는 NAT Gateway 필요
- VPC Endpoint(PrivateLink):
com.amazonaws.<region>.lambda를 만들면 호출자가 VPC 내부에서 NAT 없이 AWS 백본을 통해 Lambda 호출 → 보안·비용·지연 모두 개선 - 현재 Lambda VPC ENI는 함수 단위로 공유되어 콜드 스타트 영향이 거의 없음 (구버전 Hyperplane 이전과 다름)
7. 주요 제약 (Limits)
알아두면 설계 단계에서 시간 절약
| 항목 | 제한 |
|---|---|
| 최대 실행 시간 | 15분 (900초) |
| 메모리 | 128 MB ~ 10,240 MB (1 MB 단위), CPU는 메모리에 비례 |
| 동기 호출 페이로드 | 요청 6 MB / 응답 6 MB |
| 비동기 호출 페이로드 | 256 KB |
| /tmp 임시 디스크 | 기본 512 MB, 최대 10 GB까지 설정 가능 |
| Zip 패키지 | 50 MB(직접) / 250 MB(압축 해제) |
| Container Image | 10 GB |
| 동시 실행 | 계정/리전당 기본 1,000 (증액 가능) |
8. 장단점 한눈에
언제 빛나고 언제 부적합한가
장점
- 서버 운영 부담 0 (패치·OS·스케일 모두 AWS)
- 호출 단위 과금, 트래픽 없으면 비용 0
- 자동 무한 확장 (한도 내)
- 이벤트 소스와 즉시 통합 (S3, SQS, API Gateway 등)
- microVM 격리로 보안 우수
- 민감 권한을 Execution Role에 가두어 권한 분리 용이
단점
- 콜드 스타트 (특히 VPC + 큰 패키지 + JVM/.NET 런타임)
- 최대 15분 → 장시간 작업 부적합
- 높은 트래픽이 평탄하면 EC2/Fargate 대비 단가 ↑
- 로컬 디버깅·재현이 까다로움
- 단일 호출 페이로드·메모리 한계가 명확
- 비동기 호출은 자동 재시도가 있어 idempotent 설계 필수
9. 사용 시 유의점 (Best Practices)
실수 빈발 포인트
- 핸들러 외부에 초기화 두기 — DB·SDK 클라이언트·암호 키 로딩은 모듈 최상위에 두어 웜 호출에서 재사용
- 메모리 = CPU — 메모리를 늘리면 vCPU도 비례. CPU 바운드 함수는 메모리 1.8 GB+가 더 빠르고 더 쌀 때도 있음
- 타임아웃은 호출자 timeout보다 짧게 — API Gateway 통합 timeout(29초)을 넘기면 응답 누락
- 시크릿은 환경변수 평문 X — Secrets Manager / SSM Parameter Store + KMS, 핸들러 외부에서 캐시 로드
- 로그·관측 — CloudWatch Logs·X-Ray·Lambda Insights. 로그 보관 기간을 명시적으로 설정하지 않으면 무기한 누적
- 비동기 호출 = idempotent — 자동 재시도(2회) + DLQ 정책 사전 설계
- CPU 바인딩 워크로드는 ARM(Graviton2)이 단가 우위인 경우 많음 — 아키텍처 옵션 점검
- 콜드 스타트가 SLA에 치명적이면 Provisioned Concurrency 또는 SnapStart(Java) 검토
- VPC 내부 자원 호출 시 NAT Gateway 비용 폭증 주의 — VPC Endpoint 적극 활용
- 계정 전체 동시성 보호 — 폭주 가능 함수에 Reserved Concurrency 상한 설정
🛠 실습 — Hello Lambda 만들기
콘솔 → AWS CLI → SAM(IaC) 순서로 같은 함수를 점차 자동화합니다.
사전 준비
- AWS 계정 + IAM 사용자(Lambda·CloudWatch 권한)
- AWS CLI v2 설치 및
aws configure완료 - Node.js 20 또는 Python 3.12 (실습은 Node 기준)
- (선택) AWS SAM CLI
STEP 1 — 콘솔에서 빠르게
- AWS Console → Lambda → "Create function" → Author from scratch
- 이름
hello-lambda, 런타임 Node.js 20.x, 새 IAM Role 자동 생성 선택 - 코드 편집기에 아래 내용 붙여넣기 → Deploy
export const handler = async (event) => {
const name = event.name ?? 'world';
return {
statusCode: 200,
body: JSON.stringify({ message: `hello, ${name}!`, ts: Date.now() }),
};
};
"Test" 탭에서 {"name": "lambda"}로
호출하고 응답·로그를 확인합니다.
STEP 2 — AWS CLI로 zip 배포
# 1) 핸들러 작성
mkdir hello && cd hello
cat > index.mjs <<'EOF'
export const handler = async (event) => ({
statusCode: 200,
body: JSON.stringify({ msg: `hello ${event.name ?? 'cli'}` })
});
EOF
# 2) 압축
zip function.zip index.mjs
# 3) 함수 생성 (Role ARN은 사전에 만들어둔 lambda-basic-execution Role)
aws lambda create-function \
--function-name hello-cli \
--runtime nodejs20.x \
--role arn:aws:iam::<ACCOUNT_ID>:role/lambda-basic-execution \
--handler index.handler \
--zip-file fileb://function.zip
# 4) 동기 호출
aws lambda invoke \
--function-name hello-cli \
--payload '{"name":"world"}' \
--cli-binary-format raw-in-base64-out \
out.json
cat out.json
# 5) 코드 수정 후 업데이트
zip function.zip index.mjs
aws lambda update-function-code \
--function-name hello-cli \
--zip-file fileb://function.zip
STEP 3 — SAM으로 IaC 배포
# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
HelloFn:
Type: AWS::Serverless::Function
Properties:
FunctionName: hello-sam
Runtime: nodejs20.x
Handler: index.handler
CodeUri: ./
MemorySize: 256
Timeout: 10
Architectures: [arm64]
Events:
Api:
Type: HttpApi
Properties:
Path: /hello
Method: GET
# 빌드 + 배포
sam build
sam deploy --guided # 처음 한 번만 --guided
# 출력에 HttpApi 엔드포인트가 표시됨
curl https://<id>.execute-api.<region>.amazonaws.com/hello?name=sam
STEP 4 — 다른 서비스에서 호출하기 (SDK)
// AWS SDK v3 (Node) — 다른 서비스에서 동기 호출
import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';
const client = new LambdaClient({ region: 'ap-northeast-2' });
const res = await client.send(new InvokeCommand({
FunctionName: 'hello-sam',
InvocationType: 'RequestResponse',
Payload: Buffer.from(JSON.stringify({ name: 'caller' })),
}));
const body = JSON.parse(Buffer.from(res.Payload).toString());
console.log(body);
if (res.FunctionError) throw new Error('Lambda execution failed');
호출자(EC2/ECS Task/다른 Lambda)의 IAM Role에 lambda:InvokeFunction 권한이 있어야 합니다. ECS의 경우 Task Role이 자격증명을 자동
주입하므로 별도 키 관리 불필요.
STEP 5 — 관측·디버깅
- CloudWatch Logs → 로그 그룹
/aws/lambda/<function>에서 실행 로그 확인 - "Duration", "Init Duration"(콜드 스타트), "Max Memory Used" 메트릭으로 사이즈·콜드 스타트 튜닝
- X-Ray 활성화:
Tracing: Active로 설정 후 다운스트림 호출 분석 - SAM 로컬 호출:
sam local invoke HelloFn -e event.json
의사결정 가이드 — Lambda를 언제 쓸까
| 상황 | 권장 | 이유 |
|---|---|---|
| 간헐적·이벤트 기반 작업 (S3 업로드, 큐 처리, 스케줄) | Lambda | 호출 없을 때 비용 0 |
| 트래픽 변동이 크고 평균 RPS는 낮은 API | Lambda + API Gateway | 자동 확장 + 무대기 비용 |
| 평탄한 고RPS 트래픽이 24시간 | ECS Fargate / EC2 | 평균 단가 우위, 콜드 스타트 없음 |
| 15분 초과 장시간 작업 | Fargate Tasks / Batch / Step Functions | Lambda 시간 한계 초과 |
| 민감 권한 격리가 핵심 (KMS·HSM 호출) | Lambda | Execution Role 분리로 권한 최소화 쉬움 |
| 대형 ML 추론 (모델 수 GB) | Lambda Container Image | 10 GB 이미지 + Provisioned Concurrency |
🎯 핵심 요약
- Lambda = 함수 + 트리거의 서버리스 실행. 사용한 ms·메모리만 과금.
- 핸들러 외부 코드는 컨테이너당 1회, 안쪽은 호출마다 실행. 클라이언트 재사용으로 콜드 스타트 완화.
- 호출 방식은 동기 / 비동기 / 스트림 세 가지 — idempotency·재시도·DLQ 설계 핵심.
- 패키징은 Zip / Container Image / Layer. 의존성 크기에 맞게 선택.
- 권한은 Execution Role(나가는 호출) + Resource Policy(들어오는 호출) 두 축.
- 제약: 최대 15분, 메모리 10 GB, 페이로드 6 MB(동기) — 설계 단계에서 한계 점검.
- 고RPS·장시간·평탄한 트래픽엔 Lambda보다 ECS/Fargate가 유리할 수 있음 — 도구 선택은 트래픽 패턴부터.
Lambda는 "운영 부담 없이 빠르게 작은 일을 처리"하는 데 특화된 도구다.
트래픽 패턴, 실행 시간, 권한 분리 요구를 함께 따져 도입하면 운영 비용을 가장 크게 줄일 수 있다.