본문으로 이동
기사 목록으로 돌아가기
Infrastructure15分

Cloudflare Workers & Durable Objects 심층 분석: 전역 상태 머신 설계

Cloudflare Workers & Durable Objects Deep Dive: Designing Global State Machines

村田 聡Principal Edge Architect
2026-04-2115分
CloudflareWorkersDurable ObjectsWASMRustTypeScriptEdge Computing

Workers 플랫폼을 조감하다

Cloudflare Workers는 V8 Isolate를 기반으로 한 FaaS로, 2026년 4월 시점에서 330개 이상의 PoP에 동일 코드가 즉시 배포됩니다. 콜드 스타트는 실질적으로 제로에 가깝지만(많은 요청에서 5ms 미만), AWS Lambda처럼 컨테이너를 시작하는 것이 아니라 Isolate를 사용하는 제약으로 인해, Node.js 네이티브 모듈이나 장시간 블로킹 I/O는 본질적으로 적합하지 않습니다. 2025년 후반에 GA된 nodejs_compat_v2에 의해 fs/crypto/stream의 호환성이 크게 개선되었지만, 여전히 'Isolate의 작법'을 이해하지 않고 작성하면, 서브리퀘스트 상한(1,000)이나 CPU time 제한(유료 플랜에서 5분)에 충돌합니다.

Workers가 진정한 가치를 발휘하는 것은, 스테이트풀한 로직을 Durable Objects와 조합하는 순간입니다. Durable Object(이하 DO)는 '글로벌하게 고유한 ID를 가진, 단일 스레드·강정합성의 액터'이며, 요청은 동일 DO에 대해 반드시 직렬화됩니다. 이 모델은 '엣지에서의 mutex 대체'로 설계되어 있으며, 종래 Redis나 Postgres의 advisory lock으로 구현하던 '유저 단위의 레이트 리밋', '회의실 단위의 시그널링', '거래 ID 단위의 재고 할당'을 RTT를 거치지 않고 로컬에서 완결할 수 있습니다.

Durable Objects의 트랜잭션 모델

DO의 영속 스토어는 내부적으로 SQLite 기반의 storage API를 제공합니다. 2025년에 SQLite-backed DO가 전 플랜에 개방된 이후, 1 DO당 최대 10GB까지 관계 데이터를 저장할 수 있으며, transaction() 콜백 내에서 복수의 put/delete를 원자적으로 실행할 수 있습니다. 중요한 것은 DO가 '입력 게이트'와 '출력 게이트'를 내포하고 있다는 점입니다. 입력 게이트는 요청 처리 중 storage 쓰기 대기로 새로운 요청을 블록하며, 출력 게이트는 storage 쓰기가 영속화될 때까지 fetch 응답을 보류합니다. 이 이중 게이트에 의해, 애플리케이션 코드는 async/await를 자유롭게 써도 정합성이 무너지지 않습니다.

```typescript export class InventoryDO { state: DurableObjectState; constructor(state: DurableObjectState) { this.state = state; } async fetch(req: Request) { const { sku, qty } = await req.json<{ sku: string; qty: number }>(); return await this.state.storage.transaction(async (tx) => { const current = (await tx.get<number>(sku)) ?? 0; if (current < qty) return new Response("oos", { status: 409 }); await tx.put(sku, current - qty); return new Response(JSON.stringify({ remain: current - qty })); }); } } ```

DO를 액터 방식으로 사용할 때의 오남용으로 많은 것이 '1 DO로 모든 테넌트를 처리하는' 설계입니다. DO는 핫스팟이 되면 PoP가 고정되어 지리적으로 떨어진 유저에게 높은 RTT를 강요합니다. 정답은 idFromName()으로 '테넌트 ID + 리소스 ID'를 연결하여 샤딩하고, 쓰기가 지리적 지역성을 가지도록 배치하는 것입니다. 읽기는 replica DO(2025년 GA)로 비동기 레플리카에서 O(1)로 반환할 수 있습니다.

Workers KV, Hyperdrive, D1의 사용 구분

세 가지 데이터 레이어는 목적이 명확히 나뉩니다. Workers KV는 결과 정합의 읽기 최적화 스토어로, 60초 이내의 전파를 허용할 수 있는 설정값·메타데이터에 적합합니다. PUT의 전파 지연은 수 초에서 60초, 읽기는 PoP 로컬 캐시에서 1ms로 반환됩니다. Hyperdrive는 외부 Postgres/MySQL로의 접속 풀러로, 오리진으로의 TCP 접속을 재사용하면서 쿼리 결과를 PoP에서 캐시합니다. 기존 RDB 자산을 가진 조직이 엣지로 이전할 때의 첫 번째 단계로서 가장 현실적입니다. D1은 Cloudflare 자체의 SQLite 기반 RDB로, 2025년에 read replica가 GA되어, 쓰기는 프라이머리, 읽기는 가까운 replica라는 PostgreSQL 방식의 토폴로지를 취할 수 있습니다.

