← 글 목록으로 돌아가기

Astro + Cloudflare에 DB(데이터베이스) 연동하여 동적 웹사이트 구축하기

Cloudflare D1 서버리스 SQL과 Supabase를 Astro와 바인딩하여 서버비 0원에 댓글, 방명록, 실시간 조회수 기능을 갖춘 고성능 풀스택 웹앱을 완성하는 실무 가이드.

AI Executive Summary1초 핵심 요약
  • Cloudflare D1의 초저지연 서버리스 SQL을 활용한 완전 무료 데이터베이스 인프라 구축
  • Astro SSR 모드 전환 및 타입 세이프한 Drizzle ORM 스키마 설계와 쿼리 최적화
  • 정적 블로그의 초고속 렌더링 성능을 유지하면서 실시간 동적 API 엔드포인트 완벽 연동
Astro + Cloudflare에 DB(데이터베이스) 연동하여 동적 웹사이트 구축하기

정적 블로그에서 실시간 동적 웹사이트로의 진화

Astro와 Cloudflare Pages의 결합은 초기 페이지 로딩 속도와 검색 엔진 최적화(SEO) 측면에서 세계 최고 수준의 정적 블로그 환경을 제공합니다.

하지만 사이트가 성장함에 따라 독자들과의 직접적인 소통을 위한 실시간 댓글 창, 방명록, 포스트별 조회수 카운터, 혹은 사용자 계정 기반의 회원가입 기능과 같은 인터랙티브한 동적(Dynamic) 요구사항이 반드시 생겨나게 됩니다.

과거에는 이러한 동적 기능을 구현하기 위해 별도의 백엔드 가상 서버를 대여하고 MySQL이나 PostgreSQL 인스턴스를 유지해야 했으나, 2026년 현재는 Cloudflare D1 및 Supabase와 같은 차세대 서버리스 데이터베이스를 바인딩함으로써 추가 비용 없이 완전 무료로 풀스택 동적 웹 애플리케이션을 운영할 수 있습니다.

이 가이드에서는 기본 정적 Astro 블로그에 Cloudflare D1 서버리스 SQL을 연결하고 실시간 댓글 API와 UI를 구축하는 전 과정을 실무 코드와 함께 상세히 설명합니다.


📑 목차 (Table of Contents)

  1. 초보자를 위한 핵심 용어 사전
  2. 무료 서버리스 데이터베이스 솔루션 비교 (D1 vs Supabase)
  3. 1단계: Astro SSR(서버 사이드 렌더링) 모드 활성화
  4. 2단계: Cloudflare D1 데이터베이스 생성 및 로컬 바인딩
  5. 3단계: 테이블 스키마 정의 및 초기 데이터 마이그레이션
  6. 4단계: 실시간 댓글 CRUD API 엔드포인트 작성
  7. 5단계: 프로덕션 배포 및 성능 검증

초보자를 위한 핵심 용어 사전

데이터베이스 연동이 생소한 프론트엔드 개발자와 입문자를 위해 핵심 인프라 용어를 쉽게 정리합니다.

기술 용어 한글 설명 및 개념 본 튜토리얼에서의 역할
Cloudflare D1 Cloudflare 전 세계 엣지 네트워크에 분산 배치된 서버리스 관계형(SQLite 기반) 데이터베이스 하루 500만 회 읽기 무료 혜택으로 댓글 및 조회수 데이터 저장
SSR (Server-Side Rendering) 사용자의 요청이 들어오는 순간 엣지 서버에서 즉시 데이터를 조회하여 HTML 또는 JSON을 응답하는 렌더링 방식 실시간 댓글 목록이나 최신 동적 콘텐츠를 즉각 브라우저로 전달
바인딩 (Binding) Cloudflare Workers/Pages 코드 내에서 복잡한 커넥션 풀 설정 없이 환경 변수처럼 DB 객체에 직접 접근하는 연결 방식 `locals.runtime.env.DB` 한 줄로 안전하게 SQL 쿼리 실행
ORM (Object-Relational Mapping) SQL 쿼리를 직접 작성하는 대신 타입스크립트 코드로 데이터베이스 테이블을 다룰 수 있게 해주는 도구 컴파일 타임 타입 검사와 자동 완성으로 쿼리 실수 및 런타임 오류 원천 방지

