Lambda 함수 최적화: 콜드스타트 해결부터 메모리 튜닝까지
AWS Lambda 함수의 성능을 최적화하는 방법을 설명합니다. 콜드스타트 해결, 메모리-CPU 관계, Provisioned Concurrency까지 완벽 가이드입니다.
관련 시험 도메인
- Design High-Performing Architectures
- Design Cost-Optimized Architectures
핵심 요약
Lambda 최적화의 핵심: 메모리를 늘리면 CPU도 증가하고, 콜드스타트는 Provisioned Concurrency나 SnapStart로 해결합니다. 핸들러 외부에서 초기화하고 /tmp에 캐싱하면 실행 시간을 줄일 수 있습니다.
시험 팁
시험 빈출: "Lambda 콜드스타트를 줄이려면?" → Provisioned Concurrency 또는 SnapStart(Java). "Lambda 성능을 높이려면?" → 메모리 증가 (CPU도 함께 증가).
1. Lambda 실행 환경 이해
실행 환경 수명 주기
┌─────────────────────────────────────────────────────────┐
│ Lambda 실행 환경 수명 주기 │
├─────────────────────────────────────────────────────────┤
│ │
│ [첫 번째 호출 - 콜드스타트] │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 환경 생성 │ → │ Init 단계│ → │ Invoke │ │
│ │ (다운로드)│ │(초기화) │ │(핸들러) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ 콜드스타트 지연 시간 │ 실제 실행 시간 │
│ ─────────────────────────────┼─────────────── │
│ │
│ [후속 호출 - 웜스타트] │
│ ┌──────────────────────────┐ ┌──────────┐ │
│ │ 환경 재사용 (스킵) │ → │ Invoke │ │
│ └──────────────────────────┘ └──────────┘ │
│ 빠름! 실제 실행 시간 │
└─────────────────────────────────────────────────────────┘
콜드스타트란?
콜드스타트는 Lambda가 새로운 실행 환경을 생성하는 과정에서 발생하는 지연입니다:
- 코드 다운로드
- 런타임 환경 시작
- Init 코드 실행 (핸들러 외부 코드)
| 런타임 | 평균 콜드스타트 시간 |
|---|---|
| Python | ~200ms |
| Node.js | ~200ms |
| Go | ~100ms |
| Java | ~1-3초 |
| .NET | ~500ms-1초 |
2. 메모리와 CPU의 관계
핵심 개념
Lambda에서 메모리를 늘리면 CPU도 비례하여 증가합니다. 이는 Lambda의 가장 중요한 특징입니다.
┌─────────────────────────────────────────────────────────┐
│ 메모리-CPU 비례 관계 │
├─────────────────────────────────────────────────────────┤
│ │
│ 메모리 CPU 성능 vCPU │
│ ─────────────────────────────────────────── │
│ 128 MB 낮음 ~0.1 vCPU │
│ 512 MB 중간 ~0.4 vCPU │
│ 1,792 MB 1 vCPU 1 vCPU │
│ 3,008 MB 1.7 vCPU ~2 vCPU │
│ 10,240 MB 6 vCPU 6 vCPU (최대) │
│ │
│ 1,769MB 이상: 멀티스레드 병렬 처리 가능 │
└─────────────────────────────────────────────────────────┘
메모리 튜닝 전략
비용 최적화 공식:
실행 시간 × 메모리 = 비용
예시:
- 128MB × 10초 = 1,280 MB-초
- 512MB × 2.5초 = 1,280 MB-초 (동일 비용, 더 빠름!)
메모리를 늘려도 실행 시간이 비례해 줄어들면
비용은 같거나 오히려 줄어들 수 있음
AWS Lambda Power Tuning
메모리 최적화를 자동으로 테스트하는 도구입니다:
# Step Functions로 다양한 메모리 설정 테스트
# 128MB ~ 10GB까지 모든 조합 테스트 가능
# 결과: 최적의 메모리 설정 추천
일반적인 결과:
- 6GB 이상에서는 성능 개선 폭이 감소
- 비용 대비 성능 곡선의 "스위트 스팟" 찾기
시험 팁
시험 포인트: Lambda 함수가 CPU 집약적이라면 메모리를 늘려 CPU를 증가시켜야 합니다. 메모리와 CPU는 비례합니다.
3. 콜드스타트 해결 방법
방법 1: Provisioned Concurrency
미리 실행 환경을 준비해두어 콜드스타트를 완전히 제거합니다.
┌─────────────────────────────────────────────────────────┐
│ Provisioned Concurrency │
├─────────────────────────────────────────────────────────┤
│ │
│ 설정: Provisioned Concurrency = 100 │
│ │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ... ┌────┐ │
│ │ 환경 │ │ 환경 │ │ 환경 │ │ 환경 │ │ 환경 │ │
│ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │100 │ │
│ └────┘ └────┘ └────┘ └────┘ └────┘ │
│ ↑ │
│ 미리 초기화되어 대기 중 (웜 상태 유지) │
│ │
│ 요청 → 즉시 응답 (콜드스타트 없음) │
└─────────────────────────────────────────────────────────┘
비용 고려사항:
예: 1,536MB 메모리, 100개 동시성, 24시간
= 약 $54/일 = 약 $1,620/월
주의: EC2처럼 지속 비용 발생
→ 트래픽 패턴에 따라 Auto Scaling 설정 권장
방법 2: Lambda SnapStart (Java)
Java 함수의 Init 단계 스냅샷을 저장하여 콜드스타트를 최대 90% 단축합니다.
┌─────────────────────────────────────────────────────────┐
│ SnapStart 작동 방식 │
├─────────────────────────────────────────────────────────┤
│ │
│ [버전 배포 시] │
│ Init 실행 → 메모리 상태 스냅샷 → 암호화 저장 │
│ │
│ [함수 호출 시] │
│ 스냅샷 로드 → 즉시 실행 (Init 스킵) │
│ │
│ 결과: Java 콜드스타트 1-3초 → 200ms 이하 │
└─────────────────────────────────────────────────────────┘
방법 3: EventBridge 워밍업
5분마다 Lambda를 주기적으로 호출하여 실행 환경을 유지합니다.
┌─────────────────────────────────────────────────────────┐
│ EventBridge 워밍업 전략 │
├─────────────────────────────────────────────────────────┤
│ │
│ EventBridge Rule: rate(5 minutes) │
│ │ │
│ ▼ │
│ Lambda 함수 호출 (워밍업 이벤트) │
│ │ │
│ ▼ │
│ 실행 환경 유지 (최대 15분까지 재사용) │
│ │
│ 장점: 저렴함 (호출 비용만) │
│ 단점: 동시성 1개만 유지, 완벽하지 않음 │
└─────────────────────────────────────────────────────────┘
4. 성능 최적화 모범 사례
핸들러 외부 초기화
# ❌ 잘못된 예: 매 호출마다 초기화
def handler(event, context):
client = boto3.client('dynamodb') # 매번 생성
return client.get_item(...)
# ✅ 올바른 예: 핸들러 외부에서 초기화
client = boto3.client('dynamodb') # 한 번만 생성, 재사용
def handler(event, context):
return client.get_item(...) # 기존 연결 재사용
/tmp 디렉토리 캐싱
import os
CACHE_FILE = '/tmp/cached_data.json'
def handler(event, context):
# 캐시 확인
if os.path.exists(CACHE_FILE):
with open(CACHE_FILE) as f:
data = json.load(f)
else:
# 데이터 로드 후 캐싱
data = load_expensive_data()
with open(CACHE_FILE, 'w') as f:
json.dump(data, f)
return process(data)
최적화 체크리스트
┌─────────────────────────────────────────────────────────┐
│ Lambda 최적화 체크리스트 │
├─────────────────────────────────────────────────────────┤
│ │
│ ✅ SDK 클라이언트는 핸들러 외부에서 초기화 │
│ ✅ DB 연결은 핸들러 외부에서 생성 (연결 재사용) │
│ ✅ 정적 자산은 /tmp에 캐싱 (512MB 제한) │
│ ✅ 불필요한 패키지 제거 (배포 패키지 최소화) │
│ ✅ AWS Lambda Power Tuning으로 메모리 최적화 │
│ ✅ VPC 연결 최소화 (필요한 경우만) │
│ ✅ 프로비전드 동시성은 꼭 필요한 경우만 │
└─────────────────────────────────────────────────────────┘
5. VPC 연결 고려사항
VPC 내 Lambda 지연 문제
Lambda를 VPC에 연결하면 ENI 생성으로 인해 추가 지연이 발생할 수 있습니다.
과거 (2019년 이전):
VPC Lambda 콜드스타트: 10-30초 추가
현재 (Hyperplane 적용 후):
VPC Lambda 콜드스타트: 일반 Lambda와 유사
VPC 연결이 필요한 경우
| 필요한 경우 | 불필요한 경우 |
|---|---|
| RDS/Aurora 접근 | DynamoDB 접근 |
| ElastiCache 접근 | S3 접근 |
| 프라이빗 서브넷 리소스 | SQS, SNS 접근 |
| EC2 인스턴스 통신 | API Gateway 호출 |
6. 비용 최적화
Lambda 비용 구조
총 비용 = 요청 비용 + 컴퓨팅 비용
요청 비용: $0.20 / 100만 요청
컴퓨팅 비용: $0.0000166667 / GB-초
예: 512MB, 1초 실행, 100만 호출/월
= $0.20 + (0.5GB × 1초 × 1,000,000 × $0.0000166667)
= $0.20 + $8.33 = $8.53/월
비용 절감 전략
| 전략 | 설명 |
|---|---|
| 메모리 최적화 | Power Tuning으로 최적 메모리 찾기 |
| 실행 시간 단축 | 핸들러 외부 초기화, 캐싱 |
| Graviton2 | ARM 기반 프로세서로 20% 비용 절감 |
| Provisioned 최적화 | Auto Scaling으로 필요한 만큼만 |
Graviton2 (ARM) 사용
x86_64 대비 Graviton2:
- 가격: 20% 저렴
- 성능: 최대 34% 향상
- 전환: 아키텍처 변경 필요 (arm64)
지원 런타임:
- Python, Node.js, Ruby, Java, .NET, Go
시험 출제 포인트
자주 나오는 문제 유형
-
콜드스타트 관련
- "Java Lambda의 콜드스타트를 줄이려면?" → SnapStart
- "콜드스타트를 완전히 제거하려면?" → Provisioned Concurrency
-
성능 최적화
- "Lambda 실행 시간이 너무 길다면?" → 메모리 증가 (CPU도 증가)
- "Lambda 초기화 시간을 줄이려면?" → 핸들러 외부 초기화
-
비용 최적화
- "Lambda 비용을 줄이려면?" → Graviton2, 메모리 최적화
- "Provisioned Concurrency의 비용 특성?" → 지속 비용 발생
시험 팁
핵심 암기:
- 메모리 증가 = CPU 증가
- 콜드스타트 제거 = Provisioned Concurrency
- Java 콜드스타트 최적화 = SnapStart
- 비용 절감 = Graviton2 (ARM)
FAQ
Q1: 메모리를 늘리면 항상 비용이 증가하나요?
아니요. 메모리를 늘리면 CPU도 증가하여 실행 시간이 줄어듭니다. 실행 시간이 비례해서 줄어들면 총 비용은 같거나 오히려 줄어들 수 있습니다. Lambda Power Tuning으로 최적 메모리를 찾으세요.
Q2: Provisioned Concurrency와 Reserved Concurrency의 차이는?
- Provisioned Concurrency: 미리 초기화된 환경 유지 (콜드스타트 제거, 비용 발생)
- Reserved Concurrency: 최대 동시 실행 수 제한 (비용 없음, 콜드스타트 있음)
Q3: SnapStart는 모든 런타임에서 사용 가능한가요?
아니요. Java 11/17 이상에서만 사용 가능합니다. Python, Node.js 등 다른 런타임에서는 Provisioned Concurrency를 사용하세요.
Q4: /tmp 디렉토리의 용량 제한은?
기본 512MB이며, 최대 10GB까지 늘릴 수 있습니다 (추가 비용 발생). 실행 환경이 재사용되는 동안 /tmp 데이터도 유지됩니다.
Q5: VPC 연결이 성능에 영향을 주나요?
현재는 Hyperplane 기술 덕분에 VPC 연결로 인한 추가 지연이 거의 없습니다. 과거에는 ENI 생성으로 10-30초가 걸렸지만, 지금은 일반 Lambda와 유사합니다.
마무리
Lambda 최적화의 핵심 포인트:
- 메모리 = CPU: 메모리를 늘리면 CPU도 증가
- 핸들러 외부 초기화: SDK, DB 연결을 재사용
- 콜드스타트 해결: Provisioned Concurrency 또는 SnapStart
- 비용 최적화: Graviton2, Power Tuning
시험에서는 "Lambda 성능 향상" → 메모리 증가, "콜드스타트 제거" → Provisioned Concurrency를 떠올리세요.