필사 모드: 듀러블 실행 & 워크플로우 엔진 2026 — Temporal·Inngest·Trigger.dev·Hatchet·Restate·DBOS·Step Functions 심층 비교 (장기 실행 AI 에이전트 시대의 인프라)
한국어프롤로그 — 8시간 동안 죽지 않는 함수
2026년 봄, 한 AI 스타트업의 엔지니어가 슬랙에 글을 남긴다.
"에이전트가 PR 리뷰를 50개 처리하다가 14번째에서 OpenAI 429를 맞았다. 컨테이너가 OOM으로 죽었다. 다시 돌리면 1~13번을 또 한다. 우리 LLM 비용은 두 번씩 나간다."
이 문장이 2026년 워크플로우 엔진 르네상스의 한 줄짜리 요약이다. **AI 에이전트는 장기 실행이다.** 한 작업이 8시간을 돌고, 도중에 외부 API 100개를 호출하고, 그중 하나가 실패한다. 컨테이너는 OOM·재배포·preemption으로 언제든 죽는다. 그런데 비즈니스는 "1번부터 다시 돌리지 말고, 14번부터 이어 돌려달라"고 한다.
이 요구를 풀기 위해 나온 기술이 **듀러블 실행(durable execution)** 이다. 함수가 죽어도 마지막 단계의 상태를 디스크가 기억하고, 재시작 시 그 지점부터 결정론적으로 리플레이한다. 2016년 Uber Cadence가 처음 대중화했고, 2019년 Temporal이 포크해 오픈소스로 폭발시켰고, 2023~2025년 Inngest·Trigger.dev·Hatchet·Restate·DBOS가 각자 다른 각도로 이 시장에 진입했다.
이 글은 2026년 현재 워크플로우 엔진 지도를 그린다. 듀러블 실행 의미론부터, Temporal·Inngest·Trigger.dev·Hatchet·Restate·DBOS의 아키텍처 차이, AWS Step Functions·Airflow·Prefect·Dagster의 자리, 사가 패턴과 멱등성과 정확히 한 번 의미론, 그리고 한국·일본의 실제 사례까지.
1장 · 듀러블 실행이란 무엇인가 — 한 문장 정의
먼저 한 문장. **듀러블 실행은, 함수의 실행 상태가 외부 저장소에 영속(durable)되어서, 프로세스가 죽어도 마지막 진행 지점부터 결정론적으로 재개되는 실행 모델이다.**
이걸 풀면 세 가지 기둥이 나온다.
1. **이벤트 소싱(event sourcing)** — 함수가 한 단계 실행할 때마다 그 결과를 이벤트 로그에 추가한다. 함수 자체의 코드가 아니라 함수 실행의 역사가 진실의 원천이다.
2. **결정론적 리플레이(deterministic replay)** — 함수가 죽으면 새 워커가 같은 코드를 처음부터 다시 돌린다. 단, 외부 호출은 진짜로 호출하지 않고 이벤트 로그에서 결과를 가져온다. 외부에 부작용 없이 상태만 복원하는 셈이다.
3. **멱등성(idempotency)** — 같은 작업을 두 번 실행해도 결과가 같아야 한다. 결제 같은 외부 부작용은 멱등성 키로 보호된다.
이 세 가지가 모이면 "함수가 죽어도 안 죽은 척한다"는 마법이 가능해진다. 그래서 듀러블 실행을 "**가상 머신처럼 동작하는 함수**"라고도 부른다. 실제 머신은 죽지만 가상 머신은 영원히 산다.
여기서 결정적인 제약이 따라온다. **워크플로우 함수는 결정론적이어야 한다.** `Math.random()`·`Date.now()`·환경 변수 읽기·외부 API 직접 호출 같은 비결정적 연산은 SDK가 제공하는 결정론적 래퍼를 통해야 한다. 그렇지 않으면 리플레이 시 다른 길로 분기해버린다.
2장 · 워크플로우 엔진의 4가지 큰 갈래 — 2026년 지도
2026년 워크플로우 시장은 크게 네 갈래로 나뉜다.
- **듀러블 실행 SDK** — Temporal, Cadence, Restate, DBOS. 워크플로우를 코드로 쓰고 결정론적 리플레이로 영속한다. 장기 실행·복잡한 분기에 강하다.
- **이벤트 기반 함수 플랫폼** — Inngest, Trigger.dev. 이벤트가 함수를 호출하고, 함수 안의 `step.run`이 듀러블 경계가 된다. DX 친화적, AI 에이전트·SaaS 워크플로우에 강하다.
- **태스크 큐 + 워크플로우** — Hatchet, Celery+orchestration. Postgres·Redis 위에 짠 큐로, 단순한 큐의 진화. 단순함과 운영 비용이 강점.
- **DAG 오케스트레이션 (배치 ETL)** — Airflow, Prefect, Dagster, Argo Workflows. 데이터 파이프라인 중심, 스케줄된 DAG 실행. 듀러블 실행과는 자리가 다르다.
이외에 BPMN 기반 엔진(Camunda)과 마이크로서비스 오케스트레이션(Netflix Conductor)이 별도 자리를 차지한다. AWS Step Functions는 상태머신 DSL 기반이라 "duraable이긴 한데 코드가 아닌 JSON"인 독특한 자리다.
| 분류 | 대표 엔진 | 워크플로우 정의 | 영속 저장소 | 강점 |
| --- | --- | --- | --- | --- |
| 듀러블 실행 SDK | Temporal·Cadence·Restate·DBOS | 코드 (TS·Go·Java·Python) | Cassandra·Postgres·MySQL | 장기 실행·복잡 분기 |
| 이벤트 함수 | Inngest·Trigger.dev | 코드 (TS 주력) | 관리형 | DX·AI 에이전트 |
| Postgres 큐 | Hatchet | 코드 (TS·Python·Go) | Postgres | 단순·저운영 |
| DAG 오케스트레이션 | Airflow·Prefect·Dagster | 코드 (Python) | Postgres·SQLite | 배치 ETL·데이터 |
3장 · Temporal 아키텍처 — Uber Cadence의 진화
Temporal은 2019년 Uber Cadence 팀(Maxim Fateev, Samar Abbas)이 포크해 만든 회사이자 오픈소스 엔진이다. 2026년 현재 듀러블 실행 분야의 사실상 표준으로 자리잡았다.
Temporal 서버는 네 가지 핵심 서비스로 구성된다.
- **Frontend** — 모든 클라이언트·워커 RPC의 입구. gRPC 게이트웨이.
- **History** — 워크플로우 실행 이벤트 로그의 저장과 mutate. 가장 무거운 컴포넌트.
- **Matching** — 태스크 큐의 매칭(어떤 워커가 어떤 태스크를 받을지).
- **Worker** — 시스템 워크플로우(예약·아카이브)를 도는 내부 워커.
이 네 서비스가 Cassandra·MySQL·Postgres 같은 영속 저장소를 공유한다. 워크플로우 실행 이벤트(`WorkflowExecutionStarted`, `ActivityTaskCompleted` 등)가 History 서비스로 들어가고, 워커는 Matching에서 태스크를 폴링한다.
// Temporal TypeScript SDK — 결제 사가 워크플로우
const { chargeCard, reserveInventory, shipOrder, refundCard, releaseInventory } =
proxyActivities<typeof activities>({
startToCloseTimeout: '1 minute',
retry: { maximumAttempts: 3, initialInterval: '1s' },
})
export const cancelOrderSignal = defineSignal('cancelOrder')
export async function processOrder(orderId: string, amount: number): Promise<string> {
let cancelled = false
setHandler(cancelOrderSignal, () => { cancelled = true })
const chargeId = await chargeCard(orderId, amount)
try {
const reservationId = await reserveInventory(orderId)
if (cancelled) throw new Error('cancelled-after-reserve')
await sleep('5 seconds') // human-in-the-loop confirmation window
const trackingId = await shipOrder(orderId, reservationId)
return trackingId
} catch (err) {
// compensating actions — saga pattern
await releaseInventory(orderId).catch(() => {})
await refundCard(chargeId, amount)
throw err
}
}
이 코드의 마법은 `sleep('5 seconds')`가 진짜로 5초 동안 워커를 점유하지 않는다는 것이다. 워크플로우 상태가 History에 영속되고, 5초 후 타이머가 깨면 새 워커가 그 지점부터 재개한다. 결제 워크플로우가 며칠을 기다려도 워커 메모리를 안 먹는다.
4장 · 결정론적 리플레이 — 어떻게 함수가 안 죽은 척하나
Temporal·Cadence·Restate의 핵심 마법은 결정론적 리플레이다. 작동 방식을 한 단계씩 보자.
1. 워크플로우가 처음 시작한다. 워커가 코드를 실행한다.
2. `chargeCard(orderId, amount)` 호출이 발생한다. SDK가 이를 가로채서 History에 `ActivityTaskScheduled` 이벤트를 기록한다.
3. Activity가 완료되면 `ActivityTaskCompleted` + 결과가 History에 기록된다.
4. SDK는 결과를 워크플로우 코드에 돌려준다.
5. 다음 단계로 진행. `reserveInventory(...)`도 같은 방식.
6. **워커가 죽는다.** OOM·재배포·preemption. 무엇이든.
7. 새 워커가 같은 워크플로우 ID를 잡는다. 코드를 처음부터 실행한다.
8. `chargeCard(...)` 호출이 일어나지만, SDK는 History에 이미 결과가 있음을 보고 그 결과를 즉시 반환한다. 진짜로 카드는 안 긁는다.
9. `reserveInventory(...)`도 마찬가지로 리플레이.
10. 마지막 미완 단계까지 도달하면 그때부터 진짜 실행을 재개한다.
이 시나리오가 작동하려면 **워크플로우 코드 자체가 결정론적**이어야 한다. 같은 입력 → 같은 분기 → 같은 호출 순서. `Math.random()`을 직접 쓰면 두 번째 리플레이에서 다른 값이 나와 분기가 갈라진다. 그래서 Temporal SDK는 `workflow.uuid4()`·`workflow.now()` 같은 결정론적 함수를 제공한다.
이 제약이 듀러블 실행의 가장 큰 학습 곡선이다. "그냥 코드 짜면 안 되나"라고 생각하다 분기 비결정성 버그로 한 번 데이고 나면, 왜 SDK가 이렇게 빡빡한지 이해하게 된다.
5장 · Inngest — "함수가 이벤트 핸들러" 모델
Inngest(2021년 창업, Tony Holdstock-Brown·Dan Farrelly)는 다른 각도로 듀러블 실행을 공격한다. **"워크플로우"라는 개념을 없앤다.** 대신 **함수**가 일급 시민이고, 함수 안의 `step.run`·`step.sleep`·`step.waitForEvent`가 듀러블 경계다.
// Inngest — Stripe 결제 후 후속 처리
const inngest = new Inngest({ id: 'commerce' })
export const onPaymentSucceeded = inngest.createFunction(
{ id: 'on-payment-succeeded', retries: 3 },
{ event: 'stripe/payment.succeeded' },
async ({ event, step }) => {
const order = await step.run('load-order', async () => {
return await db.orders.findById(event.data.orderId)
})
await step.run('send-receipt', async () => {
await emails.sendReceipt(order)
})
// 24시간 후 리뷰 요청 메일 — Inngest가 24시간 동안 함수를 영속시킴
await step.sleep('wait-1-day', '1 day')
await step.run('send-review-request', async () => {
await emails.sendReviewRequest(order)
})
// 사용자가 7일 안에 리뷰를 남기면 보너스 포인트
const review = await step.waitForEvent('wait-for-review', {
event: 'review/submitted',
match: 'data.orderId',
timeout: '7 days',
})
if (review) {
await step.run('grant-bonus-points', async () => {
await loyalty.grantPoints(order.userId, 100)
})
}
}
)
Inngest의 미학은 두 가지다. 첫째, **이벤트가 진입점**이라는 점 — 워크플로우를 명시적으로 시작하는 대신 이벤트가 자동으로 함수를 깨운다. 둘째, **DX가 친화적**이라는 점 — `step.run`은 평범한 async 함수처럼 보이고, 결정론적 제약을 SDK가 거의 다 숨긴다.
대신 트레이드오프가 있다. Inngest는 관리형 SaaS가 기본이고(2024년 self-host 옵션이 추가됐지만), Temporal만큼 복잡한 분기·신호·child 워크플로우는 덜 자연스럽다. SaaS·AI 에이전트·이벤트 중심 시스템에 강하고, 거대한 결제 시스템 같은 곳엔 Temporal이 더 맞다.
6장 · Trigger.dev v3 — Vercel 친화 듀러블 실행
Trigger.dev는 2022년 시작해 2024년 v3에서 큰 폭의 재설계를 거쳤다. v2까지는 "Vercel Cron 대체" 같은 위치였다가, v3에서 진짜 듀러블 실행 엔진으로 진화했다. 핵심은 **태스크(task) 모델**이다 — Inngest의 함수와 비슷하지만 SDK가 더 명시적이다.
// Trigger.dev v3 — AI 에이전트 태스크
const anthropic = new Anthropic()
export const reviewPullRequestTask = task({
id: 'review-pull-request',
maxDuration: 1800, // 30 minutes
retry: { maxAttempts: 3 },
run: async (payload: { repo: string; prNumber: number }, { ctx }) => {
logger.info('Reviewing PR', payload)
const diff = await fetchPRDiff(payload.repo, payload.prNumber)
const review = await anthropic.messages.create({
model: 'claude-opus-4-7',
max_tokens: 4096,
messages: [
{ role: 'user', content: `Review this diff:\n${diff}` },
],
})
await wait.for({ seconds: 10 }) // backoff before posting
await postReviewComment(payload.repo, payload.prNumber, review.content)
return { tokensUsed: review.usage.input_tokens + review.usage.output_tokens }
},
})
Trigger.dev v3의 강점은 **인프라가 같이 따라온다**는 점이다 — Docker 컨테이너 안에서 태스크를 격리 실행하고, 길게 도는 AI 에이전트도 메모리·CPU 제한이 명시적이다. Vercel과 결이 맞아 Next.js + Trigger.dev 조합이 2026년 인디 SaaS에서 흔하다.
단점은 Temporal만큼 분산 시스템 추상화가 깊지 않다는 점, self-host는 가능하지만 복잡도가 있다는 점. AI 에이전트·미디어 처리 같은 "한 작업이 길지만 분기는 단순"한 워크로드에 가장 잘 맞는다.
7장 · Hatchet — Postgres 네이티브 큐의 부상
Hatchet(2024년 창업)은 2026년 시장에서 가장 흥미로운 신참 중 하나다. 메시지는 단순하다: **"Postgres 한 박스로 충분하다."** Kafka·Cassandra·Redis 같은 별도 인프라 없이 Postgres만으로 듀러블 큐와 워크플로우를 구현한다.
Hatchet Python SDK — 비동기 작업 파이프라인
from hatchet_sdk import Hatchet, Context
from pydantic import BaseModel
hatchet = Hatchet()
class ProcessVideoInput(BaseModel):
video_url: str
user_id: str
@hatchet.workflow(on_events=["video:uploaded"], input_validator=ProcessVideoInput)
class ProcessVideo:
@hatchet.step(timeout="5m")
def download(self, ctx: Context) -> dict:
input = ProcessVideoInput.model_validate(ctx.workflow_input())
path = download_to_s3(input.video_url)
return {"path": path}
@hatchet.step(parents=["download"], timeout="30m")
def transcribe(self, ctx: Context) -> dict:
path = ctx.step_output("download")["path"]
transcript = whisper_transcribe(path)
return {"transcript": transcript}
@hatchet.step(parents=["transcribe"], timeout="10m")
def summarize(self, ctx: Context) -> dict:
transcript = ctx.step_output("transcribe")["transcript"]
summary = claude_summarize(transcript)
return {"summary": summary}
Hatchet의 매력은 **운영 단순성**이다 — Postgres 하나에 워커 컨테이너 몇 개. 백업·복제·HA가 Postgres 생태계를 그대로 활용한다. 2024년 이후 "**Postgres가 모든 큐의 미래**"라는 흐름의 대표 격이고, 같은 시기에 등장한 GraphileWorker·pg-boss·Riverqueue와 같은 호흡이다.
단점은 진짜 거대한 스케일(초당 수만 건)에서는 Postgres가 병목이 될 수 있고, Temporal만큼 복잡한 워크플로우 패턴(child·signal·query)이 아직 다 갖춰지진 않았다는 점.
8장 · Restate — 상태풀(stateful) 호출
Restate(2023년 창업, Stephan Ewen·Igal Shilman 외 Apache Flink 출신)는 듀러블 실행에 또 다른 각도를 더한다. **상태풀 호출(stateful invocation)** — 함수 호출이 자체적으로 상태를 가진 객체처럼 동작한다.
// Restate — 가상 객체로서의 결제 처리
const paymentService = restate.object({
name: 'payment',
handlers: {
process: async (ctx: restate.ObjectContext, amount: number) => {
// 객체 상태 — 이 paymentId에 영속
const status = (await ctx.get<string>('status')) ?? 'pending'
if (status === 'completed') return { idempotent: true }
ctx.set('status', 'processing')
const chargeId = await ctx.run('charge', () => stripe.charge(amount))
ctx.set('chargeId', chargeId)
ctx.set('status', 'completed')
return { chargeId }
},
refund: async (ctx: restate.ObjectContext) => {
const chargeId = await ctx.get<string>('chargeId')
if (!chargeId) throw new restate.TerminalError('no-charge-to-refund')
await ctx.run('refund', () => stripe.refund(chargeId))
ctx.set('status', 'refunded')
},
},
})
restate.endpoint().bind(paymentService).listen()
Restate의 차별점은 **객체별 상태**다 — 같은 paymentId에 대한 호출은 자동으로 직렬화되고 영속 상태를 공유한다. Temporal로 짜면 워크플로우 + 시그널 조합으로 풀어야 하는 패턴이, Restate에서는 그냥 객체 메서드다.
또 하나의 강점은 **운영 모델**이다. Restate 서버는 단일 바이너리이고, 자체 RocksDB로 상태를 영속한다. Temporal처럼 Cassandra·MySQL 따로 깔 필요가 없다. 작은 팀이 듀러블 실행을 도입하기에 진입 장벽이 낮다.
9장 · DBOS — Postgres가 곧 컴퓨트 (Mike Stonebraker)
DBOS(2023년 창업, 데이터베이스의 전설 Mike Stonebraker·Matei Zaharia 공동 창업)는 가장 급진적인 입장이다. **"DB가 OS여야 한다."** 워크플로우의 상태뿐 아니라 워크플로우 실행 자체가 Postgres 내부의 트랜잭션으로 일어난다.
DBOS Python — 트랜잭션과 워크플로우의 결합
from dbos import DBOS, WorkflowContext, TransactionContext
@DBOS.workflow()
def process_signup(ctx: WorkflowContext, email: str) -> str:
user_id = create_user(ctx, email)
send_welcome_email(ctx, user_id)
grant_trial_credits(ctx, user_id)
return user_id
@DBOS.transaction()
def create_user(ctx: TransactionContext, email: str) -> str:
이 함수는 Postgres 트랜잭션 안에서 실행됨
cur = ctx.sql_session.execute(
"INSERT INTO users (email) VALUES (%s) RETURNING id",
(email,),
)
return cur.fetchone()[0]
@DBOS.step()
def send_welcome_email(ctx, user_id: str) -> None:
외부 호출 — 한 번만 실행 보장 (멱등)
sendgrid.send_email(user_id, "Welcome!")
@DBOS.transaction()
def grant_trial_credits(ctx: TransactionContext, user_id: str) -> None:
ctx.sql_session.execute(
"INSERT INTO credits (user_id, amount) VALUES (%s, %s)",
(user_id, 100),
)
DBOS의 우아함은 **트랜잭션 일관성과 워크플로우 듀러빌리티가 한 시스템**이라는 점이다. Temporal에서는 activity와 DB 트랜잭션이 다른 시스템이라 정확히 한 번 실행이 어려운데, DBOS에서는 한 트랜잭션 안에 끝난다. 데이터베이스 학계의 거장이 만든 시스템답게 의미론이 깔끔하다.
대신 새로운 패러다임이라 생태계가 작고(Python·TypeScript SDK 중심), 모든 워크로드가 트랜잭션 모델에 맞진 않는다. 2026년에는 진지한 production 사용 사례가 늘고 있지만, Temporal만큼의 성숙도는 아직이다.
10장 · AWS Step Functions — JSON 상태머신의 자리
Step Functions(2016년 AWS 출시)는 듀러블 실행 시장의 원조 중 하나이지만, 다른 도구와 결이 다르다. 워크플로우를 **Amazon States Language(ASL)** 라는 JSON DSL로 쓴다. 코드가 아닌 상태머신 정의 파일이다.
Step Functions — Standard 모드 사가 (YAML로 표현)
StartAt: ChargeCard
States:
ChargeCard:
Type: Task
Resource: arn:aws:lambda:us-east-1:123456789012:function:chargeCard
Retry:
- ErrorEquals: ["States.TaskFailed"]
IntervalSeconds: 2
MaxAttempts: 3
Catch:
- ErrorEquals: ["States.ALL"]
Next: FailOrder
Next: ReserveInventory
ReserveInventory:
Type: Task
Resource: arn:aws:lambda:us-east-1:123456789012:function:reserveInventory
Catch:
- ErrorEquals: ["States.ALL"]
Next: RefundCard
Next: ShipOrder
ShipOrder:
Type: Task
Resource: arn:aws:lambda:us-east-1:123456789012:function:shipOrder
Catch:
- ErrorEquals: ["States.ALL"]
Next: RefundAndRelease
End: true
RefundAndRelease:
Type: Parallel
Branches:
- StartAt: RefundCard
States:
RefundCard:
Type: Task
Resource: arn:aws:lambda:us-east-1:123456789012:function:refundCard
End: true
- StartAt: ReleaseInventory
States:
ReleaseInventory:
Type: Task
Resource: arn:aws:lambda:us-east-1:123456789012:function:releaseInventory
End: true
Next: FailOrder
RefundCard:
Type: Task
Resource: arn:aws:lambda:us-east-1:123456789012:function:refundCard
Next: FailOrder
FailOrder:
Type: Fail
Cause: OrderProcessingFailed
Step Functions의 두 모드를 구분해야 한다.
- **Standard** — 영속 워크플로우. 최대 1년 실행. 상태 전이마다 과금. 결제·승인 같은 비싼 적은 워크플로우.
- **Express** — 단명 워크플로우. 최대 5분. 실행 시간 + 메모리로 과금. 대량의 짧은 이벤트 처리.
Step Functions의 장점은 **AWS 통합의 깊이**다 — Lambda·DynamoDB·SQS·EventBridge 같은 200여 종 서비스와 직접 통합. 단점은 JSON DSL이 코드보다 표현력이 낮고, 디버깅이 어렵고, AWS 락인.
2026년에는 AWS-only 조직이 아니면 코드 기반 엔진(Temporal·Inngest·Trigger.dev)이 더 선호되는 추세지만, 이미 AWS 위에 다 있는 팀에게는 Step Functions가 여전히 강력한 옵션.
11장 · Apache Airflow vs Prefect vs Dagster — DAG 오케스트레이션의 자리
데이터 파이프라인 쪽에는 다른 세계관의 엔진들이 있다. **DAG 오케스트레이션**이다.
- **Apache Airflow** (2014년 Airbnb) — 산업 표준. Python으로 DAG 작성. 스케줄러 + 워커 아키텍처. 비판: 매크로 환경(Jinja) 의존, 복잡한 backfill 의미론.
- **Prefect** (2018년) — Airflow 비판에서 출발. "코드 우선" DAG, 더 명령형 모델, 클라우드 옵션 강함. Prefect 2/3에서 flow와 task 추상화 도입.
- **Dagster** (2019년 Elementl) — 데이터 자산(asset) 중심 모델. DAG가 아니라 "어떤 자산이 어떤 자산에 의존하는가"를 선언. dbt·Snowflake 같은 생태계와 깊이 통합.
- **Argo Workflows** — Kubernetes 네이티브. CRD로 DAG 정의, 파드 단위 실행. ML 파이프라인에서 자주 사용.
| 도구 | 정의 모델 | 주 사용처 | 강점 | 단점 |
| --- | --- | --- | --- | --- |
| Airflow | Python DAG | 배치 ETL | 생태계·산업 표준 | 무거운 운영·낡은 의미론 |
| Prefect | Python flow | 데이터 + 일반 워크플로우 | 명령형 API·hybrid 실행 | Airflow보다 작은 생태계 |
| Dagster | Asset 그래프 | 모던 데이터 스택 | dbt 통합·자산 추상화 | 학습 곡선·작은 도입 |
| Argo Workflows | YAML on K8s | ML·CI/CD | K8s 네이티브 | YAML 부피·진입 장벽 |
핵심 구분: **이 카테고리는 듀러블 실행 SDK가 아니다.** 배치 잡 스케줄러로 출발했고, 한 잡이 실패하면 보통 처음부터 재실행한다. AI 에이전트 같은 "수 시간을 도는 한 함수"보다 "매일 03:00에 데이터를 옮기는 잡 100개"에 맞는다.
2026년에는 영역이 섞이고 있다 — Prefect는 일반 워크플로우로 확장하고, Dagster의 자산 모델은 ML 파이프라인에서 점점 강력해진다. 하지만 결제 사가 같은 OLTP 워크플로우는 여전히 Temporal·Inngest 영역이다.
12장 · 사가 패턴 — 분산 트랜잭션의 현실적 답
마이크로서비스 시대의 가장 큰 문제 중 하나: **여러 서비스에 걸친 트랜잭션을 어떻게 일관성 있게 처리하는가.** 한 서비스에서 결제, 다른 서비스에서 재고, 또 다른 서비스에서 배송 — 이걸 ACID 트랜잭션으로 묶을 수 없다.
답은 1987년 Hector Garcia-Molina의 **사가(saga) 패턴**이다. 큰 트랜잭션을 작은 로컬 트랜잭션들의 시퀀스로 쪼개고, 실패 시 **보상(compensating) 트랜잭션**을 역순으로 실행한다.
// 결제 사가 — Temporal로 표현
export async function orderSaga(orderId: string, amount: number) {
const completed: Array<() => Promise<void>> = []
try {
const chargeId = await chargeCard(orderId, amount)
completed.push(() => refundCard(chargeId, amount))
const reservationId = await reserveInventory(orderId)
completed.push(() => releaseInventory(reservationId))
const trackingId = await shipOrder(orderId, reservationId)
completed.push(() => cancelShipment(trackingId))
await sendConfirmation(orderId, trackingId)
return { chargeId, trackingId }
} catch (err) {
// 보상 트랜잭션 역순 실행
for (const compensate of completed.reverse()) {
await compensate().catch((e) => console.error('compensation failed', e))
}
throw err
}
}
여기서 **두 가지 사가 변형**을 구분해야 한다.
- **오케스트레이션 사가 (orchestration)** — 중앙 코디네이터(워크플로우)가 각 단계를 호출. 분기가 한 곳에 있어 추적이 쉽다. Temporal·Inngest의 자연스러운 모델.
- **코레오그래피 사가 (choreography)** — 각 서비스가 이벤트를 발행/구독해 자율적으로 진행. 중앙 코디네이터 없음. Kafka·EventBridge 같은 이벤트 버스가 필요. 결합도가 낮지만 추적·디버깅이 어렵다.
2026년의 합의: **오케스트레이션 사가가 기본 선택지**다. 듀러블 실행 엔진이 코디네이터를 안전하게 실행해주기 때문에. 코레오그래피는 진정한 자율 마이크로서비스 조직에서만 가치가 있고, 대부분 팀에는 추적 부담이 더 크다.
13장 · 멱등성과 정확히 한 번 의미론
분산 시스템 책에서 가장 위험한 약속 중 하나가 "정확히 한 번(exactly-once)"이다. 엄밀한 의미에서 분산 시스템에서 정확히 한 번은 **불가능**하다 — 메시지가 도착했는지 송신자는 영원히 확신할 수 없다(Two Generals Problem).
현실적인 답은 **효과적으로 한 번(effectively-once)** 이다. 같은 작업을 여러 번 시도해도 시스템 상태는 마치 한 번 실행한 것처럼 보인다. 이를 보장하는 두 도구가 **멱등성(idempotency)** 과 **중복 제거(deduplication)** 다.
-- Postgres 멱등성 키 테이블 — 결제 중복 방지
CREATE TABLE payment_attempts (
idempotency_key TEXT PRIMARY KEY,
charge_id TEXT,
amount BIGINT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('processing', 'succeeded', 'failed')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- 멱등성 보장 결제 — 같은 키로 두 번 호출해도 한 번만 결제됨
CREATE OR REPLACE FUNCTION charge_with_idempotency(
p_idempotency_key TEXT,
p_amount BIGINT
) RETURNS TABLE(charge_id TEXT, was_new BOOLEAN) AS $$
DECLARE
v_existing payment_attempts%ROWTYPE;
v_charge_id TEXT;
BEGIN
-- 이미 처리된 키인지 확인
SELECT * INTO v_existing FROM payment_attempts
WHERE idempotency_key = p_idempotency_key FOR UPDATE;
IF FOUND THEN
RETURN QUERY SELECT v_existing.charge_id, FALSE;
RETURN;
END IF;
-- 처음이라면 실제 결제 후 기록
INSERT INTO payment_attempts(idempotency_key, amount, status)
VALUES (p_idempotency_key, p_amount, 'processing');
v_charge_id := stripe_charge(p_amount); -- 외부 API 호출
UPDATE payment_attempts
SET charge_id = v_charge_id, status = 'succeeded', updated_at = NOW()
WHERE idempotency_key = p_idempotency_key;
RETURN QUERY SELECT v_charge_id, TRUE;
END;
$$ LANGUAGE plpgsql;
듀러블 실행 엔진은 이 멱등성을 자동으로 다뤄준다. Temporal의 activity는 `ActivityId`로 식별되고, History에 결과가 있으면 리플레이 시 재실행 안 한다. 외부 호출(Stripe·SendGrid 등)의 멱등성은 사용자가 책임진다 — Stripe API의 `Idempotency-Key` 헤더, SendGrid의 `X-Idempotency-Key`. 듀러블 실행 엔진이 외부 시스템의 보장까지 대신해주진 못한다.
핵심 원칙: **외부 부작용이 있는 모든 호출에는 멱등성 키를 붙여라.** 듀러블 실행 + 멱등성 키 = 효과적으로 한 번. 둘 중 하나만 있으면 안전하지 않다.
14장 · 장기 실행 AI 에이전트 — 듀러블 실행의 새로운 킬러 앱
2026년 듀러블 실행 르네상스의 가장 큰 동력은 **장기 실행 AI 에이전트**다. LLM 에이전트의 특성을 보자.
- 한 작업이 수십 분에서 며칠을 돈다 (코드 리뷰·리서치·자동화).
- 외부 API를 수십~수백 번 호출한다 (OpenAI·Anthropic·도구들).
- 비용이 단일 작업당 `$0.10` 에서 `$10` 까지 들 수 있다.
- 도중에 사람의 승인을 기다린다 (human-in-the-loop).
- 실패 시 처음부터 다시 시작하면 비용이 두 배.
이 모든 특성이 듀러블 실행에 완벽히 맞다.
// AI 에이전트 + 듀러블 실행 — Trigger.dev v3
const claude = new Anthropic()
export const researchAgent = task({
id: 'research-agent',
maxDuration: 7200, // 2시간
run: async (payload: { question: string }, { ctx }) => {
const tools = [searchWebTool, readPageTool, summarizeTool]
const messages: Anthropic.MessageParam[] = [
{ role: 'user', content: payload.question },
]
for (let iteration = 0; iteration < 50; iteration++) {
const response = await claude.messages.create({
model: 'claude-opus-4-7',
max_tokens: 4096,
tools,
messages,
})
messages.push({ role: 'assistant', content: response.content })
if (response.stop_reason === 'end_turn') {
return { finalAnswer: extractText(response.content), iterations: iteration }
}
// 도구 호출 처리 — 각 도구 호출이 듀러블 경계
const toolResults = await Promise.all(
response.content
.filter((b) => b.type === 'tool_use')
.map(async (tool) => {
return await executeTool(tool.name, tool.input)
})
)
messages.push({ role: 'user', content: toolResults })
// 매 5회마다 잠시 휴식 — rate limit 회피
if (iteration % 5 === 4) await wait.for({ seconds: 30 })
}
throw new Error('agent-did-not-converge')
},
})
이 패턴이 2026년 AI 에이전트 인프라의 표준이 되어가고 있다. 에이전트 자체는 단순한 루프 — LLM 호출 → 도구 실행 → 다시 LLM 호출. 듀러블 실행이 그 루프의 각 단계를 영속화한다. 14번째 단계에서 죽어도 비용을 두 배로 안 낸다.
Anthropic이 2024~2025년 발표한 듀러블 컨텍스트 캐시(prompt caching), Vercel의 AI SDK + Inngest 통합, LangGraph의 체크포인트 모델 — 모두 같은 방향을 가리킨다. **LLM 에이전트는 듀러블 실행 없이는 production에 못 들어간다.**
15장 · 토스 결제 워크플로우 사례
한국 핀테크 토스(Toss)는 2018년 이후 결제 처리 인프라에서 듀러블 실행 패턴을 채택해 왔다(공개 자료 기준, 직접적인 Temporal 사용 여부는 별개). 결제는 본질적으로 듀러블 실행이 적합한 도메인이다.
토스 결제의 특성을 보자.
- 한 결제가 카드사·VAN·PG·정산 시스템을 거친다.
- 어떤 단계에서든 실패할 수 있고, 부분 실패가 흔하다.
- 결제 한 건이 두 번 처리되면 안 된다 (멱등성).
- 환불은 결제의 거울 — 보상 트랜잭션.
- 분쟁 발생 시 모든 단계의 감사 로그가 필요하다.
이 도메인에서 사가 패턴과 이벤트 소싱이 자연스럽다. 토스 같은 한국 핀테크들이 자체 워크플로우 엔진을 만들거나 Kafka 기반 사가를 짠 사례가 많고, 2024년 이후엔 Temporal 도입 사례도 늘었다. 결제 영역의 복잡도가 듀러블 실행 엔진의 가치를 가장 잘 보여주는 사례다.
비슷한 맥락에서 카카오페이도 마이크로서비스 사이의 결제 사가를 자체 프레임워크로 구현해 왔다. 카카오페이의 기술 블로그는 "분산 트랜잭션을 사가로 풀고 보상 트랜잭션을 명시적으로 코드화한다"는 패턴을 공유한 적이 있다. 결제·송금·페이백 같은 다단계 워크플로우는 듀러블 실행의 캐논 사례다.
16장 · 일본 사례 — Mercari·Rakuten·Cybozu
일본에서도 듀러블 실행의 도입이 빠르다.
**Mercari**는 마이크로서비스 환경의 결제·정산을 사가 패턴으로 풀어 왔다. 메루카리 페이(Merpay)는 분산 트랜잭션 문제를 회피하기 위해 명시적인 사가 코디네이터를 두고 각 단계를 멱등성으로 보호한다. 2024년 이후엔 일부 영역에 Temporal을 도입했다는 발표가 있었다.
**Rakuten**은 광범위한 사업(이커머스·금융·통신·여행) 사이의 워크플로우 양이 거대하다. 자체 사내 워크플로우 엔진과 함께 Apache Airflow를 데이터 파이프라인에, AWS Step Functions를 일부 영역에, Camunda를 BPMN 워크플로우에 쓰는 다중 엔진 환경이다. 라쿠텐 같은 규모에서는 한 엔진으로 통일하는 게 오히려 어렵다.
**Cybozu**(kintone 개발사)는 클라우드 서비스의 비동기 처리에 일찍이 메시지 큐 + 워커 패턴을 다뤄 왔고, 2020년대 들어 일부 영역에 듀러블 실행 패턴을 적용했다. 일본 SaaS에서 듀러블 실행은 사용자 데이터의 안전한 마이그레이션·계정 정리·구독 변경 같은 곳에 자연스럽게 적용된다.
일본 시장의 흥미로운 점은 **자체 구현 비중이 높다**는 점이다. NTT·SoftBank·Nintendo 같은 거대 조직은 자체 워크플로우 엔진을 운영하는 경우가 많고, 새 도구 도입의 속도가 미국보다 느리다. 대신 한 번 도입하면 깊이 쓴다.
17장 · Cadence — Uber가 만든 원조
Cadence(2017년 Uber 오픈소스)는 Temporal의 직계 조상이다. Maxim Fateev·Samar Abbas 등 핵심 팀이 2019년 Uber를 나와 Temporal을 창업했고, 핵심 아키텍처가 거의 동일하다. 차이는 시간이 지나며 SDK·API가 갈라졌다는 점.
2026년 현재 Cadence는 Uber 내부에서 여전히 대규모로 운영된다 — 매일 수천만 건의 워크플로우. 외부 사용자도 일부 있지만 Temporal 쪽으로 무게가 옮겨갔다. 새 프로젝트라면 Temporal을 선택하는 것이 자연스럽다. Cadence는 "Temporal 이전 시대의 운영 자산"의 자리다.
흥미로운 분기 흐름이 있다. Cadence와 Temporal은 같은 뿌리에서 출발했지만 의미론·SDK·운영 모델이 점점 갈라지고 있다. Cadence의 Long Polling 모델, Temporal의 Workflow Update 같은 신기능 — 한 쪽에 있고 다른 쪽엔 없는 기능이 늘어난다. 두 엔진 사이 호환은 더이상 보장되지 않는다.
18장 · Camunda·Conductor — BPMN과 마이크로서비스 오케스트레이션
코드 중심 듀러블 실행 옆에는 다른 전통의 엔진들이 있다.
**Camunda**(독일, 2008년 창업)는 BPMN(Business Process Model and Notation) 표준 기반의 워크플로우 엔진이다. 비즈니스 분석가가 그래픽으로 그린 BPMN 다이어그램이 그대로 실행 가능한 워크플로우가 된다. 은행·보험·통신 같은 도메인에서 강하다. Camunda 8(2022년 발표)에서 Cloud Native 재설계가 이뤄져 Kubernetes 위에서 마이크로서비스 오케스트레이션도 다룬다.
**Netflix Conductor**(2016년 Netflix 오픈소스)는 마이크로서비스 오케스트레이션 엔진이다. JSON DSL로 워크플로우를 정의하고 여러 언어 워커가 태스크를 폴링한다. Netflix 내부의 대규모 비디오 처리·콘텐츠 메타데이터 파이프라인을 돌린다. 2022년 Orkes가 회사로 spin-off되어 상용 지원을 제공한다.
| 엔진 | 정의 형식 | 강점 | 약점 |
| --- | --- | --- | --- |
| Camunda | BPMN(그래픽) | 비즈니스/IT 협업·표준 | XML 기반·복잡 |
| Conductor | JSON DSL | 다언어 워커·Netflix 검증 | 코드 표현력 낮음 |
| Temporal | 코드(TS·Go·Java·Python) | 표현력·결정론적 리플레이 | 학습 곡선 |
| Step Functions | JSON(ASL) | AWS 통합 | DSL 한계 |
핵심 구분: **코드 vs DSL**. 비즈니스 분석가가 워크플로우를 정의할 일이 많다면 BPMN/Camunda. 엔지니어가 모든 워크플로우를 짠다면 Temporal·Inngest. AWS 락인이 괜찮다면 Step Functions.
19장 · 셀프 호스트 vs SaaS — 비용·운영의 트레이드오프
워크플로우 엔진의 큰 결정 중 하나는 **셀프 호스트인가 SaaS인가**.
| 엔진 | 셀프 호스트 | SaaS | SaaS 가격 모델 |
| --- | --- | --- | --- |
| Temporal | 가능 (운영 무거움) | Temporal Cloud | 액션·이벤트 단위 |
| Inngest | 가능 (2024년~) | Inngest Cloud (기본) | 실행 단위 |
| Trigger.dev | 가능 (Docker) | Trigger.dev Cloud | 실행 + 시간 |
| Hatchet | 가능 (Docker) | Hatchet Cloud | 실행 단위 |
| Restate | 가능 (단일 바이너리) | 베타 | TBD |
| DBOS | 가능 (Postgres + 워커) | DBOS Cloud | TBD |
| Step Functions | 불가 (AWS 전용) | AWS | 상태 전이 단위 |
| Airflow | 가능 | Astronomer·MWAA | 인스턴스 시간 |
| Prefect | 가능 | Prefect Cloud | 실행 + 사용자 |
| Dagster | 가능 | Dagster Cloud | 실행 + 사용자 |
셀프 호스트의 진실: **Temporal을 production 수준으로 셀프 호스트하는 비용은 적지 않다.** Cassandra/MySQL 운영, 4개 서비스의 HA, 메트릭/모니터링, 업그레이드. 작은 팀에는 SaaS가 거의 항상 더 싸다.
대신 데이터 주권·컴플라이언스·VPC 안에서만 도는 요구가 있다면 셀프 호스트가 필수다. 한국·일본의 금융기관은 거의 항상 셀프 호스트. 미국 인디 SaaS는 거의 항상 SaaS.
흥미로운 추세: **하이브리드 모델**. Inngest·Trigger.dev는 컨트롤 플레인은 SaaS, 실제 실행 워커는 사용자 인프라에 둘 수 있다. 데이터는 안 새고, 운영 부담은 SaaS 쪽. 2026년에 점점 더 흔해질 패턴.
20장 · 어느 엔진을 어디에 쓸까 — 한 줄 가이드
도구 선택 가이드. 단순화하면 이렇다.
- **결제·핀테크 사가·복잡한 분기** → Temporal. 사실상 표준.
- **AI 에이전트·SaaS 자동화·DX 우선** → Inngest 또는 Trigger.dev v3. 둘 중 하나, 취향.
- **간단한 큐의 진화·Postgres만 쓰고 싶다** → Hatchet. 운영이 가벼움.
- **객체 단위 상태풀 호출·작은 운영 풋프린트** → Restate. 새로움, 베팅.
- **트랜잭션 일관성이 중요·Postgres 네이티브** → DBOS. 학계 근본.
- **이미 AWS 위에 모두 있다·AWS 락인 OK** → Step Functions.
- **데이터 ETL 파이프라인** → Airflow(전통)·Prefect(모던)·Dagster(자산 중심).
- **Kubernetes 네이티브 ML/CI** → Argo Workflows.
- **BPMN 표준·비즈니스/IT 협업** → Camunda.
- **Netflix-style 마이크로서비스 오케스트레이션** → Conductor.
**섞어 쓰는 것도 정상이다.** 결제는 Temporal, 데이터는 Airflow, AI는 Inngest — 흔한 셋업. 한 엔진으로 모든 워크플로우를 통일하려는 시도는 보통 실패한다. 각 엔진이 잘하는 영역이 다르고, 그 차이가 도구 선택의 본질이다.
21장 · 함정 — 듀러블 실행을 도입할 때 흔히 망하는 5가지
1. **결정론을 안 지킴** — 워크플로우 코드 안에서 `Math.random()`·`Date.now()`·환경 변수 직접 사용. 첫 리플레이에서 다른 길로 분기해 디버깅 지옥. 항상 SDK의 결정론적 함수 사용.
2. **거대한 워크플로우 페이로드** — 워크플로우 입출력에 100MB를 넣는다. History가 폭발하고 성능이 죽는다. 큰 데이터는 S3에 넣고 참조만 넘긴다.
3. **Activity와 Workflow 책임 혼동** — 워크플로우에서 직접 DB 쿼리·HTTP 호출. 모든 부작용은 Activity 안에 격리. 워크플로우는 순수한 오케스트레이션.
4. **버저닝 무시** — 워크플로우가 며칠 도는 동안 코드를 바꾸면, 진행 중인 실행이 새 코드와 호환 안 됨. Temporal의 `patched()`, Inngest의 함수 버저닝 같은 도구를 학습해야 한다.
5. **멱등성 키 안 붙임** — Activity가 외부 호출(Stripe·SendGrid)을 할 때 멱등성 키 없음. Activity 재시도 시 두 번 청구. 듀러블 실행 + 멱등성 키 = 효과적으로 한 번. 둘 다 필수.
이 다섯 가지는 듀러블 실행 도입의 진짜 학습 곡선이다. 도구를 깐다고 끝나지 않고, 결정론·격리·버저닝·멱등성을 코드 패턴으로 체화해야 한다. 2~3주는 걸린다.
22장 · 비용 모델 — 워크플로우당 진짜 비용
워크플로우 엔진 도입 시 자주 간과되는 것이 **비용 모델**이다. SaaS 가격이 작아 보이지만, 단위가 다르면 충격이 크다.
대략적인 2026년 가격대(공식 가격, 실제 협상가는 다름).
- **Temporal Cloud** — `$200` 정도부터 시작, 액션(이벤트) 단위. 큰 트래픽에서는 월 수만 달러.
- **Inngest** — 무료 50k 실행/월, Pro `$50/월` 25만 실행. 실행 단위.
- **Trigger.dev** — 무료 만 실행/월, Pro `$50/월` 10만 실행 + 시간.
- **Hatchet** — 무료 1k 워크플로우/월, Pro부터 사용량 기반.
- **Step Functions Standard** — 상태 전이 천 건당 `$0.025`. 작은 작업엔 비싸 보이고, 큰 워크플로우엔 의외로 쌈.
- **Step Functions Express** — 실행 천 건당 `$1`, 메모리·시간 추가.
직관 체크용. AI 에이전트가 워크플로우 한 번에 평균 20 스텝을 도는데, 월 10만 회 돈다고 가정.
- Inngest Pro 25만 실행 안에 들어감 — 월 `$50`.
- Step Functions Standard — 200만 상태 전이 = 약 월 `$50`.
- Temporal Cloud — 200만 액션 → 별도 산정, 큰 차이로 더 비쌀 수 있음.
- 셀프 호스트 Hatchet — Postgres 한 박스 + 워커 = 인프라 비용만.
**워크플로우당 단가가 LLM 비용 대비 얼마인지**가 진짜 신호다. 한 에이전트 실행이 `$1` 의 LLM을 태운다면 워크플로우 엔진 `$0.001` 은 사실상 무료. 반대로 단순 백그라운드 잡 (이메일 발송) 같은 곳에 비싼 엔진을 쓰면 비용이 빠르게 누적된다.
23장 · 마이그레이션 — 한 엔진에서 다른 엔진으로
워크플로우 엔진은 한 번 도입하면 바꾸기 어렵다. 워크플로우 코드와 영속 상태가 강하게 결합되어 있기 때문이다.
마이그레이션 전략을 보자.
1. **새 워크플로우는 새 엔진** — 기존은 그대로 두고, 새로 만드는 워크플로우만 새 엔진에 짠다. 가장 흔한 패턴, 시간이 가면 자연 마이그레이션.
2. **드레인 모델** — 기존 엔진에 새 실행을 막고, 진행 중인 실행이 끝날 때까지 기다린다. 워크플로우가 며칠 도는 거라면 몇 달이 걸릴 수도 있다.
3. **이벤트 재방송** — 이벤트 소싱 기반이라면 이벤트 로그를 새 엔진에 재방송. 이론적으로 가능하지만 의미론 차이로 어려움.
4. **수동 상태 이전** — 진행 중인 워크플로우의 상태를 추출해 새 엔진의 워크플로우로 복원. 가장 어렵고 위험.
대부분의 팀은 1번을 선택한다. 시간이 친구다. 새 엔진을 도입할 가치가 있다면 6~12개월 후 기존 엔진의 비중은 자연히 줄어든다.
24장 · 2026년의 트렌드 — 어디로 가는가
마지막으로 2026년 시점의 큰 흐름을 정리한다.
- **AI 에이전트가 듀러블 실행을 강제했다** — LLM 비용·길이·신뢰성 문제로 듀러블 실행 없는 production 에이전트는 사실상 불가능. Temporal/Inngest/Trigger.dev의 매출 곡선이 이 트렌드를 정확히 따른다.
- **Postgres가 인프라의 중심으로** — Hatchet·DBOS·GraphileWorker·Riverqueue·pg-boss. Kafka 없이 Postgres로 충분하다는 인식이 확산. "Postgres가 큐도, 워크플로우 엔진도, 컴퓨트도"라는 흐름.
- **하이브리드 셀프 호스트** — 컨트롤 플레인은 SaaS, 실행은 사용자 VPC. 데이터 주권과 운영 편의의 절충.
- **워크플로우 버저닝의 성숙** — Temporal의 Workflow Update, Inngest의 함수 버저닝. 며칠 도는 워크플로우의 코드 변경 의미론이 점점 정교해진다.
- **이벤트 함수 모델의 보편화** — Inngest·Trigger.dev 스타일의 "이벤트가 함수를 깨움" 모델이 SaaS·인디 개발자에게 표준화. 별도의 워크플로우 정의 없이 함수 자체가 워크플로우.
또 하나의 흐름은 **CDC + 워크플로우의 결합**이다. Postgres CDC(Debezium·Sequin)로 이벤트를 빼서 워크플로우 엔진을 깨우는 패턴. 데이터베이스 변경이 곧 워크플로우 시작점이 된다. 2026년 후반에 더 흔해질 것으로 예상된다.
에필로그 — 죽지 않는 함수의 시대
한 문장 요약: **2026년에 워크플로우 엔진은 인프라의 핵심 레이어가 됐다. 그 이유는 두 가지 — AI 에이전트가 듀러블 실행을 강제했고, Postgres가 워크플로우의 백본이 되어가기 때문.**
15년 전 분산 시스템 책의 사가 패턴이 학술적이었다면, 2026년에는 그게 모든 SaaS 백엔드의 기본기다. 결제·송금·예약·메시징·AI 에이전트 — 모두 사가의 변형이다. 그리고 그 사가는 듀러블 실행 엔진 위에서 돈다.
다음 10년의 백엔드 엔지니어링은 "어떤 데이터베이스를 쓰는가"만큼 "어떤 워크플로우 엔진을 쓰는가"가 중요해진다. 그리고 그 엔진 선택은 비즈니스 도메인의 본질에 의존한다 — 결제는 Temporal, AI는 Inngest, ETL은 Airflow. 한 도구로 모든 걸 풀 수는 없다.
마지막으로 한 마디: **컨테이너는 죽는다. 그러나 워크플로우는 죽지 않아야 한다.** 그게 듀러블 실행의 약속이다.
> "프로세스는 영원하지 않다. 그러나 함수의 의미는 영원할 수 있다. 그게 듀러블 실행이다."
— 듀러블 실행 & 워크플로우 엔진 2026, 끝.
참고 / References
- [Temporal — Durable execution platform](https://temporal.io/)
- [Temporal Documentation](https://docs.temporal.io/)
- [Cadence — Uber open source](https://cadenceworkflow.io/)
- [Inngest — Durable event-driven functions](https://www.inngest.com/)
- [Inngest Documentation](https://www.inngest.com/docs)
- [Trigger.dev — Background jobs platform](https://trigger.dev/)
- [Trigger.dev v3 Documentation](https://trigger.dev/docs)
- [Hatchet — Postgres-native task queue](https://hatchet.run/)
- [Hatchet GitHub — hatchet-dev/hatchet](https://github.com/hatchet-dev/hatchet)
- [Restate — Durable stateful invocations](https://restate.dev/)
- [DBOS — Postgres-native compute](https://www.dbos.dev/)
- [AWS Step Functions](https://aws.amazon.com/step-functions/)
- [Apache Airflow](https://airflow.apache.org/)
- [Prefect](https://www.prefect.io/)
- [Dagster](https://dagster.io/)
- [Argo Workflows — argoproj](https://argoproj.github.io/argo-workflows/)
- [Camunda — BPMN process automation](https://camunda.com/)
- [Netflix Conductor / Orkes](https://orkes.io/)
- [Saga pattern — Hector Garcia-Molina, 1987](https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf)
- [Pattern: Saga — microservices.io](https://microservices.io/patterns/data/saga.html)
현재 단락 (1/497)
2026년 봄, 한 AI 스타트업의 엔지니어가 슬랙에 글을 남긴다.