Skip to content

필사 모드: 내구성 워크플로우 엔진 2026 완벽 가이드 - Temporal · Restate · Hatchet · Inngest · Trigger.dev · Cadence · DBOS · Dapr Workflows 심층 분석

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

프롤로그 — "백그라운드 잡인가, 워크플로우인가?"

2026년 어느 회사의 결제 시스템 회의.

주니어: "결제 후 메일 보내는 건 그냥 큐에 넣고 워커가 처리하면 되죠?"

시니어: "그 워커가 죽으면?"

주니어: "재시도하면 되잖아요."

시니어: "근데 메일은 이미 두 번 갔다면? 환불은 했는데 재고는 안 풀렸다면? 결제는 됐는데 주문 상태는 pending에 멈춰 있다면?"

주니어: "..."

시니어: "그게 워크플로우 엔진이 필요한 순간이야."

이 짧은 대화에 2026년 분산 시스템의 핵심 고민이 담겨 있다. Cron + Celery + Redis로 시작한 백그라운드 잡이, 결제·주문·구독·온보딩·AI 에이전트라는 **다단계 비동기 비즈니스 프로세스**로 진화하면서, 단순 큐로는 감당이 안 되는 영역이 생겼다.

**내구성 실행(durable execution)** — 코드를 짜듯이 워크플로우를 쓰지만, 그 코드의 모든 단계가 영속화돼서 프로세스가 죽었다 깨어나도 정확히 같은 자리에서 이어진다. 2026년 이 패러다임은 Temporal이 만든 카테고리에서 Restate·Hatchet·Inngest·Trigger.dev v3·DBOS가 각자의 답을 내놓는 풍성한 시장으로 변했다.

이 글은 그 전체 지형을 정리한다. 무엇이 내구성 실행인지부터, 각 엔진의 설계 철학, 코드 예제, Saga·Outbox 같은 패턴, AI 에이전트 오케스트레이션에서의 위치, 그리고 한국·일본 빅테크가 무엇을 어떻게 쓰는지까지.

1장 · 내구성 실행이란 무엇인가 — 이벤트 소싱과 리플레이

**Durable execution**의 한 줄 정의는 "함수의 모든 입출력과 비결정적 부분을 이벤트 로그에 영속화하고, 장애 후 재시작 시 로그를 리플레이해 정확히 같은 상태로 복구하는 실행 모델"이다.

이 아이디어의 뿌리는 세 가지에 있다.

1. **이벤트 소싱(event sourcing)** — 상태를 직접 저장하지 않고, 상태를 만든 사건들을 저장한다.

2. **결정적 리플레이(deterministic replay)** — 같은 이벤트 로그에 같은 코드를 돌리면 항상 같은 결과가 나와야 한다.

3. **사이드 이펙트 격리** — 외부 호출(HTTP, DB, 큐)은 한 번만 실행되고, 그 결과가 로그에 저장돼야 재실행해도 중복되지 않는다.

전통적 워크플로우 엔진(BPMN, Airflow)은 DAG 정의를 외부 파일에 두고, 엔진이 그 DAG를 해석해 실행한다. 내구성 실행은 다르다 — **워크플로우 자체가 코드**다. `if`, `for`, `try/catch`, 함수 호출이 모두 워크플로우 정의의 일부고, 엔진은 그 코드 실행을 영속화한다.

차이를 표로.

| 항목 | 전통 워크플로우(Airflow/Argo) | 내구성 실행(Temporal/Restate) |

| --- | --- | --- |

| 정의 형식 | YAML/Python DAG 선언 | 임의의 코드 |

| 분기 | DAG에 명시 | 코드의 `if/else` |

| 장기 대기 | sensor/poke | `sleep(30d)` 같은 함수 호출 |

| 상태 저장 | 외부 DB의 task 상태 | 이벤트 로그 |

| 실패 복구 | 실패한 태스크부터 재시도 | 같은 자리에서 리플레이 재개 |

| 개발 경험 | DSL 학습 | 보통의 코드 |

이 모델의 진정한 가치는 "**`sleep(30d)`가 실제로 30일을 자고 일어나도 메모리에 남아 있는 듯이 동작한다**"는 점이다. 프로세스가 죽고 다른 노드에서 다시 떠도, 이벤트 로그를 리플레이해 같은 자리로 복구된다.

2장 · 왜 지금 워크플로우 엔진이 중요한가 — 다섯 가지 문제

2026년 마이크로서비스 환경에서 워크플로우 엔진이 풀어주는 문제들.

**문제 1 — 분산 사가(distributed saga)**. 주문이 결제·재고·배송·알림 4개 서비스를 거치는데, 3단계에서 실패하면 1·2단계를 보상해야 한다. 데이터베이스 트랜잭션으로는 묶을 수 없다.

**문제 2 — 장기 실행 작업**. 회원 가입 후 7일 트라이얼, 14일 후 결제, 30일 후 만료 — 이 타임라인은 메모리에 들고 있을 수 없고, cron + state machine으로 짜면 코드가 폭주한다.

**문제 3 — AI 파이프라인**. RAG 인덱싱 → 임베딩 → 생성 → 검토 → 게시 같은 다단계 LLM 파이프라인은 단계별 실패율이 다르고, 일부는 분 단위로 오래 걸리며, 비용이 큰 단계는 절대 중복 호출하면 안 된다.

**문제 4 — 멱등성과 재시도**. 외부 API(결제, 메일, SMS)는 네트워크 단절 시 멱등성 키 없이는 재시도가 위험하다. 워크플로우 엔진은 그 멱등 처리를 코드 한 줄로 추상화한다.

**문제 5 — 정확히 한 번(exactly-once)**. 메시지 큐로 흉내 낼 수 있는 "at-least-once + 멱등성"의 한계를 넘어, "각 비즈니스 액션은 정확히 한 번 일어났음"을 강제하는 게 워크플로우 엔진의 코어 약속이다.

요컨대, 2026년 백엔드 엔지니어가 풀어야 할 문제가 점점 "한 번의 HTTP 응답" 모양이 아니라 "여러 시스템을 가로지르며 시간을 가로지르는 프로세스" 모양이라는 것이다.

