NestBook / Cloudflare + D1

Cloudflare Workers란?

Cloudflare Workers는 **전 세계 300개 이상의 데이터 센터(엣지 노드)**에서 코드를 실행하는 서버리스 플랫폼이다. 사용자가 서울에서 요청을 보내면 서울 근처 엣지에서 코드가 실행된다. 도쿄에서 보내면 도쿄에서 실행된다.

기존 서버리스 vs 엣지 컴퓨팅

일반적인 서버리스(AWS Lambda 등)는 특정 리전(서울, 도쿄 등)의 서버에서만 실행된다. 반면 Workers는 사용자와 가장 가까운 엣지에서 실행되어 레이턴시가 극적으로 낮아진다.

구분AWS LambdaCloudflare Workers
실행 위치선택한 리전 1곳전 세계 300+ 엣지
콜드 스타트100~500ms0ms (항상 워밍 상태)
런타임Node.js, Python 등V8 (JavaScript/TypeScript/WASM)
메모리 제한수백 MB128MB (충분히 가볍다)
무료 한도100만 req/월10만 req/일
💡 왜 콜드 스타트가 0ms인가?
Lambda는 함수가 오래 호출 안 되면 컨테이너가 종료된다. 다음 요청이 오면 컨테이너를 새로 띄우는 시간이 "콜드 스타트"다. Workers는 V8 Isolate(격리된 JS 실행 컨텍스트)를 사용해 컨테이너보다 수천 배 빠르게 시작할 수 있으며, 엣지 노드에서 항상 준비 상태를 유지한다.

Workers가 적합한 사용 사례

  • API 게이트웨이 — 인증, 라우팅, 요청 변환
  • 이미지 리사이징 — Cloudflare Images와 연동
  • A/B 테스트 — 엣지에서 요청을 분기
  • 지역별 콘텐츠 차별화 — 사용자 위치 기반 응답
  • KV/D1을 사용하는 풀스택 앱 — 완전한 백엔드
📌 Workers가 적합하지 않은 경우
  • CPU 연산이 오래 걸리는 작업 (최대 실행 시간 30초 제한, 무료 플랜 50ms)
  • 대용량 파일 처리 (메모리 128MB 제한)
  • Node.js 전용 API(fs, child_process 등)를 쓰는 기존 코드 — V8 Web API 환경이므로 Node.js API는 제한적으로 지원

Wrangler CLI 설치 및 계정 설정

Wrangler는 Cloudflare Workers 개발·배포 CLI 도구다.

1. Node.js 설치 확인

# Node.js 18 이상 필요
node -v   # v18.x 이상이어야 함
npm -v

2. Wrangler 설치

# 전역 설치 (권장)
npm install -g wrangler

# 또는 npx로 매번 실행 (설치 없이)
npx wrangler --version

3. Cloudflare 계정 연결

wrangler login

브라우저가 열리며 Cloudflare 대시보드 로그인 화면이 표시된다. 로그인하면 터미널에 “Successfully logged in” 메시지가 나온다.

# 로그인 확인
wrangler whoami
# 출력 예시:
# ⛅️ wrangler 3.x.x
# -------------------
# Getting User settings...
# 👋 You are logged in with an API Token, associated with the email 'your@email.com'!
⚠️ 무료 플랜 계정으로 충분하다
Cloudflare Workers는 무료 플랜으로 시작할 수 있다. 무료 플랜 한도: 요청 10만 건/일, 서브도메인 workers.dev 제공. 학습 목적으로는 무료 플랜이면 충분하다. 유료 플랜($5/월)은 CPU 시간 제한이 늘어나고 커스텀 도메인 연결이 간편해진다.

첫 번째 Worker 만들기

1. 프로젝트 초기화

# 새 Worker 프로젝트 생성
npm create cloudflare@latest my-first-worker

# 인터랙티브 프롬프트 응답:
# ? What type of application do you want to create?
#   > "Hello World" Worker
# ? Do you want to use TypeScript? Yes
# ? Do you want to deploy your application?  No (일단 로컬에서 확인)

2. 생성된 디렉토리 구조

my-first-worker/
├── src/
│   └── index.ts          ← 핵심 코드 — 여기서만 작업한다
├── wrangler.toml          ← Worker 설정 파일
├── package.json
├── tsconfig.json
└── .dev.vars              ← 로컬 환경 변수 (gitignore 필수!)

3. wrangler.toml 살펴보기

name = "my-first-worker"        # Worker 이름 (배포 시 URL 결정)
main = "src/index.ts"           # 진입점 파일
compatibility_date = "2024-01-01"  # Workers 런타임 버전 고정

# KV, D1 등 바인딩은 여기에 추가한다 (뒤 챕터에서 다룸)

