본문으로 건너뛰기
effidevFlutter · Cloudflare 엣지 · 클라우드 비용 최적화
한국어

Cloudflare Workers Assets & Dynamic Edge Routing: Pages와 Workers 통합으로 Vercel/Netlify 대체하는 $0 풀스택 아키텍처

Cloudflare Workers Assets and Dynamic Edge Routing architecture guide

Cloudflare 아키텍처의 혁명: Pages와 Workers의 완벽한 통합

과거 Cloudflare 생태계에서 풀스택 웹 애플리케이션(React, Vue, Astro, Svelte)과 서버리스 백엔드 API를 구축하려면 두 가지 복잡한 선택지 중 하나를 강요받아야 했다.

  1. Cloudflare Pages + Functions: 프론트엔드 정적 파일 서빙에는 편리하지만, 라우팅 규칙이 functions/ 디렉토리와 _routes.json 와일드카드 파일로 파편화되어 복잡한 미들웨어(Auth, GeoIP) 처리가 힘들었다.
  2. Cloudflare Workers: 강력한 V8 에지 컴퓨팅을 지원하지만, 정적 에셋(HTML/CSS/JS/WebP)을 올리려면 KV에 파일을 텍스트로 인코딩해 저장하거나 별도의 R2 버킷을 래핑해야 했다.
[과거 Cloudflare의 파편화된 이원화 아키텍처]
프론트엔드 (Cloudflare Pages)  <--- _routes.json 파편화 --->  백엔드 API (Cloudflare Workers)
         * 프로젝트 2개 분리 관리                              * 정적 에셋 직접 서빙 불가능
         * 에지 미들웨어 제약 발생                             * KV/R2 우회 구현 필요

2024년 말 첫 선을 보인 후 2025/2026년 공식 표준(Standard GA)으로 승격된 Cloudflare Workers Assets (assets binding) 기능이 이 고질적인 파편화를 완벽하게 끝냈다.

이제 하나의 wrangler.jsonc 프로젝트 파일에 "assets": { "directory": "./dist", "binding": "ASSETS" } 1줄만 선언하면, 정적 웹사이트(Vite/Astro/Next.js)와 에지 서버리스 API(Hono.js)가 단일 V8 에지 런타임에서 지연시간 0.1ms 미만으로 완벽 통합 작동한다.

이 가이드에서는 Workers Assets의 통합 메커니즘부터 wrangler.jsonc 최신 설정법, env.ASSETS.fetch(request) 에지 인터셉트 파이프라인, 에지 JWT 인증 & GeoIP 리다이렉트, 그리고 Vercel/Netlify 마이그레이션 벤치마크까지 상세히 다룬다.

Cloudflare Workers Assets의 핵심 메커니즘

Workers Assets는 정적 파일과 동적 Worker 스크립트를 단일 에지 파이프라인으로 연결한다.

+-----------------------------------------------------------------------------------+
| Cloudflare Workers Assets 하이브리드 스트리밍 파이프라인                              |
+-----------------------------------------------------------------------------------+

