🔍 검색 키워드: AWS Lambda cold start 해결, Lambda 콜드 스타트 최적화, Lambda 응답 지연 원인, Provisioned Concurrency 설정, Lambda 함수 초기화 시간 단축
AWS Lambda Cold Start 완벽 해결 가이드 — 지연 원인과 최적화 전략
증상: 첫 요청만 유독 느리다
Lambda 기반 API에서 이런 현상이 보인다.
일반 응답: 50~100ms
첫 번째 요청 / 트래픽 없다가 재요청: 1500~3000ms
CloudWatch 로그를 보면:
REPORT RequestId: abc-123 Duration: 1823.45 ms Billed Duration: 1824 ms
Memory Size: 512 MB Max Memory Used: 128 MB
Init Duration: 1654.23 ms
Init Duration이 실제 함수 실행 시간보다 훨씬 길다. 이것이 콜드 스타트(Cold Start)다.
원인 분석: Lambda 실행 생명주기
Lambda는 요청이 없을 때 컨테이너를 종료한다. 새 요청이 들어오면 다음 단계를 거친다.
- 컨테이너 생성 — Lambda 실행 환경(마이크로VM) 할당
- 런타임 초기화 — Node.js / Python / JVM 등 런타임 부팅
- 코드 초기화 — 핸들러 외부 코드 실행 (import, DB 연결, 설정 로드)
- 핸들러 실행 — 실제 요청 처리
1~3 단계가 "콜드 스타트"다. 이후 일정 시간 안에 다시 요청이 오면 4단계만 실행하는 "웜 스타트(Warm Start)"가 된다.
런타임별 콜드 스타트 시간
| 런타임 | 평균 콜드 스타트 |
|---|---|
| Python 3.x | ~200ms |
| Node.js 18.x | ~250ms |
| Go | ~50ms |
| Java 17 (JVM) | ~1000~3000ms |
| Java 17 (GraalVM Native) | ~150ms |
| .NET 6 | ~500ms |
JVM 기반이 압도적으로 느리다. Spring Boot on Lambda는 이 문제의 대표적인 사례다.
해결방법
해결 1 — 핸들러 외부에서 초기화 (재사용 최대화)
# ❌ 잘못된 패턴: 매 요청마다 DB 연결
def handler(event, context):
db = pymysql.connect(host=os.environ['DB_HOST'], ...) # 매 요청마다 연결
result = db.execute("SELECT ...")
db.close()
return result
# ✅ 올바른 패키-��팭: 요청마 항됐 ₔ DB 연결
import pymysql
import os
# 콜드 스타트 웄 해 벰헐 실행l 이후 재사용볠
db = pymysql.connect(
host=os.environ['DB_HOST'],
user=os.environ['DB_USER'],
password=os.environ['DB_PASSWORD'],
database=os.environ['DB_NAME'],
cursorclass=pymysql.cursors.DictCursor
)
def handler(event, context):
with db.cursor() as cursor:
cursor.execute("SELECT ...")
return cursor.fetchall()
// Node.js — SDK 클흼스이 언트도 외부초기화
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
// 콜드 스타트 시 읐 번 생성, 이후 재사용트 시 한 번 생성, 이후 재사용
const dynamo = new DynamoDBClient({ region: 'ap-northeast-2' });
exports.handler = async (event) => {
const result = await dynamo.send(new GetItemCommand({ ... }));
return result;
};
해결 2 — 배포 패키지 최소화
# Node.js — esbuild로 번들링 (tree-shaking)
esbuild src/handler.ts --bundle --platform=node --target=node18 \
--outfile=dist/handler.js --minify
# 패키지 크기 확인 (목표: 압축 기준 5MB 이하)
du -sh ./dist
해결 3 — 메모리 최적화 (CPU와 비례)
Lambda는 메모리 설정에 비례해 vCPU를 할당한다. 메모리를 늘리면 초기화도 빨라진다.
# AWS CLI로 메모리 설정 변경
aws lambda update-function-configuration \
--function-name my-function \
--memory-size 1024
# 콜드 스타트 비교 (동일 코드)
# 128 MB → Init: 1200ms
# 512 MB → Init: 400ms
# 1024 MB → Init: 180ms
해결 4 — Provisioned Concurrency 설정
콜드 스타트를 완전히 없애는 방법. 미리 초기화된 컨테이너를 대기시킨다.
# Provisioned Concurrency 설정
aws lambda put-provisioned-concurrency-config \
--function-name my-function \
--qualifier prod \
--provisioned-concurrent-executions 5
# Auto Scaling으로 트래픽에 따라 자동 조절
aws application-autoscaling register-scalable-target \
--service-namespace lambda \
--resource-id function:my-function:prod \
--scalable-dimension lambda:function:ProvisionedConcurrency \
--min-capacity 2 \
--max-capacity 20
해결 5 — Warm-up 스케줄러 (저비용 대안)
# 핸들러에서 warmup 요청 처리
def handler(event, context):
if event.get('source') == 'serverless-plugin-warmup':
print('WarmUp - Lambda is warm!')
return {'statusCode': 200, 'body': 'warm'}
# 실제 처리
return process(event)
정리표
| 방법 | 효과 | 비용 | 적합한 상황 |
|---|---|---|---|
| 핸들러 외부 초기화 | 재사용 극대화 | 무료 | 항상 적용 |
| 패키지 최소화 | 초기화 시간 단축 | 무료 | 항상 적용 |
| 메모리 증가 | 초기화 속도 향상 | 미미 | 128~512MB 구간 |
| Provisioned Concurrency | 콜드 스타트 제거 | 높음 | 상시 트래픽 API |
| Warm-up 스케줄러 | 웜 상태 유지 | 낮음 | 간헐적 트래픽 |
| VPC 제거/RDS Proxy | ENI 지연 제거 | RDS Proxy 비용 | DB 접근 Lambda |
모니터링
# CloudWatch에서 콜드 스타트 추적
# INIT_DURATION이 있는 로그 = 콜드 스타트 콜드 스타트 발생
aws logs filter-log-events \
--log-group-name /aws/lambda/my-function \
--filter-pattern "INIT_DURATION" \
--start-time $(date -d '1 hour ago' +%s000)
콜드 스타트 최적화는 "없애기"보다 "허용 가능한 수준으로 관리하기"가 현실적 목표다. 핸들러 외부 초기화와 패키지 최소화는 무조건 적용하고, SLA 요구사항에 따라 Provisioned Concurrency 여부를 결정하면 