3장 · Temporal Cloud + Temporal Server 1.25 — 카테고리 정의자

Temporal은 2019년 Maxim Fateev와 Samar Abbas(둘 다 Uber Cadence 원작자)가 창업한 회사로, 사실상 "내구성 실행"이라는 카테고리를 정의했다. 2025년 시리즈 D로 평가가 15억 달러를 넘었다.

핵심 아키텍처.

| 구성 요소 | 역할 |

| --- | --- |

| Frontend | gRPC API gateway |

| History | 이벤트 로그 영속화 (Cassandra/PostgreSQL/MySQL) |

| Matching | 태스크 큐 |

| Worker (Internal) | 시스템 워크플로우(예: 아카이브) |

| **Worker (User)** | 사용자가 SDK로 작성한 워크플로우/액티비티를 실행 |

Temporal Server 1.25(2025년 후반)의 큰 변화.

- **PostgreSQL 16 지원 + 새로운 visibility 백엔드**(ElasticSearch 의존성 줄임).

- **Update with start** — 워크플로우를 시작과 동시에 입력을 전달.

- **Nexus** — 서로 다른 namespace 간 시그널/쿼리를 안전하게 (멀티테넌시).

- **워크플로우 메모이제이션 캐시 개선** — 메모리 사용 50% 절감.

SDK는 Go·Java·Python·.NET·TypeScript·PHP·Ruby가 공식이고, 2025년 Rust SDK가 베타로 추가됐다. 가장 사랑받는 건 TypeScript와 Python.

**TypeScript 워크플로우 예시**.

// workflows/order.ts

const { chargeCard, reserveInventory, ship, sendEmail, refundCard } =

proxyActivities<typeof activities>({ startToCloseTimeout: '1 minute' })

export const cancelOrderSignal = defineSignal('cancelOrder')

export async function orderWorkflow(orderId: string, amount: number) {

let cancelled = false

setHandler(cancelOrderSignal, () => { cancelled = true })

await chargeCard(orderId, amount)

try {

await reserveInventory(orderId)

await ship(orderId)

await sleep('48 hours') // 배송 후 48시간 후 만족도 메일

if (!cancelled) await sendEmail(orderId, 'satisfaction-survey')

} catch (err) {

await refundCard(orderId, amount) // 보상 액션

throw err

}

}

이 코드의 마법은 `sleep('48 hours')`다. 워커가 죽었다 다시 떠도, 다른 호스트에서 다시 시작해도, 48시간 후의 그 시점에 정확히 다음 줄로 이어진다.

워커 실행.

// worker.ts

const worker = await Worker.create({

workflowsPath: require.resolve('./workflows'),

activities,

taskQueue: 'orders',

})

await worker.run()

**Temporal Cloud**는 매니지드 형태로, 2026년 가격은 액션(이벤트) 기반 + active execution. 일반적인 SaaS는 클러스터 자체 운영보다 Cloud가 싸다.

4장 · Cadence (Uber) — Temporal의 조상

Cadence는 2017년 Uber가 오픈소스화한 워크플로우 엔진으로, Temporal의 직계 조상이다. Temporal 공동창업자들이 원래 Uber Cadence 팀을 이끌었고, 2019년 Temporal로 fork·창업했다.

2026년 시점에서 두 시스템의 관계.

- **API/SDK는 유사**하지만 호환되지 않음. Cadence Go SDK 코드를 Temporal로 옮기려면 패키지명·일부 시맨틱을 손봐야 함.

- **Cadence는 여전히 Uber 내부에서 거대 규모로 운영** 중 (수십만 워크플로우 인스턴스/일).

- **Temporal이 OSS 측 혁신을 주도** — Nexus, Workflow Updates, Visibility v2 등 새 기능은 Temporal에서 먼저 나온다.

새 프로젝트라면 Temporal을 권한다. Cadence는 Uber 생태계 또는 기존 Cadence 자산이 있는 곳에서만 유의미.

5장 · Restate — Workflow + RPC, "더 단순한 Temporal"

Restate는 2023년 Stephan Ewen(Apache Flink 공동창업자)이 창업한 회사로, 2025년 1.0이 출시됐다.

설계 결정의 차이.

| 항목 | Temporal | Restate |

| --- | --- | --- |

| 핵심 추상 | 워크플로우 + 액티비티 | 가상 객체(virtual object) + 워크플로우 + 서비스 |

| 영속 저장 | Cassandra/Postgres | 내장 RocksDB + 임의 외부 저장소 |

| 통신 | gRPC + 자체 프로토콜 | HTTP/2 + Connect/gRPC 프로토콜 |

| 배포 | 클러스터(History/Matching/...) | 단일 바이너리 |

| 결정성 | SDK가 보장 | 핸들러 단위 멱등성 |

Restate의 핵심 키워드는 **가상 객체**다. 무상태 핸들러(HTTP 엔드포인트)와 영속 상태를 결합한 단위로, "결제 도메인 객체" 같은 모델을 자연스럽게 표현한다.

**TypeScript 예시**.

const orderService = restate.service({

name: 'OrderService',

handlers: {

async place(ctx: restate.Context, input: { orderId: string; amount: number }) {

const paymentId = await ctx.run('charge', () =>

chargeAPI(input.orderId, input.amount)

)

try {

await ctx.run('reserve', () => reserveInventory(input.orderId))

} catch (err) {

await ctx.run('refund', () => refundAPI(paymentId))

throw err

}

await ctx.sleep(48 * 60 * 60 * 1000) // 48h

await ctx.run('survey', () => sendSurveyEmail(input.orderId))

},

},

})

restate.endpoint().bind(orderService).listen(9080)

`ctx.run(...)`이 사이드 이펙트의 멱등 단위다. 결과가 Restate 서버에 영속화되고, 재실행 시 같은 결과를 그대로 반환한다.

Restate의 매력은 **운영 단순성**이다. 단일 Rust 바이너리, 별도의 SQL 또는 Cassandra 클러스터 없이도 작은 규모는 그대로 동작. AWS·GCP·Azure 매니지드도 베타로 등장 중.

