긴 대기는 워커가 아니라 상태로 버텨야 한다: Lambda durable functions로 보는 재시도 설계
사용자 승인, 외부 콜백, AI 작업처럼 오래 기다리는 일을 “잠자는 워커”가 아니라 “재개 가능한 상태”로 만들려면 무엇을 먼저 설계해야 할까?
긴 대기는 워커가 아니라 상태로 버텨야 한다: Lambda durable functions로 보는 재시도 설계
- 카테고리: infra_dev
- 예상 읽기 시간: 10분
- 오늘의 질문: 사용자 승인, 외부 콜백, AI 작업처럼 오래 기다리는 일을 “잠자는 워커”가 아니라 “재개 가능한 상태”로 만들려면 무엇을 먼저 설계해야 할까?
- 핵심 출처:
- Build multi-step applications and AI workflows with AWS Lambda durable functions - 게시일 미표기, 확인일 2026-06-17
- Best practices for Lambda durable functions using a fraud detection example - 게시일 미표기, 확인일 2026-06-17
- Idempotency - AWS Lambda - 문서, 확인일 2026-06-17
- How Lambda handles errors and retries with asynchronous invocation - 문서, 확인일 2026-06-17
- Idempotency - Powertools for AWS Lambda (TypeScript) - 문서, 확인일 2026-06-17
1. 왜 지금 봐야 하나
작은 팀의 백그라운드 작업은 처음에는 단순합니다. 결제 후 영수증을 보내고, 가입 후 온보딩 메일을 보내고, AI 분석 결과가 끝날 때까지 기다립니다. 그런데 작업이 몇 초를 넘어 몇 분, 몇 시간, 하루 이상으로 길어지는 순간부터 문제의 종류가 바뀝니다.
가장 흔한 실수는 “워커를 계속 켜두고 기다리기”입니다. HTTP 서버든 Lambda든 컨테이너든, 실행 중인 프로세스가 아무 일도 하지 않고 외부 승인이나 콜백을 기다리면 비용이 새고, 배포 중단·타임아웃·스케일 인에 취약해집니다. 더 위험한 점은 실패 후 재시작했을 때 어디까지 처리했는지 애매해져 중복 결제, 중복 알림, 중복 DB 업데이트가 발생한다는 것입니다.
AWS가 Lambda durable functions를 내놓으며 강조한 지점도 여기에 있습니다. 긴 워크플로를 “계속 실행되는 함수”로 보는 대신, 체크포인트와 재생 가능한 상태의 흐름으로 다루자는 것입니다. 특정 플랫폼 기능을 외우는 것이 목적은 아닙니다. 오늘 가져갈 개념은 “긴 대기 작업은 CPU 시간이 아니라 상태 전이를 설계하는 문제”라는 점입니다.
2. 핵심 개념
Durable execution의 핵심은 세 가지입니다.
첫째, step입니다. 비즈니스 로직을 여러 단계로 쪼개고, 각 단계가 끝날 때 결과를 저장합니다. 나중에 함수가 다시 실행되면 이미 끝난 step은 다시 수행하지 않고 저장된 결과를 반환합니다. 이것이 체크포인트입니다.
둘째, wait입니다. 외부 승인, 예약 시간, 콜백, 폴링 대기를 만났을 때 프로세스를 계속 붙잡지 않습니다. 실행을 멈추고 상태만 남긴 뒤, 조건이 충족되면 다시 이어갑니다. AWS 설명에 따르면 Lambda durable functions는 정의된 지점에서 최대 1년까지 실행을 중단할 수 있고, 대기 중에는 온디맨드 함수의 idle compute 비용을 내지 않는 모델입니다.
셋째, replay입니다. 장애나 재개 시 핸들러를 처음부터 다시 실행하되, 완료된 durable operation은 건너뜁니다. 이 말은 코드가 “위에서 아래로 한 번만 실행된다”는 직관을 버려야 한다는 뜻입니다. durable workflow 코드는 다시 실행될 수 있고, 그래서 step 내부의 부작용은 멱등성을 가져야 합니다.
짧게 정리하면 이렇습니다.
워커는 일을 하는 곳이고, durable execution은 일이 어디까지 끝났는지 기억하는 방식이다.
3. 최신 이슈와 연결
AWS News Blog는 Lambda durable functions가 일반 Lambda 함수 모델에 상태 추적, 자동 재시도, 체크포인트, 실패 후 replay, 최대 1년 대기를 붙인다고 설명합니다. Compute Blog의 사기 탐지 예시는 더 현실적입니다. 낮은 위험 결제는 바로 승인하고, 중간 위험 결제는 SMS와 이메일을 보내고 최대 24시간 응답을 기다린 뒤, 응답이 없으면 에스컬레이션합니다.
이 예시가 중요한 이유는 “긴 작업”의 대부분이 실제로는 긴 계산이 아니기 때문입니다. 오래 걸리는 것은 CPU가 아니라 사람, 외부 API, 다른 시스템의 응답입니다. 따라서 긴 실행 시간을 늘리는 것보다, 대기 상태를 안전하게 저장하고 재개하는 쪽이 더 안정적입니다.
동시에 AWS 문서는 조심해야 할 사실도 명확히 말합니다. durable function의 실행 이름은 중복 실행을 막는 idempotency key처럼 동작하지만, step은 기본적으로 at-least-once 실행 의미를 가집니다. 즉, 완료된 step은 checkpoint로 건너뛸 수 있지만, 완료되기 전 실패한 step은 여러 번 실행될 수 있습니다. Event Source Mapping은 출시 시점에 durable execution idempotency를 직접 지원하지 않으므로, Powertools 같은 애플리케이션 레벨 멱등성 또는 dispatcher Lambda로 실행 이름을 명시하는 우회가 필요합니다.
4. 개발자 관점 해석
이 주제는 AWS만의 이야기가 아닙니다. 큐, 워커, cron, 서버리스, Kubernetes Job을 쓰는 모든 팀에 같은 질문을 던집니다.
재시도는 기능이 아니라 부작용 증폭기입니다. 재시도가 없으면 일시 장애에 약하지만, 재시도를 켜면 같은 이벤트가 여러 번 처리될 수 있습니다. Lambda 비동기 호출 문서는 함수 오류 시 기본적으로 두 번 더 재시도하고, throttling이나 5xx 계열 시스템 오류는 최대 6시간 동안 큐에 되돌려 재시도할 수 있다고 설명합니다. 또한 함수가 오류를 반환하지 않아도 eventually consistent queue 특성 때문에 같은 이벤트를 여러 번 받을 수 있다고 경고합니다.
그래서 설계 순서는 “재시도 몇 번?”이 아니라 “무엇을 중복해도 안전하게 만들 것인가?”가 먼저입니다.
- 결제 API 호출: 외부 API의 idempotency key를 반드시 사용합니다.
- DB 업데이트: 주문 ID, 이벤트 ID, 실행 이름 같은 자연 키로 upsert하거나 transaction으로 보호합니다.
- 알림 발송: 알림 로그에 unique key를 두고, 중복 발송을 감지합니다.
- 파일 생성/리포트 생성: 결과 객체 경로를 deterministic하게 만들고 덮어쓰기/버전 정책을 정합니다.
- 외부 시스템이 멱등성을 지원하지 않음: at-most-once에 가까운 보호를 선택하되, 실패 시 자동 복구보다 수동 확인을 택해야 할 수 있습니다.
비용 관점도 있습니다. 긴 대기를 실행 중 컨테이너로 붙잡으면 단순하지만 비용이 예측 불가능해집니다. durable state나 큐, DB를 쓰면 별도 저장 비용과 복잡도가 생기지만, idle compute를 줄이고 장애 복구 지점을 명확히 만들 수 있습니다. 보안 관점에서는 실행 이름이나 idempotency key에 개인정보·토큰을 직접 넣지 말고, 추측하기 어려우면서도 감사 가능한 업무 식별자를 써야 합니다.
5. 내 프로젝트에 적용할 체크포인트
긴 백그라운드 작업이 있다면 아래 질문으로 먼저 분류해보세요.
- 이 작업은 실제 계산이 긴가, 아니면 외부 응답을 기다리는 시간이 긴가?
- 중간 단계 중 “두 번 실행되면 안 되는” 부작용은 무엇인가?
- 재시도 단위는 전체 워크플로인가, 개별 step인가?
- 중복 이벤트를 식별할 안정적인 키가 있는가? 예: order_id, transaction_id, webhook event_id.
- 키가 같고 payload가 다르면 에러로 막을 것인가, 새 버전으로 처리할 것인가?
- 실패한 이벤트는 어디에 남길 것인가? DLQ, on-failure destination, audit table 중 무엇인가?
- 대기 시간이 길 때 compute 비용을 계속 지불하고 있지는 않은가?
- 배포 중 코드가 바뀌어도 suspended workflow가 같은 의미로 replay되는가? AWS는 프로덕션에서 Lambda versions 사용을 권장합니다.
- event source mapping, queue consumer, webhook ingress 중 어디에서 idempotency key를 부여할 것인가?
- 멱등성 저장소의 TTL은 비즈니스 재시도 기간보다 충분히 긴가?
특히 작은 팀은 “나중에 DLQ 보자”라고 미루기 쉽습니다. 하지만 DLQ는 실패 쓰레기통이 아니라 replay 계약입니다. 어떤 메시지를 다시 넣어도 안전한지, 오래된 메시지를 버릴 기준은 무엇인지, 수동 처리 담당자는 누구인지까지 정해야 합니다.
6. 오늘 10분 액션
오늘은 코드를 고치지 말고 표 하나만 만드세요. 최근 만든 백그라운드 작업 하나를 골라 아래 네 칸을 채웁니다.
| 단계 | 부작용 | idempotency key | 실패 시 처리 |
|---|---|---|---|
| 예: 주문 검증 | 없음/읽기 중심 | order_id | 재시도 가능 |
| 예: 결제 승인 | 카드 승인 | transaction_id 또는 외부 API idempotency key | 중복 금지, 실패 시 수동 확인 |
| 예: 알림 발송 | SMS/이메일 | transaction_id + channel | 중복 발송 로그 확인 |
| 예: 결과 저장 | DB 상태 변경 | order_id + target_state | transaction/upsert |
그 다음 한 문장을 적습니다.
이 워크플로에서 재시도해도 안전한 단계는 ___이고, 재시도 전에 멱등성 키가 필요한 단계는 ___이다.
이 한 문장이 없으면 retry, queue, durable function, cron을 무엇으로 바꿔도 같은 장애가 반복됩니다.
7. 더 볼 자료
- AWS Lambda durable functions launch blog: Lambda 안에서 step, wait, callback, replay를 어떻게 설명하는지 확인하기 좋습니다.
- AWS Compute Blog의 fraud detection 예시: human-in-the-loop 워크플로에서 at-least-once step과 at-most-once 선택의 tradeoff를 보여줍니다.
- AWS Lambda idempotency 문서: execution name이 중복 실행을 어떻게 막는지, event source mapping에서 무엇을 조심해야 하는지 정리되어 있습니다.
- Lambda asynchronous invocation error handling 문서: 기본 재시도, throttling 재시도, 이벤트 만료, DLQ/on-failure destination의 차이를 확인하세요.
- Powertools for AWS Lambda TypeScript idempotency 문서: DynamoDB, Valkey, Redis 기반 idempotency record를 구현할 때 참고할 수 있습니다.
중복 회피 메모
최근 infra_dev 글은 GitHub Actions 장애와 외부 제어면 의존성, Cloudflare Queues의 backlog/DLQ, PostgreSQL 19 관측 지표, Docker docker cp 보안 경계, GKE standby buffer, OpenTelemetry Collector, Cloud Run worker pool과 Pub/Sub/Kafka backpressure, OIDC 기반 secret 축소를 다뤘습니다. 이번 글은 큐 백로그나 CI 장애를 반복하지 않고, AWS Lambda durable functions와 Lambda/Powertools 문서를 바탕으로 “긴 대기 워크플로를 실행 시간 대신 checkpoint, replay, idempotency state로 설계하는 법”에 집중합니다.
핵심 출처
로그인하면 이 글을 북마크하고, 나만 보는 한 줄 메모를 남길 수 있어요.
댓글 0
최신순 ▾혹시 이 글을 읽는 동료 개발자가 있다면, GitHub으로 로그인하고 한 줄 흔적을 남겨줘요. (스팸 방지용 로그인이에요)