무료 서버리스 데이터베이스 솔루션 비교 (D1 vs Supabase)

웹 서비스 개발 시 가장 널리 사용되는 두 가지 무료 데이터베이스 옵션의 장단점을 비교하여 프로젝트 목적에 맞는 최적의 선택을 돕습니다.

비교 기준 Cloudflare D1 (본 가이드 채택) Supabase (PostgreSQL BaaS)
엔진 및 아키텍처 SQLite 기반 전 세계 엣지 복제 분산 SQL 표준 엔터프라이즈 PostgreSQL 16+ 인스턴스
무료 사용량 한도 하루 500만 회 읽기 / 10만 회 쓰기 500MB 데이터 저장 공간 및 50,000 MAU 무료
연동 복잡도 Cloudflare 대시보드 클릭 1번으로 바인딩 완수 Supabase 클라이언트 라이브러리 및 API 키 설정 필요
적합한 서비스 블로그 댓글, 방명록, 실시간 카운터, 투표 시스템 복잡한 다대다 관계형 서비스, 소셜 OAuth 로그인, 대용량 스토리지

서버리스 인프라 전반의 동작 원리와 기본 호스팅 설정은 블로그의 서버비 0원으로 만드는 Astro + Cloudflare Pages 초고속 블로그 구축기 포스트에서 기초 내용을 먼저 살펴보실 수 있습니다.


1단계: Astro SSR(서버 사이드 렌더링) 모드 활성화

기본 정적 블로그 프로젝트에서 실시간 API 라우트를 처리하려면 Cloudflare 공식 어댑터를 프로젝트에 추가해야 합니다. 터미널에서 다음 명령어를 실행합니다.

# Cloudflare 어댑터 자동 설치 및 설정 주입
npx astro add cloudflare

설치가 완료되면 astro.config.mjs 파일이 자동으로 업데이트되며, 하이브리드(Hybrid) 또는 서버(Server) 모드로 동작할 수 있는 기반이 마련됩니다.

// astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  output: 'server', // 또는 정적 페이지 유지를 위해 'hybrid' 선택
  adapter: cloudflare({
    platformProxy: {
      enabled: true // 로컬 개발 시 Cloudflare 바인딩을 에뮬레이트
    }
  })
});

2단계: Cloudflare D1 데이터베이스 생성 및 로컬 바인딩

Wrangler CLI를 활용하거나 Cloudflare 공식 대시보드 웹 콘솔에서 클릭 몇 번으로 D1 인스턴스를 즉시 생성할 수 있습니다.

# Wrangler CLI를 통한 D1 데이터베이스 신규 생성
npx wrangler d1 create my-blog-db

명령어가 성공하면 데이터베이스 이름과 고유한 database_id UUID 값이 터미널에 출력됩니다. 이를 프로젝트 루트의 wrangler.toml 파일에 바인딩 정보로 등록합니다.

# wrangler.toml
name = "my-tech-blog"
pages_build_output_dir = "dist"

[[d1_databases]]
binding = "DB"
database_name = "my-blog-db"
database_id = "여기에-출력된-데이터베이스-ID-입력"

3단계: 테이블 스키마 정의 및 초기 데이터 마이그레이션

댓글과 방명록 데이터를 안정적으로 보관하기 위한 테이블 스키마 SQL 파일을 생성합니다. 프로젝트 루트에 migrations/0001_create_comments.sql 파일을 만듭니다.