2026년 Restate의 포지셔닝은 "**Temporal의 강력함은 필요한데, 운영 복잡성은 싫은 팀**" 이다. 작은 스타트업이나 단일 서비스에 빠르게 도입하려는 곳에서 채택이 늘었다.

6장 · Hatchet — Postgres 위의 분산 큐 + 워크플로우

Hatchet은 2023년 등장한 오픈소스 워크플로우 엔진으로, **Postgres만으로 동작**한다는 게 핵심 차별점이다.

설계 선언.

- 외부 의존성은 Postgres 하나. Cassandra·Redis·NATS·Kafka 안 씀.

- gRPC + 워커 SDK (Python·TypeScript·Go).

- 멀티테넌시 내장.

- AOR(Acyclic Orchestration Runtime) — DAG처럼 단계를 정의.

**Python 예시**.

from hatchet_sdk import Hatchet, Context

hatchet = Hatchet()

@hatchet.workflow(on_events=["order:created"])

class OrderWorkflow:

@hatchet.step(retries=3, timeout="1m")

def charge(self, ctx: Context):

order = ctx.workflow_input()

return charge_card(order["id"], order["amount"])

@hatchet.step(parents=["charge"])

def reserve(self, ctx: Context):

return reserve_inventory(ctx.workflow_input()["id"])

@hatchet.step(parents=["reserve"])

def ship(self, ctx: Context):

return ship_order(ctx.workflow_input()["id"])

worker = hatchet.worker("orders-worker")

worker.register_workflow(OrderWorkflow())

worker.start()

Hatchet의 강점은 **이미 Postgres를 쓰고 있는 팀**에게 절대 매력적이라는 점이다. 새 인프라 없이 비동기 잡 + 워크플로우 + 큐를 한 시스템으로 통합. 게다가 Python 인기 분야(데이터·AI)에서 빠르게 자리잡았다.

2026년 Hatchet Cloud도 출시돼 매니지드 옵션이 추가됐다.

7장 · Inngest — Step Functions, 개발자 우선

Inngest는 2021년 등장해, "**개발자에게 Step Functions의 정확성을, AWS 락인 없이**" 를 슬로건으로 자리 잡았다. TypeScript 우선 SDK가 가장 잘 만들어졌다는 평가.

핵심 추상은 `step`이다. 함수 안에서 `step.run`, `step.sleep`, `step.sendEvent`, `step.waitForEvent`로 영속 단위를 정의하면, Inngest 엔진이 각 step의 입출력을 저장하고 재실행 시 캐시된 값을 재사용한다.

**TypeScript 예시**.

export const onboarding = inngest.createFunction(

{ id: 'user-onboarding' },

{ event: 'user.signed_up' },

async ({ event, step }) => {

await step.run('send-welcome-email', () => sendEmail(event.data.email, 'welcome'))

await step.sleep('wait-2-days', '2 days')

await step.run('send-tips', () => sendEmail(event.data.email, 'tips'))

const purchase = await step.waitForEvent('await-purchase', {

event: 'order.completed',

timeout: '7d',

match: 'data.userId',

})

if (!purchase) {

await step.run('reminder', () => sendEmail(event.data.email, 'reminder'))

}

}

)

이 코드는 사용자 가입 후 7일짜리 온보딩을 그대로 표현한다. `step.waitForEvent`로 특정 이벤트 도착을 기다리는 게 자연스럽다.

Inngest의 매력은 **다섯 가지가 한 곳에 합쳐졌다**는 것 — 이벤트 큐, 크론, 워크플로우, 함수 호스팅, 옵저버빌리티. 별도의 BullMQ/Sidekiq + Temporal 조합을 한 SaaS로 끝낸다.

가격은 함수 호출(steps) 기반. 작은 스타트업은 무료 티어로 충분히 시작 가능.

8장 · Trigger.dev v3 — 오픈소스 Inngest 대안

Trigger.dev는 2022년 시작했고, v2까지는 SaaS 중심이었다. 2024년 출시된 **v3가 큰 전환**이다.

- **오픈소스화**: AGPL 라이선스로 자체 호스팅 가능.

- **컨테이너 기반 실행**: 작업을 Firecracker 또는 Docker에서 격리 실행.

- **체크포인팅**: 작업 중간에 메모리 스냅샷을 떠서, 긴 작업을 재개 가능.

- **TypeScript 우선**.

**예시**.

export const onboarding = task({

id: 'user-onboarding',

maxDuration: 60 * 60 * 24 * 7, // 7d

run: async (payload: { userId: string; email: string }) => {

await sendEmail(payload.email, 'welcome')

await wait.for({ days: 2 })

await sendEmail(payload.email, 'tips')

const purchase = await wait.forEvent('order.completed', {

timeout: '5d',

filter: (e: any) => e.userId === payload.userId,

})

if (!purchase) {

await sendEmail(payload.email, 'reminder')

}

},

})

Trigger.dev v3의 차별 포인트는 **체크포인팅**이다. 임의의 npm 라이브러리를 호출해도 (예: Puppeteer로 PDF 생성) 중간에 컨테이너를 정지·재개할 수 있다. AI 추론처럼 GPU 자원을 쓰는 작업에 특히 어울린다.

Inngest와 Trigger.dev의 차이.

| 항목 | Inngest | Trigger.dev v3 |

| --- | --- | --- |

| 라이선스 | 비공개(코어 OSS 일부) | AGPL |

| 실행 모델 | 사용자 함수가 HTTP로 호출됨 | Trigger 컨테이너가 사용자 코드를 실행 |

| 자체 호스팅 | 제한적 | 완전 가능 |

| 가격 | step 기반 | 컴퓨트 시간 |

| AI/긴 작업 | 가능하지만 step 분할 필요 | 체크포인팅으로 자연스러움 |

9장 · DBOS — Postgres가 곧 런타임

DBOS는 2023년 MIT의 Mike Stonebraker(PostgreSQL·Vertica·VoltDB) 그룹이 창업했다. 한 줄 요약: "**프로그램 상태를 Postgres에 영속화하는 런타임**".

DBOS의 발상은 이렇다 — 모든 함수 호출, 트랜잭션, 워크플로우 단계의 입출력을 Postgres에 저장한다. 그러면 함수 자체가 **transactional**이고, 실패 후 재시작도 같은 Postgres 트랜잭션 정합성으로 보장된다.