4. Hello World 코드

src/index.ts를 열면 기본 코드가 있다:

// Cloudflare Workers 기본 타입 정의 임포트
export default {
  // fetch 핸들러 — 모든 HTTP 요청의 진입점
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    return new Response('Hello World!');
  },
};

세 가지 파라미터를 이해하는 것이 중요하다:

파라미터타입역할
requestRequest들어온 HTTP 요청 전체 (URL, 헤더, 바디 등)
envEnvKV, D1 같은 바인딩 객체에 접근하는 환경 변수
ctxExecutionContextwaitUntil(), passThroughOnException() 등 실행 컨텍스트

조금 더 실용적인 Hello World

단순히 “Hello World”를 반환하는 것에서 나아가, JSON 응답과 경로 분기를 추가한 실용적인 예시:

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    // 요청 URL 파싱
    const url = new URL(request.url);
    const pathname = url.pathname;

    // 경로별 분기
    if (pathname === '/') {
      // 홈: JSON 응답 반환
      return Response.json({
        message: '안녕하세요! Cloudflare Workers입니다.',
        timestamp: new Date().toISOString(),
        // CF-Ray 헤더에서 실행된 엣지 노드 정보 확인 가능
        region: request.headers.get('CF-Ray') ?? 'local',
      });
    }

    if (pathname === '/health') {
      // 헬스체크 엔드포인트
      return new Response('OK', { status: 200 });
    }

    // 매칭되지 않는 경로: 404 반환
    return new Response('Not Found', { status: 404 });
  },
};

로컬 테스트 및 배포

로컬 개발 서버 실행

cd my-first-worker
wrangler dev

# 출력 예시:
# ⛅️ wrangler 3.x.x
# ------------------
# ⎔ Starting local server...
# [mf:inf] Ready on http://localhost:8787

브라우저에서 http://localhost:8787 접속하면 응답 확인 가능하다. 파일을 수정하면 자동으로 핫 리로드된다.

배포

wrangler deploy

# 출력 예시:
# ⛅️ wrangler 3.x.x
# ------------------
# Total Upload: 1.23 KiB / gzip: 0.65 KiB
# Uploaded my-first-worker (1.23 sec)
# Published my-first-worker (0.30 sec)
#   https://my-first-worker.계정명.workers.dev

배포 후 https://my-first-worker.계정명.workers.dev 로 전 세계에서 접근 가능하다.

📌 배포 전 확인사항
  • wrangler.tomlname이 이미 사용 중인 이름이면 에러가 난다 — 고유한 이름으로 변경
  • 민감한 정보(API 키 등)는 절대 코드에 하드코딩하지 않는다 — wrangler secret 명령어 사용 (11챕터에서 다룸)
  • TypeScript 타입 오류가 있으면 빌드가 실패한다 — npm run typecheck 먼저 확인

핵심 포인트 정리

🚀 이 챕터에서 배운 것
  • Workers는 V8 Isolate 기반 — Node.js가 아니라 브라우저 Web API 환경에 가깝다
  • 콜드 스타트 없음 — 엣지 노드에서 항상 준비 상태
  • fetch 핸들러가 진입점request, env, ctx 세 파라미터를 기억한다
  • wrangler.toml이 설정 중심 — 이름, 진입점, 바인딩이 모두 여기에 정의된다
  • 무료 플랜: 10만 req/일 — 개인 프로젝트·학습에 충분

초보자 흔한 오해와 주의사항

오해 1: “Workers는 Node.js다” Workers는 Node.js가 아니다. V8 엔진 위의 Web Standard API 환경이다. require(), fs, path 같은 Node.js 전용 모듈은 기본적으로 쓸 수 없다. node_compat = true 옵션으로 일부 Node API를 폴리필할 수 있지만 제한이 있다.

오해 2: “로컬 개발은 완벽히 동일하다” wrangler dev는 로컬 시뮬레이션이지 실제 엣지 환경이 아니다. KV, D1 등 바인딩 동작이 미묘하게 다를 수 있다. 중요한 테스트는 스테이징 환경에서 wrangler deploy --env staging으로 확인한다.

주의: CPU 시간 제한 무료 플랜은 요청당 CPU 시간 10ms 제한이 있다. I/O(KV 읽기, fetch 요청 등) 대기 시간은 포함되지 않지만, JS 연산 자체가 오래 걸리면 에러가 난다. 복잡한 연산은 반드시 유료 플랜($5/월, 30초 제한)에서 테스트한다.


다음 챕터에서는 Request 객체를 완전히 분해하고, URL 라우팅·쿼리 파라미터 파싱·POST 바디 읽기·CORS 헤더 설정까지 실전 요청·응답 처리를 다룬다.