Astro + Cloudflare Pages
Astro 프로젝트를 Cloudflare Pages에 배포하는 방법을 설명합니다. SSR(Server-side Rendering)을 활성화하여 동적 기능을 사용할 수 있습니다.
Video Tutorial
새 프로젝트 생성
create-cloudflare를 사용하여 Cloudflare에 최적화된 Astro 프로젝트를 생성합니다:
# npmnpm create cloudflare@latest -- my-astro-app --framework=astro --platform=pages
# yarnyarn create cloudflare my-astro-app --framework=astro --platform=pages
# pnpmpnpm create cloudflare@latest my-astro-app --framework=astro --platform=pages이 명령어는 다음을 자동으로 수행합니다:
- Astro 프로젝트 생성
- Wrangler CLI 설치
@astrojs/cloudflare어댑터 설치 및 설정- Git 초기화 (선택사항)
기존 프로젝트에 어댑터 추가
기존 Astro 프로젝트에 Cloudflare 어댑터를 추가하려면:
# npmnpx astro add cloudflare
# yarnyarn astro add cloudflare
# pnpmpnpm astro add cloudflare이 명령어는 astro.config.mjs를 자동으로 업데이트하여 SSR을 활성화합니다.
Astro 설정
기본 설정
astro.config.mjs:
import { defineConfig } from "astro/config";import cloudflare from "@astrojs/cloudflare";
export default defineConfig({ adapter: cloudflare(),});로컬 개발 런타임 활성화
로컬에서 Cloudflare 바인딩을 사용하려면 platformProxy를 활성화합니다:
import { defineConfig } from "astro/config";import cloudflare from "@astrojs/cloudflare";
export default defineConfig({ adapter: cloudflare({ platformProxy: { enabled: true, }, }),});Wrangler 설정
프로젝트 루트에 Wrangler 설정 파일을 생성합니다.
wrangler.toml
name = "my-astro-app"main = "./dist/_worker.js/index.js"compatibility_date = "2025-03-25"compatibility_flags = ["nodejs_compat"]
[assets]binding = "ASSETS"directory = "./dist"
[observability]enabled = truewrangler.jsonc
{ "$schema": "./node_modules/wrangler/config-schema.json", "name": "my-astro-app", "main": "./dist/_worker.js/index.js", "compatibility_date": "2025-03-25", "compatibility_flags": ["nodejs_compat"], "assets": { "binding": "ASSETS", "directory": "./dist" }, "observability": { "enabled": true }}바인딩 사용하기
Cloudflare 서비스(KV, D1, R2, Durable Objects 등)를 Astro에서 사용할 수 있습니다.
TypeScript 타입 설정
먼저 wrangler types 명령어로 타입을 생성한 후, src/env.d.ts를 업데이트합니다:
/// <reference types="astro/client" />
type ENV = { MY_KV: KVNamespace; DB: D1Database; MY_BUCKET: R2Bucket;};
type Runtime = import("@astrojs/cloudflare").Runtime<ENV>;
declare namespace App { interface Locals extends Runtime {}}API 라우트에서 바인딩 접근
src/pages/api/data.ts:
import type { APIContext } from "astro";
export async function GET({ locals }: APIContext) { const { MY_KV, DB } = locals.runtime.env;
// KV에서 데이터 읽기 const value = await MY_KV.get("my-key");
// D1에서 쿼리 실행 const { results } = await DB.prepare("SELECT * FROM users").all();
return new Response(JSON.stringify({ value, results }), { headers: { "Content-Type": "application/json" }, });}Astro 컴포넌트에서 바인딩 접근
---const myKV = Astro.locals.runtime.env.MY_KV;const value = await myKV.get("greeting");---
<div>{value}</div>환경 변수
wrangler.toml에서 설정
[vars]API_HOST = "api.example.com"PUBLIC_API_KEY = "pk_12345"
[env.staging][env.staging.vars]API_HOST = "staging.example.com"
[env.production][env.production.vars]API_HOST = "production.example.com"wrangler.jsonc에서 설정
{ "$schema": "./node_modules/wrangler/config-schema.json", "vars": { "API_HOST": "api.example.com", "PUBLIC_API_KEY": "pk_12345" }, "env": { "staging": { "vars": { "API_HOST": "staging.example.com" } }, "production": { "vars": { "API_HOST": "production.example.com" } } }}로컬 개발용 Secret
.dev.vars 파일을 생성하여 로컬에서 사용할 secret을 정의합니다:
API_SECRET=my-secret-keyDATABASE_URL=postgres://localhost:5432/mydb
.dev.vars파일은.gitignore에 추가하여 Git에 커밋하지 않도록 합니다.
환경별 secret은 .dev.vars.<environment> 파일로 관리합니다:
.dev.vars.staging.dev.vars.production
빌드 설정
Cloudflare Pages 대시보드에서 다음 값을 설정합니다:
| 설정 | 값 |
|---|---|
| Production branch | main |
| Build command | npm run build |
| Build directory | dist |
배포
Git 연동 (자동 배포)
- GitHub/GitLab에 코드를 푸시합니다
- Cloudflare 대시보드에서 저장소를 연결합니다
- 커밋할 때마다 자동으로 빌드 및 배포됩니다
- Pull Request에 대해 Preview 배포가 생성됩니다
Wrangler로 직접 배포
# 빌드npm run build
# 배포npx wrangler pages deploy dist환경별 배포
# 스테이징 배포npx wrangler pages deploy dist --env staging
# 프로덕션 배포npx wrangler pages deploy dist --env production정적 사이트 vs SSR
정적 사이트
Astro 프로젝트가 완전히 정적(pre-rendered)인 경우:
name = "my-static-site"compatibility_date = "2025-03-25"
[assets]directory = "./dist"SSR 사이트
동적 렌더링이 필요한 경우 main 필드를 추가합니다:
name = "my-ssr-site"main = "./dist/_worker.js/index.js"compatibility_date = "2025-03-25"compatibility_flags = ["nodejs_compat"]
[assets]binding = "ASSETS"directory = "./dist"바인딩 설정 예시
KV Namespace
[[kv_namespaces]]binding = "MY_KV"id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"D1 Database
[[d1_databases]]binding = "DB"database_name = "my-database"database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"R2 Bucket
[[r2_buckets]]binding = "MY_BUCKET"bucket_name = "my-bucket"package.json 스크립트
{ "scripts": { "dev": "astro dev", "build": "astro build", "preview": "wrangler pages dev dist", "deploy": "npm run build && wrangler pages deploy dist", "deploy:staging": "npm run build && wrangler pages deploy dist --env staging", "deploy:production": "npm run build && wrangler pages deploy dist --env production" }}