**Python 예시**.

from dbos import DBOS, Queue, WorkflowHandle

from sqlalchemy import text

DBOS()

@DBOS.workflow()

def order_workflow(order_id: str, amount: int):

payment_id = charge_step(order_id, amount)

try:

reserve_step(order_id)

ship_step(order_id)

except Exception:

refund_step(payment_id)

raise

@DBOS.transaction()

def charge_step(order_id: str, amount: int):

DBOS.sql_session.execute(

text("INSERT INTO payments(order_id, amount) VALUES (:o, :a)"),

{"o": order_id, "a": amount},

)

return f"pay-{order_id}"

`@DBOS.workflow()`와 `@DBOS.transaction()` 데코레이터로 영속 단위를 명시한다. 트랜잭션 액티비티는 Postgres에 직접 쓰고, 그 트랜잭션이 워크플로우 상태 업데이트와 같은 트랜잭션에 묶인다 — **DB 정합성 + 워크플로우 정합성 통일**.

2026년 DBOS는 **Postgres 위에서 모든 걸 끝내고 싶은 팀**에서 인기. 단점은 Postgres에 종속된다는 점, 그리고 매우 큰 처리량 워크로드에서 Postgres가 병목이 될 수 있다는 점.

10장 · Dapr Workflows — 쿠버네티스 네이티브 사이드카

Dapr는 마이크로소프트가 2019년 오픈소스화한 마이크로서비스 런타임으로, **사이드카 패턴**(애플리케이션 옆에 Dapr 사이드카가 붙어 상태/큐/이벤트 추상화 제공)이 핵심이다. 2022년 CNCF 졸업.

**Dapr Workflows**는 Dapr 1.10에서 알파로 등장, 1.13(2024)에서 안정화됐다. 내부적으로 **DurableTask** 라이브러리(Azure Durable Functions 코어)를 채택했다.

특징.

- **언어 SDK**: Go·.NET·Python·Java·JavaScript.

- **백엔드 추상화**: state store는 Redis·Postgres·Cosmos DB 등 임의 선택.

- **쿠버네티스에 자연스럽게 통합**: Dapr가 K8s 사이드카로 동작.

**Python 예시**.

from dapr.ext.workflow import WorkflowRuntime, DaprWorkflowContext, WorkflowActivityContext

wfr = WorkflowRuntime()

@wfr.workflow(name="order")

def order_workflow(ctx: DaprWorkflowContext, order: dict):

payment = yield ctx.call_activity(charge, input=order)

try:

yield ctx.call_activity(reserve, input=order)

yield ctx.create_timer(fire_at=ctx.current_utc_datetime + timedelta(hours=48))

yield ctx.call_activity(send_survey, input=order)

except Exception:

yield ctx.call_activity(refund, input=payment)

raise

@wfr.activity(name="charge")

def charge(ctx: WorkflowActivityContext, order: dict):

return charge_card_api(order["id"], order["amount"])

Dapr Workflows의 강점은 **Dapr를 이미 쓰고 있는 K8s 환경에서 추가 인프라 없이 도입 가능**하다는 점. state store만 정해 두면 동일 코드로 백엔드 교체 가능.

약점은 다른 런타임 대비 SDK 완성도와 옵저버빌리티가 아직 한 단계 뒤라는 것.

11장 · AWS Step Functions — 매니지드의 표준

AWS Step Functions(2016년 출시)는 워크플로우 매니지드 서비스의 사실상 표준이다. **JSON으로 정의된 상태 머신**이 핵심.

종류.

| 종류 | 가격 | 용도 |

| --- | --- | --- |

| Standard | 상태 전이당 ($0.025/1000) | 장기 실행, 최대 1년, 정확히 한 번 보장 |

| Express | 실행 시간 + 메모리 | 단기, 최대 5분, at-least-once |

**ASL(Amazon States Language) 예시**.

{

"StartAt": "ChargeCard",

"States": {

"ChargeCard": {

"Type": "Task",

"Resource": "arn:aws:states:::lambda:invoke",

"Parameters": { "FunctionName": "charge-card", "Payload.$": "$" },

"Next": "Reserve"

},

"Reserve": {

"Type": "Task",

"Resource": "arn:aws:states:::lambda:invoke",

"Parameters": { "FunctionName": "reserve-inventory", "Payload.$": "$" },

"Catch": [{ "ErrorEquals": ["States.ALL"], "Next": "Refund" }],

"Next": "Wait48h"

},

"Wait48h": { "Type": "Wait", "Seconds": 172800, "Next": "Survey" },

"Survey": {

"Type": "Task",

"Resource": "arn:aws:states:::lambda:invoke",

"Parameters": { "FunctionName": "send-survey", "Payload.$": "$" },

"End": true

},

"Refund": {

"Type": "Task",

"Resource": "arn:aws:states:::lambda:invoke",

"Parameters": { "FunctionName": "refund-card", "Payload.$": "$" },

"End": true

}

}

}

AWS 락인이 큰 대신 **운영 부담이 사실상 없다**. AWS 생태계의 모든 서비스(Lambda·DynamoDB·SQS·Bedrock·Athena·Glue)와 직접 통합돼 SDK 호출이 한 줄.

비용 함정. Standard는 상태 전이가 많은 워크플로우에서 빠르게 비싸진다. 수백만 실행 + 수십 step이면 월 수천 달러를 쉽게 넘긴다. Express + Map state로 비용 최적화하는 게 표준.

12장 · GCP Workflows + Azure Durable Functions

**Google Cloud Workflows** (2020).

- YAML 또는 JSON 정의.

- HTTP 호출 + 분기 + 병렬.

- Eventarc, Cloud Run, Cloud Functions와 자연스러운 통합.

- 가격: step 실행당.

- 단점: 상태 머신 표현력이 Step Functions보다 단순.

**Azure Durable Functions** (2017).

- Azure Functions의 확장.

- **C#/JavaScript/Python**으로 코드처럼 워크플로우 작성.

- 내구성 실행 진영의 원조 격 — Temporal의 일부 아이디어가 여기서 영감받음.

