Workflow 장기 실행
Workflow를 장기 실행 에이전트의 오케스트레이션 계층으로 사용해 승인, 이벤트 재개, durable replay를 구현하는 방법을 정리합니다.
에이전트가 실제 업무를 다루기 시작하면 요청-응답 구조만으로는 부족합니다.
승인 대기, 외부 웹훅 재개, 긴 시간의 분석 작업, 밤새 돌아가는 배치가 생기기 때문입니다. 이때 필요한 것은 "더 긴 timeout"이 아니라 durable execution 모델입니다.
Workflow에 올려야 하는 작업
Vercel Workflows는 2026년 4월 GA 이후 "use workflow"와 "use step" directive를 중심으로 설명됩니다. workflow 함수는 오케스트레이션을, step 함수는 재시도·영속화·관측 가능한 작업 단위를 담당합니다.
| 작업 유형 | Workflow 적합도 | 이유 |
|---|---|---|
| 즉시 채팅 응답 | 낮음 | request path에 남기는 편이 단순 |
| 수분~수시간 배치 분석 | 높음 | 재개 가능성과 상태 추적 필요 |
| 사람 승인 대기 | 매우 높음 | external event와 pause/resume 필요 |
| 외부 API 재시도 | 높음 | step retry와 backoff 관리 필요 |
| cron성 작업 | 중간 | 큐 또는 스케줄 작업과 비교 필요 |
실행 구조
Workflow와 Queue의 경계
| 질문 | Workflow | Queue |
|---|---|---|
| 상태 재개가 필요한가 | 강점 | 약함 |
| 사람 승인/이벤트 대기가 필요한가 | 강점 | 별도 구현 필요 |
| 단순 fan-out 비동기 처리인가 | 가능 | 더 단순할 수 있음 |
| 실행 경로를 단계별로 감사해야 하는가 | 강점 | 제한적 |
step 설계 원칙
| 원칙 | 이유 | 예시 |
|---|---|---|
| step은 작게 유지 | 재시도 단위 명확화 | fetch data, run model, persist result |
| side effect는 뒤로 민다 | replay 시 중복 방지 | approval 이후 write 실행 |
| human approval은 별도 단계 | business gate 명시 | payment, message send, privilege grant |
| versioned deployment를 고려 | 장기 실행 중 코드 변경 대비 | migration-safe payload 사용 |
예시: 승인 포함 오케스트레이션
import { defineHook, sleep } from 'workflow'
const approvalHook = defineHook<{ approved: boolean; operatorId: string }>()
export async function customerEscalation(ticketId: string) {
'use workflow'
const summary = await summarizeTicket(ticketId)
const approval = approvalHook.create({ token: `ticket:${ticketId}` })
await sendApprovalRequest({ ticketId, summary, token: approval.token })
const result = await Promise.race([
approval,
sleep('24h').then(() => ({ approved: false, operatorId: 'timeout' })),
])
if (!result.approved) {
return { status: 'rejected' }
}
return executeEscalation(summary)
}
async function summarizeTicket(ticketId: string) {
'use step'
return loadAndSummarizeTicket(ticketId)
}
async function executeEscalation(summary: TicketSummary) {
'use step'
return dispatchEscalation(summary)
}승인이 필요한 업무 예시
| 업무 | 승인 이유 | 기본 대기 시간 |
|---|---|---|
| 고객에게 금전성 혜택 발송 | 비용/악용 방지 | 4시간 |
| 권한 승격 | 보안 리스크 | 24시간 |
| 법적 문안 발송 | 규제 리스크 | 8시간 |
| 대량 외부 메시지 발송 | 브랜드 리스크 | 2시간 |
추론
Vercel Workflow는 장기 실행과 이벤트 재개를 강점으로 하지만, 모든 비동기 작업을 Workflow로 몰아넣는 것은 좋지 않습니다. 단순 큐잉과 상태 머신은 분리하는 편이 비용과 운영 복잡도 모두에서 유리합니다.
운영 기준
- 사용자가 기다리는 요청과 사람이 나중에 확인할 작업을 분리합니다.
- 승인 전 단계는 읽기 중심으로 설계하고, 쓰기는 승인 뒤에 배치합니다.
- step payload는 버전 호환성을 고려해 최소 필드만 유지합니다.
- replay 가능한 설계를 위해 외부 side effect idempotency key를 사용합니다.
ADR 스타일 결론
Decision
장기 실행, 외부 이벤트 재개, 사람 승인 대기가 있는 작업은 Workflow로 이동합니다. request timeout을 늘려 해결하지 않고, durable state machine으로 모델링합니다.
실무 체크리스트
- 30초 이상 걸리는 작업이 request path에 남아 있지 않은가
- approval 전에 irreversible side effect가 실행되지 않는가
- step payload가 버전 안전한 최소 구조로 유지되는가
- 외부 write가 idempotency key를 갖는가