-- migrations/0001_create_comments.sql
CREATE TABLE IF NOT EXISTS comments (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  post_slug TEXT NOT NULL,
  author_name TEXT NOT NULL,
  author_email TEXT,
  content TEXT NOT NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 포스트별 댓글 조회를 고속화하기 위한 인덱스 생성
CREATE INDEX IF NOT EXISTS idx_comments_slug ON comments (post_slug);

로컬 환경 및 원격 Cloudflare 서버에 마이그레이션을 순서대로 적용합니다.

# 로컬 개발용 로컬 SQLite 에뮬레이터에 적용
npx wrangler d1 execute my-blog-db --local --file=migrations/0001_create_comments.sql

# 원격 프로덕션 Cloudflare D1 인스턴스에 적용
npx wrangler d1 execute my-blog-db --remote --file=migrations/0001_create_comments.sql

4단계: 실시간 댓글 CRUD API 엔드포인트 작성

Astro의 서버 엔드포인트 파일인 src/pages/api/comments.ts를 생성하여 댓글 목록 조회(GET) 및 새 댓글 작성(POST) API를 작성합니다.

// src/pages/api/comments.ts
import type { APIRoute } from 'astro';

export const GET: APIRoute = async ({ request, locals }) => {
  const url = new URL(request.url);
  const slug = url.searchParams.get('slug');

  if (!slug) {
    return new Response(JSON.stringify({ error: 'post_slug parameter is required' }), {
      status: 400,
      headers: { 'Content-Type': 'application/json' }
    });
  }

  // Cloudflare D1 바인딩 객체 접근
  const runtime = locals.runtime as any;
  const db = runtime?.env?.DB;

  if (!db) {
    return new Response(JSON.stringify({ error: 'Database binding not found' }), { status: 500 });
  }

  const { results } = await db
    .prepare('SELECT id, author_name, content, created_at FROM comments WHERE post_slug = ? ORDER BY created_at DESC')
    .bind(slug)
    .all();

  return new Response(JSON.stringify(results), {
    status: 200,
    headers: {
      'Content-Type': 'application/json',
      'Cache-Control': 'public, max-age=10, s-maxage=30' // 엣지 CDN 캐싱 적용
    }
  });
};

export const POST: APIRoute = async ({ request, locals }) => {
  try {
    const body = await request.json();
    const { slug, author, content } = body;

    if (!slug || !author || !content) {
      return new Response(JSON.stringify({ error: 'All fields are required' }), { status: 400 });
    }

    const runtime = locals.runtime as any;
    const db = runtime?.env?.DB;

    await db
      .prepare('INSERT INTO comments (post_slug, author_name, content) VALUES (?, ?, ?)')
      .bind(slug, author, content)
      .run();

    return new Response(JSON.stringify({ success: true }), {
      status: 201,
      headers: { 'Content-Type': 'application/json' }
    });
  } catch (error: any) {
    return new Response(JSON.stringify({ error: error.message }), { status: 500 });
  }
};

5단계: 프로덕션 배포 및 성능 검증

Cloudflare 대시보드의 Pages 프로젝트 설정 페이지에서 방금 생성한 D1 데이터베이스를 최종 바인딩합니다.

  1. 대시보드 Settings 메뉴 진입: Workers & Pages $\rightarrow$ 본인의 Astro 프로젝트 $\rightarrow$ Settings $\rightarrow$ Functions로 이동합니다.
  2. D1 database bindings 설정: Add binding을 누르고 Variable name에 DB, D1 database name에 my-blog-db를 선택 후 저장합니다.
  3. Git 푸시를 통한 자동 배포: 코드를 커밋하고 GitHub main 브랜치로 푸시하면 1분 이내에 동적 데이터베이스가 결합된 최신 버전이 글로벌 엣지로 배포됩니다.

이로써 정적 아일랜드 아키텍처의 빠른 검색 색인 성능과 실시간 풀스택 웹 애플리케이션의 유연성을 완벽하게 동시에 확보할 수 있게 되었습니다.

웹 개발 전반의 최신 프레임워크 패러다임과 기술 흐름에 대해 더 깊이 이해하고 싶으시다면 2026년 웹 개발 & AI 코딩 에이전트 핵심 트렌드 분석 글을 함께 확인해 보시기 바랍니다.

NT

NewType Studio Editorial

기술과 디자인의 경계를 허무는 세련된 디지털 가치를 만듭니다.