- DurableTask(오픈소스) 라이브러리가 Dapr Workflows의 코어.

**TypeScript Durable Function 예시**.

df.app.orchestration('orderWorkflow', function* (ctx) {

const order = ctx.df.getInput()

const payment = yield ctx.df.callActivity('chargeCard', order)

try {

yield ctx.df.callActivity('reserveInventory', order)

yield ctx.df.createTimer(new Date(Date.now() + 48 * 3600 * 1000))

yield ctx.df.callActivity('sendSurvey', order)

} catch {

yield ctx.df.callActivity('refundCard', payment)

throw new Error('order failed')

}

})

`yield`마다 체크포인트가 생성된다. 클라우드 락인이지만 정형화돼 있고, Azure 사용자라면 표준 선택.

13장 · Airflow + Dagster + Prefect — 데이터 엔지니어링 DAG

데이터 파이프라인 영역에는 별도의 DAG 엔진이 자리 잡고 있다. 본 글의 범위는 아니지만 비교 차원에서 짚는다.

| 엔진 | 시작 | 강점 | 약점 |

| --- | --- | --- | --- |

| Apache Airflow | 2014 (Airbnb) | 가장 많이 쓰임, 풍부한 연결자 | Python DAG 정의, 동적 워크플로우 약함 |

| Dagster | 2018 | 자산 중심(asset graph), 타입 시스템 | 학습 곡선 |

| Prefect | 2018 | Pythonic API, 동적 워크플로우 | 작은 커뮤니티 |

| Argo Workflows | 2018 | K8s 네이티브, CI/CD에 강함 | Pod 오버헤드 |

데이터 엔지니어링 DAG와 내구성 실행의 결정적 차이.

- **DAG 엔진**: 데이터 자산 변환 그래프, 시간 단위 트리거가 중심.

- **내구성 실행**: 비즈니스 프로세스, 이벤트·시간·시그널이 혼재된 코드 흐름.

2026년 패턴은 "**DAG는 데이터 파이프라인용, 내구성 실행은 비즈니스 로직용**" 으로 분업이 굳어졌다.

14장 · Argo Workflows — 쿠버네티스 CI/CD

Argo Workflows는 2017년 Applatix(인튜이트 인수)가 오픈소스화한 CNCF 졸업 프로젝트로, **모든 단계가 K8s Pod**다.

apiVersion: argoproj.io/v1alpha1

kind: Workflow

metadata: { generateName: build-and-deploy- }

spec:

entrypoint: pipeline

templates:

- name: pipeline

steps:

- - name: build

template: build

- - name: test

template: test

- - name: deploy

template: deploy

- name: build

container: { image: golang:1.23, command: ["go", "build", "./..."] }

- name: test

container: { image: golang:1.23, command: ["go", "test", "./..."] }

- name: deploy

container: { image: argoproj/argocd:v2.12, command: ["argocd", "app", "sync", "main"] }

Argo Workflows는 **K8s 네이티브 CI/CD**의 표준. ML 파이프라인(Kubeflow Pipelines가 Argo 기반), 빌드/배포(Argo CD와 결합), 데이터 파이프라인에 두루 쓰인다.

내구성 실행과의 위치 차이: Argo는 **컨테이너 오케스트레이션 워크플로우**, Temporal/Restate는 **언어 내 영속 실행**. 같은 자리에 둘 다 쓰는 경우도 많다.

15장 · Cloudflare Workflows — Workers + Durable Objects

Cloudflare Workflows는 2024년 9월 베타로 출시됐다. 핵심은 **Cloudflare Workers 위에서 동작하는 내구성 워크플로우**라는 점.

export class OrderWorkflow extends WorkflowEntrypoint<Env, { orderId: string; amount: number }> {

async run(event: WorkflowEvent<{ orderId: string; amount: number }>, step: WorkflowStep) {

const payment = await step.do('charge', async () =>

chargeCard(event.payload.orderId, event.payload.amount)

)

try {

await step.do('reserve', async () => reserveInventory(event.payload.orderId))

await step.sleep('wait 48h', '48 hours')

await step.do('survey', async () => sendSurvey(event.payload.orderId))

} catch (err) {

await step.do('refund', async () => refundCard(payment))

throw err

}

}

}

엣지 컴퓨팅 + 내구성 실행의 조합. 글로벌 엣지에서 실행되므로 지연이 매우 낮고, Durable Objects가 영속 상태를 책임진다. 2026년 GA를 향해 가는 중.

16장 · Conductor (Netflix → Orkes 2022) — JSON DSL

Conductor는 2016년 Netflix가 오픈소스화한 워크플로우 엔진으로, **JSON DSL** 기반이다. 2022년 핵심 팀이 Orkes로 분사해 매니지드 서비스를 운영 중.

{

"name": "order_workflow",

"version": 1,

"tasks": [

{ "name": "charge_card", "type": "SIMPLE", "taskReferenceName": "charge" },

{ "name": "reserve_inventory", "type": "SIMPLE", "taskReferenceName": "reserve" },

{

"name": "wait_48h", "type": "WAIT", "taskReferenceName": "wait48",

"inputParameters": { "duration": "48h" }

},

{ "name": "send_survey", "type": "SIMPLE", "taskReferenceName": "survey" }

]

}

Conductor의 강점은 **언어 중립**이다. JSON DSL + 워커가 어떤 언어로든 가능. Netflix 내부 수천 개의 워크플로우를 운영한 실전 검증이 있다.

약점은 DSL 학습이 별도로 필요하다는 것. 2026년 Conductor는 큰 엔터프라이즈(Netflix 외에도 Walmart·Tesla 인용)에서 쓰이지만, 스타트업 채택은 Temporal/Inngest에 밀린다.

17장 · Zeebe + Camunda 8 — BPMN 기반

Camunda는 2008년 시작한 워크플로우 회사로, 2022년 Camunda 8과 함께 **Zeebe** 엔진(클라우드 네이티브, gRPC)을 메인으로 채택했다.

핵심 특징.

- **BPMN 2.0**: 비즈니스가 이해할 수 있는 시각적 표기.

- **DMN**: 의사결정 테이블.

- **클러스터링**: Zeebe broker + Elasticsearch로 클러스터 구성.

