AI 에이전트를 Lambda에 올리면 LLM SDK 임포트와 시크릿 페치가 Init phase에 누적되어 cold start가 일반 함수보다 수 배로 늘어난다. AWS가 공식 지원하는 5가지 패턴(SnapStart, Provisioned Concurrency, Init 최적화, Container Image, arm64 Graviton)으로 이 비용을 잡는다.
왜 AI 에이전트 cold start가 더 비싼가
Lambda cold start는 Init → Invoke 두 단계(SnapStart 사용 시 중간에 Restore)로 구성되며, AWS는 Init을 "function's static initialization code" 실행 구간으로 정의한다.1 AI 에이전트 함수에서는 이 구간이 다음 세 가지 이유로 부풀어 오른다.
- LLM SDK 임포트 —
boto3,anthropic,langchain패키지는 임포트 시점에 수십 개의 트랜지티브 의존성을 로딩한다. 압축 해제·바이트코드 컴파일 비용이 Init에 집중된다. - 시크릿/구성 페치 — Secrets Manager·SSM Parameter Store 호출을 Init에 묶으면 네트워크 RTT가 그대로 cold start에 더해진다.
- 프롬프트 캐시 미스 — 새 실행 환경은 이전 환경의 in-memory 캐시(토크나이저, 임베딩, 시스템 프롬프트)를 공유하지 않는다. Bedrock 측 prompt caching은 별도이며, Lambda 인스턴스 간 캐시 동기화는 불가능하다.
Init phase에는 또한 10초 타임아웃이 적용된다. 모델 가중치를 Init에서 다운로드하는 식의 설계는 이 한도에 부딪힌다.1
패턴 1 — SnapStart로 Init phase 스냅샷 재사용
SnapStart는 Init이 끝난 시점의 메모리·디스크 상태를 스냅샷으로 저장하고, 이후 cold start에서 그 스냅샷을 복원(Restore)하므로 Init을 건너뛴다. 결과적으로 Init이 무거운 함수의 cold start가 크게 줄어든다.
지원 런타임: Java 11+, Python 3.12+, .NET 8+2
# AWS SAM — SnapStart 활성화
Resources:
AgentFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: python3.12
SnapStart:
ApplyOn: PublishedVersions # 배포된 버전에만 적용
Handler: agent.handler
CodeUri: src/
MemorySize: 1024
주의 1 — uniqueness 함정. 스냅샷이 여러 인스턴스로 복원되면 PRNG seed, UUID, TLS 세션 키처럼 인스턴스별로 달라야 할 값이 동일해진다.
beforeCheckpoint/afterRestore라이프사이클 훅에서 재생성해야 한다.2주의 2 — 네트워크 핸들 함정. Init에서 만든 HTTPS 커넥션·DB 풀은 스냅샷에 박제된다. 복원 직후 대상 서버가 keep-alive를 끊었을 가능성이 높으므로,
afterRestore에서 클라이언트를 재초기화하거나 lazy-init으로 미루는 패턴이 안전하다.
패턴 2 — Provisioned Concurrency로 항상 warm 유지
Provisioned Concurrency(PC)는 지정한 수의 실행 환경을 미리 초기화하고 warm 상태로 유지한다. Invoke 시점에 Init이 완료된 환경이 대기하므로 cold start latency가 사실상 사라진다.3
import boto3
client = boto3.client('lambda')
client.put_provisioned_concurrency_config(
FunctionName='my-agent-function',
Qualifier='PROD',
ProvisionedConcurrentExecutions=5,
)
선택 가이드 (수치는 실측 시나리오에 따라 다름, 일반적 경향):
| 설정 | Cold start | 추가 비용 | 적합 워크로드 |
|---|---|---|---|
| 기본 | 가장 느림 | 없음 | 비정기 배치 |
| SnapStart | 중간 | 없음 | 버스트 트래픽 |
| PC | 사실상 0 | 시간당 PC 단가 × 인스턴스 수 | p99 SLA 엄격 |
| PC + SnapStart | 사실상 0 | PC 단가만 | 일관성 최우선 |
PC는 Application Auto Scaling과 결합해 시간대·트래픽 패턴에 맞춰 인스턴스 수를 자동 조정할 수 있다.3 인터랙티브 챗봇처럼 p99 응답시간이 SLA인 워크로드에 적합하지만, 항상 warm 상태이므로 비용 분석이 선결 조건이다.
패턴 3 — Init phase에서 무거운 작업 선점 실행
핸들러 바깥의 코드는 Init에서 한 번 실행되고 실행 환경이 재사용되는 동안 캐시된다. AWS 공식 베스트 프랙티스는 "initialize SDK clients and database connections outside of the function handler"를 명시적으로 권장한다.4
import boto3
from anthropic import Anthropic
# Init phase: 실행 환경 생성 시 1회 실행
_secrets = boto3.client('secretsmanager')
_api_key = _secrets.get_secret_value(
SecretId='prod/anthropic/api-key'
)['SecretString']
_llm = Anthropic(api_key=_api_key)
_bedrock = boto3.client('bedrock-runtime')
def handler(event, context):
# Invoke phase: 요청마다 실행
response = _llm.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": event['prompt']}],
)
return {"statusCode": 200, "body": response.content[0].text}
_llm, _bedrock을 모듈 레벨에 둠으로써 warm invoke의 SDK 재초기화 비용이 제거된다. SnapStart와 결합하면 cold start에서도 이 비용이 0에 수렴한다.
패턴 4 — Container Image로 레이어 캐시 활용
Lambda 컨테이너 이미지는 최대 10 GB까지 허용되며, ECR에서 동일 이미지를 재사용하는 환경은 레이어를 캐시한다.5 AI 에이전트 워크로드에서 컨테이너가 유리한 이유는 세 가지다.
- ML 라이브러리(
torch,transformers)가 ZIP 250 MB 한계를 자주 넘는다 - 의존성 레이어를 공유하면 대용량 패키지를 한 번만 pull한다
- 동일 Dockerfile로 로컬·CI·Lambda 환경을 통일할 수 있다
FROM public.ecr.aws/lambda/python:3.12
# 의존성 레이어: 자주 안 바뀜 → 캐시 최우선
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 애플리케이션 코드: 자주 바뀜 → 최후 레이어
COPY src/ ${LAMBDA_TASK_ROOT}/
CMD ["agent.handler"]
의존성 레이어를 코드 레이어보다 먼저 두는 것이 핵심이다. 코드만 바뀌었을 때 의존성 레이어 캐시가 유지되어 ECR pull 시간과 cold start 이미지 페치 시간이 함께 줄어든다.
패턴 5 — arm64 Graviton으로 비용·성능 개선
Lambda는 x86_64 외에 arm64(Graviton2) 아키텍처를 지원한다. AWS는 동일 메모리 구성에서 arm64가 x86_64 대비 가격·성능 면에서 유리한 워크로드가 있다고 안내한다(실제 효과는 워크로드별 측정 필요).6
Resources:
AgentFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: python3.12
Architectures: [arm64]
MemorySize: 1024
SnapStart:
ApplyOn: PublishedVersions
arm64 전환 시 점검 포인트
- 순수 Python·Node.js 코드는 대체로 그대로 동작
- C 확장(
numpy,pydantic-core,torch)은 arm64용 wheel이 필요 - 컨테이너 이미지는
docker buildx build --platform linux/arm64로 빌드
워크로드별 패턴 선택 가이드
패턴 결정 매트릭스
| 워크로드 | 권장 조합 | 이유 |
|---|---|---|
| 실시간 챗봇 (p99 < 200 ms) | PC + arm64 | 항상 warm + 비용 절감 |
| 버스트 API | SnapStart + arm64 | cold start 최소, PC 비용 없음 |
| 배치 AI 파이프라인 | Container image + arm64 | 대용량 ML 의존성, 비용 우선 |
| Init 무거운 에이전트 | Init 최적화 + SnapStart | SDK 초기화 1회, 스냅샷 재사용 |
| 온디맨드 모델 추론 | Container image + PC | 모델 가중치 warm 유지 |
'Concurrency & Execution' 카테고리의 다른 글
| Lambda에서 만난 Signature expired — 시계는 멀쩡했다 (0) | 2026.09.13 |
|---|---|
| [EXPRESS] 413 - Payload Too Large (0) | 2024.10.14 |