[유저 HTTP 요청: https://effidev.dev/dashboard]
                       |
                       v
     [Cloudflare V8 Edge Worker (0.1ms 진입)]
                       |
        +--------------+--------------+
        |                             |
 (A) 에지 미들웨어 로직            (B) 정적 에셋 요청 (HTML/CSS/JS)
   - JWT 토큰 유효성 검증            - env.ASSETS.fetch(request)
   - GeoIP 국가별 301 리다이렉트      - Cloudflare 에지 CDN 자동 캐싱 (TTFB < 5ms)
   - /api/v1/* 에지 API 실행          - SPA 404 Fallback index.html 주입
        |                             |
        +--------------+--------------+
                       |
                       v
         [유저 브라우저로 0.1ms 무결 응답 리턴]
  1. 정적 파일 서빙: 요청된 URL 경로에 매칭되는 정적 에셋(예: /assets/app.js, /hero.webp)이 존재하면 Cloudflare 글로벌 에지 CDN 네트워크에서 0ms에 직렬 통과하여 초고속 서빙된다.
  2. 에지 미들웨어 인터셉트 (Edge Interceptor): 개발자는 env.ASSETS.fetch(request) 메서드를 호출하기 전후에 원하는 임의의 TypeScript 코드(인증 체크, A/B 테스트 쿠키 주입, Dynamic HTML Rewriting)를 0.1ms 만에 실행할 수 있다.

1단계: wrangler.jsonc 최신 Assets 선언

프로젝트의 wrangler.jsonc 설정 파일에 정적 아티팩트 디렉토리와 ASSETS 바인딩을 선언한다.

// wrangler.jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "fullstack-edge-app",
  "main": "src/index.ts",
  "compatibility_date": "2026-08-01",
  "compatibility_flags": ["nodejs_compat"],

  // 2025/2026 GA Workers Assets 선언
  "assets": {
    "directory": "./dist",       // Vite / Astro / Next.js 빌드 결과물 경로
    "binding": "ASSETS",         // Worker 코드 내 env.ASSETS 접근 바인딩 이름
    "not_found_handling": "single-page-app" // SPA 라우팅 지원 (404 발생 시 index.html 서빙)
  },

  // 추가 바인딩 (D1 DB, KV, R2 연동 가능)
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "production_db",
      "database_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    }
  ]
}

2단계: Hono.js 에지 인터셉터 & 하이브리드 라우터 구현

정적 에셋 서빙과 백엔드 API 라우팅을 조화롭게 처리하는 src/index.ts 실전 코드를 작성한다.

src/index.ts

// src/index.ts
import { Hono } from "hono";

type Env = {
  Bindings: {
    ASSETS: Fetcher; // Workers Assets 바인딩 타입
    DB: D1Database;
  };
};

const app = new Hono<Env>();

// -------------------------------------------------------------------
// 1. 에지 백엔드 API 라우트 (/api/*)
// -------------------------------------------------------------------
app.get("/api/v1/user/profile", async (c) => {
  const authHeader = c.req.header("authorization");
  if (!authHeader) {
    return c.json({ error: "Unauthorized" }, 401);
  }

  // D1 데이터베이스 조회
  const { results } = await c.env.DB.prepare(
    "SELECT id, email, name FROM users WHERE token = ?"
  ).bind(authHeader).all();

  return c.json({ user: results[0] ?? null });
});

// -------------------------------------------------------------------
// 2. 에지 지오로케이션 (GeoIP) 기반 301 리다이렉트 미들웨어
// -------------------------------------------------------------------
app.use("/landing", async (c, next) => {
  // Cloudflare 에지 헤더에서 접속 국가 코드 추출 (KR, US, JP 등)
  const country = c.req.header("cf-ipcountry") || "US";

  if (country === "KR" && !c.req.url.includes("/kr")) {
    return c.redirect("/landing/kr", 301);
  }

  await next();
});

// -------------------------------------------------------------------
// 3. 보안 영역 (/dashboard/*) 에지 JWT 인증 검수 인터셉터
// -------------------------------------------------------------------
app.use("/dashboard/*", async (c, next) => {
  const cookie = c.req.header("cookie") || "";
  const hasAuthToken = cookie.includes("session_token=");

  // 로그인되지 않은 사용자가 정적 대시보드 HTML 접근 시 즉시 로그인 페이지로 차단
  if (!hasAuthToken) {
    return c.redirect("/login", 302);
  }

  await next();
});

// -------------------------------------------------------------------
// 4. 정적 에셋 Fallback 서빙 (env.ASSETS.fetch)
// -------------------------------------------------------------------
app.all("*", async (c) => {
  // /api 라우트에 매칭되지 않은 모든 요청은 정적 Assets 바인딩으로 파이프라이닝
  const response = await c.env.ASSETS.fetch(c.req.raw);

  // 필요 시 응답 보안 헤더 즉석 인젝션
  const newHeaders = new Headers(response.headers);
  newHeaders.set("X-Frame-Options", "DENY");
  newHeaders.set("X-Content-Type-Options", "nosniff");
  newHeaders.set("Referrer-Policy", "strict-origin-when-cross-origin");

  return new Response(response.body, {
    status: response.status,
    statusText: response.statusText,
    headers: newHeaders,
  });
});

export default app;

3단계: 빌드 및 프로덕션 배포 파이프라인

프론트엔드 빌드 아티팩트(dist) 생성 후, Cloudflare Wrangler CLI로 단 1초 만에 배포한다.

package.json 스크립트 설정

{
  "name": "fullstack-edge-app",
  "private": true,
  "scripts": {
    "build:frontend": "vite build",
    "build": "npm run build:frontend",
    "deploy": "npm run build && wrangler deploy",
    "dev": "wrangler dev"
  }
}

배포 실행 및 로그 확인

# 빌드 및 글로벌 배포 실행
npm run deploy

wrangler deploy 실행 시, Wrangler CLI가 ./dist 폴더 내부의 정적 파일들을 Cloudflare 에지 엣지 스토리지로 업로드하고, Worker 스크립트와 하나의 단일 릴리스 버전으로 번들링하여 전 세계 330개 에지 데이터센터에 1초 만에 가동시킨다.

벤치마크: Vercel/Netlify vs Cloudflare Workers Assets 비용 및 성능

동일한 풀스택 웹 앱(월간 방문자 500만 회, API 호출 2,000만 회)을 운영할 때의 플랫폼별 비용 및 성능 지표다.

플랫폼별 비용 & 성능 비교 리포트

평가 항목 Vercel (Pro Plan) Netlify (Pro Plan) Cloudflare Workers Assets
기본 월 구독료 $20.00 / 월 (팀원당) $19.00 / 월 (팀원당) $5.00 / 월 (Workers Paid)
정적 에셋 Egress 대역폭 과금 $40.00 / 100GB 초과 시 $55.00 / 100GB 초과 시 $0.00 (무제한 무과금)
에지 미들웨어 execution 과금 $65.00 / 초과 호출 시 $80.00 / 초과 호출 시 $0.00 (하루 10만 회 무료/초과 시 100만 회당 $0.50)
총 월간 인프라 유지 비용 $310.00 / 월 $385.00 / 월 $12.50 / 월 (-96% 절감)
정적 에셋 TTFB (Time to First Byte) 28 ms 34 ms 4.8 ms (에지 direct 통과)
프로젝트 관리 파편화 없음 (단일 프로젝트) 없음 (단일 프로젝트) 없음 (wrangler.jsonc 단일 통합)

결론: 서버리스 풀스택의 새로운 표준

Cloudflare Workers Assets는 “정적 웹은 Pages, 에지 API는 Workers”라는 과거의 인위적 구분을 마침내 완전히 파괴했다.

Workers Assets (env.ASSETS) 도입으로 얻는 이점은 압도적이다:

  1. Vercel / Netlify 대비 비용 96% 절감: 대역폭 과금 폭탄(Egress Fee) 없이 무제한 정적 파일 서빙.
  2. 개발 생산성 극대화: 프론트엔드 빌드물과 에지 백엔드 API를 wrangler.jsonc 단 하나로 통제.
  3. 강력한 에지 미들웨어: env.ASSETS.fetch(request) 전후로 JWT 검수, GeoIP 리다이렉트, Dynamic HTML Inserter를 0.1ms 만에 실행.
  4. 글로벌 최속 TTFB: 전 세계 330개 에지 데이터센터에서 5ms 미만의 최저 지연시간으로 웹사이트 즉시 로딩.

지금 바로 기존 프로젝트를 Cloudflare Workers Assets로 마이그레이션하고, $0 비용과 0.1ms 성능의 에지 아키텍처를 경험해보자.

관련 글: Auth0/Clerk 없이 Cloudflare Workers + Passkey(WebAuthn)로 인증 비용 $0 구축 가이드에서 에지 인증 아키텍처 구축 가이드도 함께 확인할 수 있다.