BPMN은 비즈니스/마케팅/오퍼레이션 팀과 워크플로우를 협업하기 좋다. 보험·은행·통신에서 채택률이 높다. 엔지니어가 코드로 짜고 싶다면 Temporal/Restate가 자연스럽고, **비즈니스가 다이어그램으로 본다**가 중요하면 Camunda가 맞다.

18장 · 사가(Saga) 패턴 — 분산 보상 트랜잭션

내구성 워크플로우의 단골 패턴은 **사가**다.

| 단계 | 액션 | 보상 |

| --- | --- | --- |

| 1 | 결제 | 환불 |

| 2 | 재고 차감 | 재고 복원 |

| 3 | 배송 | 배송 취소 |

| 4 | 알림 | (없음) |

3단계에서 실패하면 2 → 1 순으로 보상 액션을 역순 실행. 워크플로우 엔진은 이 흐름을 `try/catch + 보상 호출`로 쉽게 표현한다.

**Temporal에서 사가**.

const { charge, refund, reserve, restore, ship, cancel, notify } =

proxyActivities<typeof activities>({ startToCloseTimeout: '1 minute' })

export async function saga(orderId: string, amount: number) {

const compensations: Array<() => Promise<void>> = []

try {

await charge(orderId, amount)

compensations.push(() => refund(orderId, amount))

await reserve(orderId)

compensations.push(() => restore(orderId))

await ship(orderId)

compensations.push(() => cancel(orderId))

await notify(orderId)

} catch (err) {

for (const compensate of compensations.reverse()) await compensate()

throw err

}

}

**보상의 멱등성**이 핵심. `refund(orderId)`가 두 번 호출돼도 두 번 환불하면 안 된다.

19장 · Outbox 패턴과 멱등성 키

워크플로우 엔진이 풀어주지 못하는(혹은 풀어주는) 두 가지 정합성 도구.

**Outbox 패턴** — DB 트랜잭션과 메시지 발송을 묶기 위해, 비즈니스 변경과 같은 트랜잭션에 "이벤트 보낼 거" 레코드를 outbox 테이블에 쓴다. 별도 디스패처가 outbox 테이블을 읽어 메시지 큐로 보낸다. DBOS는 이 패턴이 자연스럽고, Temporal에서는 활동에서 직접 outbox 테이블에 INSERT 하는 식으로 결합.

BEGIN;

UPDATE orders SET status='paid' WHERE id='o1';

INSERT INTO outbox(topic, payload) VALUES ('order.paid', '{"id":"o1"}');

COMMIT;

**멱등성 키(idempotency key)** — 외부 API(특히 결제) 호출 시 같은 요청을 두 번 보내도 한 번만 처리되도록 키를 함께 전달. Stripe·Adyen·PayPal API는 모두 이 패턴을 지원.

curl -X POST https://api.stripe.com/v1/charges \

-H "Idempotency-Key: order-o1-charge" \

-d amount=10000 -d currency=usd -d source=tok_visa

Temporal/Restate/Inngest는 워크플로우 ID 또는 step ID를 자연스럽게 멱등성 키로 활용. `Idempotency-Key: ${workflowId}-${stepName}` 같은 식.

20장 · 지수 백오프 재시도와 데드 레터

모든 워크플로우 엔진의 표준 기능은 **지수 백오프 재시도**. Temporal RetryPolicy 예시.

const { charge } = proxyActivities<typeof activities>({

startToCloseTimeout: '30 seconds',

retry: {

initialInterval: '1 second',

backoffCoefficient: 2,

maximumInterval: '1 minute',

maximumAttempts: 5,

nonRetryableErrorTypes: ['ValidationError'],

},

})

5번 실패하면 워크플로우는 실패 상태로 가고, 운영자가 수동으로 재시작하거나 데드 레터 큐로 옮긴다. Inngest는 이 자동 데드 레터를 기본 제공.

비결정적 오류(타임아웃, 네트워크)는 재시도해도 되지만, **결정적 오류**(검증 실패, 잘못된 입력)는 재시도해도 똑같이 실패한다. `nonRetryableErrorTypes`로 분리하는 게 표준.

21장 · AI 에이전트 오케스트레이션 — LangGraph · Claude · OpenAI Agents

2025~2026년 가장 빠르게 자라는 워크플로우 활용 영역은 **AI 에이전트**다. 다단계 LLM 파이프라인은 모든 내구성 실행의 매력 — 단계별 비용, 단계별 실패, 멱등성 — 이 그대로 적용된다.

**LangGraph** (LangChain 자매 프로젝트, 2024~). 그래프 기반 에이전트 워크플로우. 노드와 엣지로 상태 머신을 구성.

from langgraph.graph import StateGraph, END

from typing import TypedDict

class State(TypedDict):

question: str

answer: str

graph = StateGraph(State)

graph.add_node("retrieve", lambda s: {"answer": rag(s["question"])})

graph.add_node("review", lambda s: {"answer": review(s["answer"])})

graph.add_edge("retrieve", "review")

graph.add_edge("review", END)

graph.set_entry_point("retrieve")

app = graph.compile()

LangGraph 자체는 "그래프 정의 + 인메모리 런타임"이지만, **LangGraph Cloud**에서 체크포인트 저장과 재개를 제공해 내구성 실행에 가까워진다.

**Anthropic Claude Agent SDK** (2025). 도구 사용 + 핸드오프 기반. Temporal/Restate와 결합해 도구 호출을 액티비티로 래핑하면 자연스러운 내구성 에이전트가 된다.

**OpenAI Agents SDK** (2025). 비슷한 핸드오프 모델. 단일 에이전트가 다른 에이전트로 작업 전달.

세 SDK의 공통점은 **에이전트 자체는 내구성 보장이 약하고**, 그래서 Temporal/Restate/Inngest를 백엔드로 깔아 영속성을 책임지는 패턴이 표준이 되어가고 있다.

22장 · 비교 매트릭스 — 무엇을 언제 고를까

| 엔진 | OSS | 운영 복잡도 | SDK | 강점 | 약점 |

| --- | --- | --- | --- | --- | --- |