선정 기준은 '쓰기 빈도'와 '정합성 요건'으로 분해합니다. 초당 1,000 쓰기 이상으로 테넌트 단위로 분리 가능하다면 DO, 글로벌한 소수 write + 지역 분산 read라면 D1, 외부 DB가 이미 있다면 Hyperdrive, TTL 기반의 설정 배포라면 KV가 실무의 정석입니다. R2(S3 호환 오브젝트 스토리지)는 이것들과 직교하며, 이그레스 무료라는 특성을 살려 동영상 배포·백업·데이터 레이크에 사용합니다.

Workers AI와 추론 라우팅

Workers AI는 2024년 GA 이후, Llama 3.3 70B, Mistral Large 2, GPT-OSS-120B, Qwen 3 계열 등 주요 OSS 모델을 종량 과금으로 호출할 수 있습니다. 2026년 현재는 BYOK로 OpenAI/Anthropic/Google을 동일 API(AI Gateway) 경유로 라우팅할 수 있으며, 응답 캐시·재시도·레이트 리밋을 Workers 측에서 통합 관리할 수 있다는 점이 우위성이 되고 있습니다. AI Gateway의 로그는 Analytics Engine으로 흘러가므로, 프롬프트별 토큰 비용을 SQL로 쿼리할 수 있습니다.

레이턴시 최적화의 정석은 '작은 판정은 Workers AI의 로컬 추론, 복잡한 추론은 외부 LLM'이라는 하이브리드입니다. 예를 들어 Bot 판정·NSFW 분류·다국어 감지를 Workers AI의 Llama Guard/Llama-3 8B로 처리하고, 결과가 '불확실'한 경우에만 Claude나 GPT로 상향 라우팅하는 2단계 라우팅으로, 비용을 70% 절감한 사례를 저희 회사에서도 복수 확인하였습니다.

Rust + WASM 바인딩에 의한 핫패스 최적화

TypeScript로 5ms, Rust + WASM으로 0.8ms. 이 차이가 초당 10만 요청에서 효과를 발휘하면, CPU time 예산에 직결됩니다. workers-rs(Rust crate)는 #[event(fetch)] 매크로로 Workers 런타임에 컴파일할 수 있으며, wasm-bindgen 경유로 JS API(fetch/crypto/R2)에 접근할 수 있습니다. JSON 파싱이 무거운 API 게이트웨이나, HMAC 검증·JWT 검증·이미지 리사이즈를 Rust로 재작성하면 비용 절감 효과가 큽니다.

```rust use worker::*; #[event(fetch)] async fn main(req: Request, env: Env, _ctx: Context) -> Result<Response> { let body: serde_json::Value = req.json().await?; let signature = req.headers().get("x-signature")?.unwrap_or_default(); if !verify_hmac(&body, &signature, &env.secret("HMAC_KEY")?.to_string()) { return Response::error("invalid signature", 401); } Response::ok("ok") } ```

주의점으로, WASM 모듈 크기는 10MB까지로 억제해야 하며, wasm-opt -Oz와 wee_alloc의 조합으로 실효 크기를 반으로 줄일 수 있습니다. 시작 비용은 Isolate 재사용에 의해 거의 무시할 수 있지만, 초회 컴파일은 20~50ms 걸리므로, 트래픽이 극단적으로 낮은 PoP에서는 TypeScript 쪽이 빠른 역전 현상도 발생합니다. 벤치마크는 본番 PoP에서 취하는 것이 필수입니다.

글로벌 스테이트 머신 구축 패턴

WebSocket Hibernation + Durable Objects의 조합은, 실시간 협업 편집·라이브 방송의 시그널링·IoT 디바이스 오케스트레이션의 정석이 되었습니다. Hibernation API에 의해, WebSocket 접속은 열린 채로 메모리를 해제할 수 있으며, DO의 과금은 '활성 시간'만으로 됩니다. 100만 접속을 유지해도 월 수천 달러 이내에 수렴하는 비용 구조가, Ably나 Pusher 같은 서비스를 자체적으로 재구축하는 동기를 만들고 있습니다.

설계상의 포인트는, DO를 '스테이트 머신의 단일 노드'로 취급하는 것입니다. 상태 전이는 storage.transaction 내에서 state version을 CAS 업데이트하고, 외부 이벤트는 Queues 경유로 발화합니다. 실패 시의 보상 트랜잭션은 alarm() API로 지연 실행할 수 있습니다. 이를 통해 '엣지에서 시작하고, 엣지에서 끝나는' 사가 패턴을 낮은 레이턴시로 구성할 수 있습니다. 오리진으로 돌아가지 않는 아키텍처가, 2026년의 분산 시스템 설계의 주전장입니다.

기술적 과제를 함께 해결해 보시겠습니까?

KGA IT Solutions는 AI·클라우드·DevOps 전문 팀이 고객의 과제에 최적의 솔루션을 제공합니다.

문의하기