--- id: backend-edge-functions title: Edge Functions — Cloudflare / Vercel / Deno Deploy category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [backend, edge, serverless, vibe-coding] tech_stack: { language: "TS", applicable_to: ["Backend"] } applied_in: [] aliases: [Cloudflare Workers, Vercel Edge, Deno Deploy, edge runtime, V8 isolate, Wasm edge] --- # Edge Functions > 사용자 가까이 (300+ region) 실행. **Cloudflare Workers / Vercel Edge / Deno Deploy / Fastly Compute@Edge**. V8 isolate (cold start ms), 작은 limit. ## 📖 핵심 개념 - V8 Isolate: process 안 — 매 request fast. - Web Standard: Request / Response / fetch. - Limits: CPU / memory / time 작음. - Storage: KV / D1 / Durable Object / R2. ## 💻 코드 패턴 ### Cloudflare Workers ```ts // src/index.ts export interface Env { DB: D1Database; CACHE: KVNamespace; BUCKET: R2Bucket; } export default { async fetch(req: Request, env: Env, ctx: ExecutionContext): Promise { const url = new URL(req.url); if (url.pathname === '/api/users/me') { const userId = await getUserId(req); const cached = await env.CACHE.get(`user:${userId}`, { type: 'json' }); if (cached) return Response.json(cached); const user = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first(); ctx.waitUntil(env.CACHE.put(`user:${userId}`, JSON.stringify(user), { expirationTtl: 60 })); return Response.json(user); } return new Response('Not found', { status: 404 }); }, }; ``` ```toml # wrangler.toml name = "my-api" main = "src/index.ts" compatibility_date = "2024-12-01" [[d1_databases]] binding = "DB" database_name = "my-app" database_id = "..." [[kv_namespaces]] binding = "CACHE" id = "..." [[r2_buckets]] binding = "BUCKET" bucket_name = "uploads" [observability] enabled = true ``` ```bash wrangler dev wrangler deploy ``` ### Vercel Edge Function ```ts // app/api/users/route.ts import { type NextRequest } from 'next/server'; export const runtime = 'edge'; export async function GET(req: NextRequest) { const id = req.nextUrl.searchParams.get('id'); return Response.json({ id }); } ``` ```ts // 또는 standalone // pages/api/edge.ts export const config = { runtime: 'edge' }; export default function handler(req: Request) { return new Response('Hello from edge'); } ``` ### Deno Deploy ```ts import { Hono } from 'hono'; const app = new Hono(); app.get('/', (c) => c.text('Hello from Deno Deploy')); Deno.serve(app.fetch); ``` ```bash deployctl deploy --project=my-app src/index.ts ``` ### Bun on edge (Fly.io / Railway) ``` Bun = full Node API + Web Standard. Fly / Railway 가 Bun runtime 지원. Edge X but 가까운 region. ``` ### KV (Cloudflare) ```ts // 빠른 read (eventually consistent globally) await env.KV.put('key', 'value', { expirationTtl: 3600 }); const v = await env.KV.get('key'); const json = await env.KV.get('key', { type: 'json' }); // List const list = await env.KV.list({ prefix: 'user:' }); // Stream large const stream = await env.KV.get('large-file', { type: 'stream' }); ``` → Read 빠름 (각 region cache), write 글로벌 propagate (1-60s). ### D1 (SQLite at edge) ```ts const r = await env.DB.prepare('SELECT * FROM users WHERE email = ?') .bind('a@b.com') .first(); // Multi const all = await env.DB.prepare('SELECT * FROM users WHERE status = ?') .bind('active') .all(); // Batch (transaction) await env.DB.batch([ env.DB.prepare('INSERT INTO users VALUES (?, ?)').bind(id1, email1), env.DB.prepare('INSERT INTO users VALUES (?, ?)').bind(id2, email2), ]); ``` ### Durable Objects (글로벌 state) ```ts // Counter — 한 instance per name, 글로벌 단일 export class Counter { state: DurableObjectState; constructor(state: DurableObjectState) { this.state = state; } async fetch(req: Request): Promise { let count = (await this.state.storage.get('count')) ?? 0; count++; await this.state.storage.put('count', count); return Response.json({ count }); } } // Worker export default { async fetch(req: Request, env: Env) { const url = new URL(req.url); const name = url.searchParams.get('room') ?? 'default'; const id = env.COUNTER.idFromName(name); const stub = env.COUNTER.get(id); return stub.fetch(req); }, }; ``` → Stateful — chat room, game session, rate limit. ### R2 (S3-compatible storage) ```ts const obj = await env.BUCKET.get('photo.jpg'); if (obj) return new Response(obj.body, { headers: { 'Content-Type': obj.httpMetadata?.contentType ?? '' } }); await env.BUCKET.put('upload.jpg', file, { httpMetadata: { contentType: 'image/jpeg' }, }); await env.BUCKET.delete('old.jpg'); ``` → S3-compat + free egress. ### Cron triggers ```toml # wrangler.toml [triggers] crons = ["0 9 * * *"] # 매일 9시 ``` ```ts export default { async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext) { await runDailyTask(env); }, async fetch(req: Request, env: Env) { ... }, }; ``` ### Queues (Cloudflare) ```ts // Producer await env.QUEUE.send({ orderId: '...', userId: '...' }); // Consumer export default { async queue(batch: MessageBatch, env: Env) { for (const msg of batch.messages) { await processOrder(msg.body); msg.ack(); } }, }; ``` → Decouple. ### Limits (대략) ``` Cloudflare Workers: - CPU: 30s (paid) / 10ms (free) per request - Memory: 128 MB - Subrequests: 1000 - Bundle: 10 MB - Compute units / month: $5 = 10M+ Vercel Edge: - CPU: 30s - Memory: 128 MB - Bundle: 1 MB Deno Deploy: - CPU: 50ms (per request) - Memory: 512 MB ``` → Long-running task = 다른 (Lambda / VM). ### Edge 의 함정 ``` 1. CPU limit (10ms free) — 큰 work X. 2. Bundle size — Node module 일부 X. 3. Cold start — 거의 0 (V8 isolate). 4. Connection pool 어려움 (no persistent state). 5. 일부 Node API X (fs, child_process). ``` → HTTP / KV / D1 만 사용. ### Use cases (적합) ``` - API gateway (auth, rate limit, route) - A/B test, geo redirect - Image / response transformation - Analytics ingestion - Search index 호출 - Cache layer - Webhook receiver - Static site SSR ``` ### Use cases (안 적합) ``` - 큰 ML inference - Long task (1 min+) - Persistent connection (DB pool) - File system 의존 - Large dependencies (Node-specific) ``` ### Multi-region database ``` Edge function 가 사용자 가까이. DB 가 single region = 큰 latency. 해결: - Read replica per region - Hyperdrive (CF cache) - Turso embedded replica - 분산 DB (Spanner, Yugabyte) ``` ### Auth at edge ```ts import { jwt } from 'hono/jwt'; app.use('/api/*', jwt({ secret: env.JWT_SECRET })); // 또는 직접 async function verifyJwt(token: string, secret: string) { const [header, payload, signature] = token.split('.'); // JWT verify (jose 같은 lib) return JSON.parse(atob(payload)); } ``` ### Static + Edge function ``` Vercel / Cloudflare Pages: - Static assets — CDN - API routes — edge function → Most modern stack. ``` ### Streaming ```ts export default { async fetch() { const { readable, writable } = new TransformStream(); const writer = writable.getWriter(); (async () => { for (let i = 0; i < 5; i++) { await writer.write(new TextEncoder().encode(`chunk ${i}\n`)); await new Promise(r => setTimeout(r, 1000)); } writer.close(); })(); return new Response(readable); }, }; ``` → SSE / streaming response. ### Test (local) ```bash wrangler dev # local + miniflare (Cloudflare emulator) vercel dev deno run --watch src/index.ts ``` ### Deploy ```bash wrangler deploy --env production vercel --prod deployctl deploy --prod ``` ### Cost ``` Cloudflare Workers: Free: 100K req/day Paid: $5/month + $0.50 per million Vercel: Hobby: free Pro: $20/month + execution time ``` → 가장 cheap edge. ### Comparison ``` Cloudflare: + 가장 빠름 (V8 isolate) + KV / D1 / R2 통합 + Free tier 강 - Node API 제한 Vercel: + Next.js 통합 (best) + Frontend / API 통합 - 비싸 (큰 traffic) Deno Deploy: + Deno native + Web Standard - Smaller ecosystem Fastly Compute@Edge: + Wasm 지원 + 큰 enterprise ``` ## 🤔 의사결정 기준 | 상황 | 추천 | |---|---| | 빠른 API + 글로벌 | Cloudflare Workers | | Next.js | Vercel Edge | | Deno project | Deno Deploy | | Wasm | Fastly / CF Workers | | Long task | Lambda / VM | | Big data | Container / VM | ## ❌ 안티패턴 - **Edge 안 long task**: timeout. - **Big bundle (큰 dep)**: limit. - **Node-specific (fs, net)**: 깨짐. - **DB persistent connection**: HTTP driver. - **Edge 가 모든 답**: 가까운 user 가 critical 시만. - **State in memory**: cold isolate 에 잃음. KV / DO. ## 🤖 LLM 활용 힌트 - Cloudflare Workers + D1 + KV = 가장 강. - Vercel Edge + Next.js = best DX. - Web Standard API only. - Cold start 거의 0. ## 🔗 관련 문서 - [[Backend_Hono_Modern]] - [[DB_Serverless_Edge]] - [[Backend_Geo_Replication]]