| Temporal | Yes (MIT) | 중상 | Go·Java·Py·.NET·TS·PHP·Rust | 가장 강력, 대규모 검증 | Cassandra/PG·운영 부담, 클라우드는 비쌀 수 있음 |

| Restate | Yes (BSL) | 하 | Go·Java·TS·Py·Rust·Kotlin | 운영 단순, 가상 객체 | 신규, 생태계 작음 |

| Hatchet | Yes (MIT) | 하 | Py·TS·Go | Postgres 기반 단순 | 신규, 큰 규모 검증 부족 |

| Inngest | 일부 | 매니지드 | TS·Py·Go | 개발 경험 최고 | 자체 호스팅 제한 |

| Trigger.dev v3 | Yes (AGPL) | 중 | TS | OSS + 체크포인팅 | 컨테이너 오버헤드 |

| DBOS | Yes (MIT) | 하 | Py·TS | Postgres 트랜잭션 통합 | PG 의존, 처리량 한계 |

| Dapr Workflows | Yes (Apache 2.0) | 중 | Go·.NET·Py·Java·JS | K8s·Dapr 생태계 | SDK 성숙도 낮음 |

| AWS Step Functions | No | 매니지드 | JSON DSL | AWS 통합, 운영 0 | AWS 락인, 비용 |

| Azure Durable | No | 매니지드 | C#·JS·Py·Java | Azure 통합 | Azure 락인 |

| GCP Workflows | No | 매니지드 | YAML | GCP 통합 | 표현력 낮음 |

| Cadence | Yes (MIT) | 중상 | Go·Java | Uber 검증 | Temporal에 밀리는 추세 |

| Conductor | Yes (Apache 2.0) | 중 | 언어 중립 워커 | JSON DSL, 언어 중립 | DSL 학습 |

| Camunda 8 / Zeebe | 일부 | 중상 | BPMN + 클라이언트 | BPMN, 비즈니스 협업 | 무거움 |

| Cloudflare Workflows | No | 매니지드 | TS | 엣지 + 워커 | 베타, 단기 작업 위주 |

**한 줄 가이드**.

- "현실 검증된, 가장 강력한" → Temporal.

- "운영 단순함, 비슷한 표현력" → Restate.

- "Postgres만 쓰고 싶다" → Hatchet 또는 DBOS.

- "TS 코드로 빠르게, 매니지드" → Inngest.

- "OSS 매니지드 대안, 긴 작업/AI" → Trigger.dev v3.

- "AWS만 쓰는데 운영 0" → Step Functions.

- "K8s + Dapr 환경" → Dapr Workflows.

- "비즈니스 BPMN 협업" → Camunda 8.

23장 · 한국 빅테크 채택 사례

**토스(Toss)** — 금융 거래의 내구성 트랜잭션에 내부 워크플로우 엔진을 구축, 2024년 컨퍼런스에서 Temporal 도입 경험을 발표(2023~). 결제·정산·이체 도메인에서 사가 패턴 활용.

**쿠팡(Coupang)** — 주문 파이프라인의 다단계 처리에 내부 워크플로우 엔진과 AWS Step Functions를 혼용. 새 마이크로서비스에서는 Temporal 도입을 평가 중.

**네이버(Naver)** — Naver Cloud 내부 자동화에 Argo Workflows + 자체 엔진. 검색·쇼핑의 배치 처리는 자체 분산 잡 시스템.

**NC소프트(NCsoft)** — 게임 상태 머신, 길드 이벤트 등 장기 비동기 처리에 Cadence/Temporal류 검토 사례 공유.

**라인플러스 / LY** — 메시지·결제·광고의 비동기 처리에 Kafka + 자체 워크플로우 엔진. 일부 도메인은 Temporal POC 진행.

**카카오** — 카카오톡 알림·결제 파이프라인. 자체 비동기 처리 인프라가 강하고, 새 도메인에는 Temporal·Inngest 평가.

공통점은 **결제와 주문 영역**에서 가장 먼저 내구성 실행 도입을 검토한다는 점. 트랜잭션 정합성 + 보상 + 운영 가시성을 동시에 풀어야 하기 때문.

24장 · 일본 빅테크 채택 사례

**Mercari** — 결제·송금 도메인에 자체 워크플로우 엔진과 일부 Temporal POC. 마이크로서비스화가 가장 진전된 사례로 알려져 있다.

**LINE Yahoo (LY Corporation)** — 합병 후 통합 주문/결제 파이프라인 구축에 Kafka + 워크플로우 엔진을 혼용. 자체 엔진 + 부분적으로 Temporal.

**Rakuten** — 공급망·구독·포인트 시스템. AWS Step Functions와 Apache Airflow가 두 축, 새 도메인은 Temporal Cloud 평가.

**Recruit** — Indeed/SUUMO 등 자회사가 다양. 일부 팀은 Inngest, 일부는 Airflow + 자체 DAG.

**SmartHR / freee** — SaaS HR/회계. 비동기 잡 + 워크플로우 통합에 Temporal·Inngest를 활발히 검토.

**NTT Data** — 엔터프라이즈 통합에 Camunda BPMN 채택률 높음.

일본 시장의 특징: 엔터프라이즈에서는 BPMN(Camunda) 채택률이 한국·미국보다 상대적으로 높다. 스타트업/모던 SaaS에서는 Temporal·Inngest가 빠르게 자리잡는 중.

25장 · 시작하기 — 30분 안에 첫 내구성 워크플로우

가장 빠른 시작은 Temporal CLI + TypeScript 예제.

1. Temporal Server 띄우기

brew install temporal

temporal server start-dev

2. 새 프로젝트

npx @temporalio/create@latest hello-temporal

cd hello-temporal

3. 워커 + 클라이언트

npm install

npm run start.watch # 워커

npm run workflow # 워크플로우 실행

Inngest는 더 빠르다.

npx inngest-cli@latest dev

별도 터미널

mkdir hello-inngest && cd $_

npm init -y

npm install inngest

Restate.

docker run -d --name restate -p 8080:8080 -p 9070:9070 docker.restate.dev/restatedev/restate:latest

npm install @restatedev/restate-sdk

