장기 실행 분산 워크플로우의 장애 복구를 자동화하는 Temporal Durable Execution과 결정적 리플레이 아키텍처

장기 실행 분산 워크플로우의 장애 복구를 자동화하는 Temporal Durable Execution과 결정적 리플레이 아키텍처
장기 실행 분산 워크플로우의 장애 복구를 자동화하는 Temporal Durable Execution과 결정적 리플레이 아키텍처

1. 장기 실행 자동화 파이프라인의 상태 유실과 보일러플레이트 병목

결제 정산, 다단계 데이터 ETL, AI 에이전트 오케스트레이션처럼 수 분에서 수 주에 걸쳐 실행되는 장기 실행 워크플로우(Long-Running Workflow)는 실행 도중 워커 프로세스 크래시, 컨테이너 OOM 종료, 네트워크 타임아웃에 상시 노출됩니다. 이를 전통적인 상태 테이블과 크론잡(Cron Job) 조합으로 구현하면 단계별 체크포인트 컬럼 관리, 분산 락, 재시도 스케줄러, 정합성 보정 배치 등 본질적인 비즈니스 로직보다 장애 복구 보일러플레이트 코드가 수배 이상 비대해집니다.

이러한 구조적 복잡성을 플랫폼 레벨로 추상화하여 코드가 중단 없이 끝까지 완주되도록 보장하는 패러다임이 바로 Durable Execution(지속 가능 실행)입니다.

2. Temporal Durable Execution의 3계층 아키텍처와 Command·Event 매핑

에 따르면, Temporal은 워크플로우 코드가 외부 부작용(Side Effect)을 직접 실행하지 않고 Command(명령)를 발행하면 서버가 이를 Event History에 영속화하는 이벤트 소싱 기반 상태 머신으로 동작합니다.

  • Workflow(결정적 오케스트레이션 계층): 비즈니스 흐름과 상태 전이를 정의하며, Activity 호출이나 타이머 대기 시 실제 I/O 대신 ScheduleActivityTask, StartTimer 같은 Command를 Temporal Service에 전송합니다.
  • Activity(비결정적 I/O 격리 계층): 외부 REST API 호출, 데이터베이스 쓰기, 파일 처리 등 실패 가능성이 높은 실제 작업은 별도의 Activity Task Queue를 통해 폴링한 워커가 독립적으로 실행하고 결과만 History Service에 보고합니다.
  • Event History(추가 전용 감사·복구 로그): 워크플로우의 시작(WorkflowExecutionStarted)부터 타이머 만료, Activity 완료 결과까지 모든 상태 전이가 데이터베이스에 불변 시퀀스로 기록됩니다.

3. 결정적 리플레이(Deterministic Replay)와 Continue-As-New 설계 원칙

에 명시된 바와 같이, 실행 중인 워커가 크래시되면 새로운 워커가 Event History를 처음부터 고속 리플레이(Replay)하여 크래시 직전의 로컬 변수와 콜 스택 상태를 100% 재구성합니다. 리플레이 중 이미 완료된 Activity는 재실행하지 않고 기록된 ActivityTaskCompleted 결과값만 즉시 주입하며, 미완료 지점부터 실제 실행을 재개합니다.

  • 결정성 제약(Deterministic Constraints): 동일한 입력과 Event History를 리플레이할 때 워크플로우 코드는 반드시 동일한 순서의 Command를 생성해야 합니다. 따라서 워크플로우 내부에서 datetime.now(), random(), 직접 네트워크 호출을 사용하면 리플레이 시 시퀀스 불일치(Non-determinism Error)가 발생하므로 반드시 SDK 제공 결정적 API(workflow.now())를 사용해야 합니다.
  • 히스토리 상한선과 Continue-As-New: 단일 워크플로우 실행의 Event History는 최대 51,200개 이벤트(또는 50MB)로 제한되므로, 무한 루프형 액터 워크플로우는 주기적으로 Continue-As-New를 호출해 현재 상태를 인자로 넘기며 새 히스토리 체인으로 원자적 전환해야 합니다.

4. 프로덕션 Temporal Python SDK 워크플로우 및 Activity 격리 구현

다음은 를 준수하여 비결정적 외부 결제를 Activity로 격리하고 지수 백오프 재시도 정책과 결정적 시간 API를 결합한 구현체입니다.

5. 상태 관리 방식별 운영 지표 비교 및 프로덕션 도입 가이드

10단계 외부 API 연동과 지연 대기를 포함하는 장기 실행 파이프라인(월 100만 건 처리)에서 DB 상태 폴링 아키텍처와 Temporal Durable Execution의 엔지니어링 지표를 비교한 결과는 다음과 같습니다.

DB 상태 테이블 + Cron 폴링 Temporal Durable Execution
별도 이력 테이블 수동 로깅

프로덕션 환경에 본 아키텍처를 도입할 때는 다음 사항을 반드시 설계에 반영해야 합니다.

  • Activity 멱등성 키(Idempotency Key) 결합: Activity 타임아웃(start_to_close_timeout) 초과 후 재시도가 발생할 때 외부 API가 중복 처리되지 않도록 workflow.info().workflow_id와 activity.info().activity_id 조합을 멱등성 키로 전달해야 합니다.
  • 워크플로우 버저닝(Patching) 전략: 장기 실행 중인 워크플로우가 수천 건 대기 중인 상태에서 코드를 배포할 때는 workflow.patched() API를 사용해 기존 리플레이 경로와 신규 실행 경로를 분기해야 결정성 붕괴를 방어할 수 있습니다.
  • Heartbeat를 통한 장시간 Activity 생존 확인: 대용량 파일 변환이나 LLM 배치 추론처럼 수십 분 걸리는 Activity는 주기적으로 activity.heartbeat()를 호출하여 워커 다운 시 타임아웃 만료 전 즉각 재할당되도록 구성해야 합니다.

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다