세 엔진의 첫 워크플로우는 모두 30분 내. 그 다음은 자기 도메인의 가장 골치 아픈 비동기 흐름 하나를 골라 옮겨보는 것 — "결제 → 환불", "회원 가입 → 트라이얼 만료", "AI 인덱싱 → 검토" 같은.

26장 · 안티패턴과 흔한 실수

내구성 워크플로우를 잘못 쓰는 흔한 케이스.

**1. 모든 걸 워크플로우로 만들기**. 단순 백그라운드 잡(이메일 1개 발송)에는 BullMQ/Sidekiq/Celery로 충분. 워크플로우 엔진은 "다단계 + 시간 가로지름 + 보상 필요"에 어울린다.

**2. 결정성 깨기**. 워크플로우 코드 안에서 직접 `Date.now()`, `Math.random()`, `fetch(...)`를 호출하면 리플레이가 깨진다. 항상 `proxyActivities` / `ctx.run` / `step.run`을 통해서.

**3. 큰 페이로드 전달**. 워크플로우 입출력은 이벤트 로그에 저장된다. MB 단위 페이로드는 로그가 폭주. S3 키만 전달하고 액티비티 안에서 읽는 게 표준.

**4. 워크플로우 안에서 무한 루프**. `while(true)`로 폴링하지 마라. Temporal은 `continueAsNew`, Restate는 새 세션, Inngest는 새 이벤트로 워크플로우를 갱신.

**5. 보상 누락**. 사가의 본질은 보상이다. "보상 액션이 실패하면?"이라는 질문을 항상 함께 답하라.

**6. 시그널 폭주**. 시그널은 워크플로우의 상태를 비결정적으로 만들 수 있다. 시그널 처리 순서와 idempotency를 신중히.

**7. 매니지드 비용 무시**. Temporal Cloud / Step Functions는 액션 단위 과금이다. 1초마다 폴링하는 워크플로우는 한 달에 수천 달러를 쉽게 넘긴다.

27장 · 마치며 — "코드처럼 워크플로우를"

2026년 워크플로우 엔진의 큰 흐름.

1. **코드 중심으로 통일**. JSON/YAML/BPMN DSL은 입지가 줄고, "일반 코드로 짜고 엔진이 영속화" 패러다임이 주류가 됐다.

2. **개발자 우선**. Inngest·Trigger.dev·Hatchet의 부상은 DX(developer experience)가 결정적 차별점이 됐음을 보여준다.

3. **AI 에이전트 결합**. LangGraph·Claude·OpenAI Agents SDK가 모두 내구성 실행 백엔드 필요성에 닿고 있다.

4. **운영 단순성 경쟁**. Restate·DBOS·Hatchet은 모두 "Temporal보다 운영 쉽다"를 핵심 어필로 삼는다.

5. **클라우드 매니지드 성숙**. Temporal Cloud, Inngest Cloud, Restate Cloud, Trigger.dev Cloud — 자체 운영을 피할 수 있는 선택지가 다양해졌다.

처음 도입하는 팀에게 권하는 흐름은 이렇다.

1. 가장 골치 아픈 비동기 비즈니스 프로세스 한 개를 고른다(보통은 결제 또는 온보딩).

2. Temporal Cloud 또는 Inngest로 매니지드로 시작한다.

3. 워크플로우 정의를 코드로 짜고, 액티비티는 작고 멱등하게 유지한다.

4. 사가 + 멱등성 키 + 보상을 명시적으로 설계한다.

5. 운영 가시성(워크플로우 상태, 재시도, 데드 레터)을 확인한다.

워크플로우 엔진은 "더 많은 인프라"가 아니라 "**비즈니스 로직을 더 잘 표현할 수 있는 새 추상**"이다. 잘 쓰면, 분산 시스템의 가장 까다로운 부분이 "그냥 코드"가 된다.

참고 자료

1. [Temporal — Open Source Durable Execution Platform](https://temporal.io/)

2. [Temporal Cloud Documentation](https://docs.temporal.io/cloud)

3. [Temporal Server 1.25 Release Notes](https://github.com/temporalio/temporal/releases)

4. [Cadence Workflow — Uber Open Source](https://cadenceworkflow.io/)

5. [Restate — Distributed Application Toolkit](https://restate.dev/)

6. [Hatchet — Postgres-backed Workflow Engine](https://hatchet.run/)

7. [Inngest — Reliable Background Jobs and Workflows](https://www.inngest.com/)

8. [Trigger.dev v3 — Open Source Background Jobs](https://trigger.dev/)

9. [DBOS — Database-Backed Durable Programs](https://www.dbos.dev/)

10. [Dapr Workflows Documentation](https://docs.dapr.io/developing-applications/building-blocks/workflow/)

11. [AWS Step Functions Documentation](https://docs.aws.amazon.com/step-functions/)

12. [Azure Durable Functions Overview](https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview)

13. [Google Cloud Workflows](https://cloud.google.com/workflows)

14. [Cloudflare Workflows Documentation](https://developers.cloudflare.com/workflows/)

15. [Conductor / Orkes](https://orkes.io/)

16. [Camunda 8 Documentation](https://docs.camunda.io/)

17. [Apache Airflow](https://airflow.apache.org/)

18. [Dagster](https://dagster.io/)

19. [Prefect](https://www.prefect.io/)

20. [Argo Workflows](https://argoproj.github.io/workflows/)

21. [Saga Pattern — microservices.io](https://microservices.io/patterns/data/saga.html)

22. [Outbox Pattern — microservices.io](https://microservices.io/patterns/data/transactional-outbox.html)

23. [Stripe API — Idempotency](https://docs.stripe.com/api/idempotent_requests)

24. [LangGraph Documentation](https://langchain-ai.github.io/langgraph/)

25. [Anthropic Claude Agent SDK](https://docs.anthropic.com/en/docs/agents)

26. [OpenAI Agents SDK](https://github.com/openai/openai-agents-python)

27. [Maxim Fateev — Designing Temporal (QCon)](https://www.infoq.com/presentations/temporal-design/)

28. [Mercari Engineering Blog — Microservices](https://engineering.mercari.com/en/)

현재 단락 (1/556)

2026년 어느 회사의 결제 시스템 회의.

작성 글자: 0원문 글자: 23,607작성 단락: 0/556