정적 블로그(Next.js를 output: 'export'로 빌드한 사이트)에 댓글을 붙이려면 보통 giscus, Disqus, Utterances 같은 외부 위젯을 먼저 떠올려요. 저는 자체 D1을 골랐어요. 왜 그랬는지, 그리고 0부터 어떻게 붙이는지를 따라하기로 정리했어요.
왜 giscus·Disqus가 아니었나
- giscus·Utterances는 댓글을 GitHub 이슈/디스커션에 저장해요. 그래서 독자가 댓글을 남기려면 GitHub 로그인을 해야 해요. 개발 블로그라도 일반 독자에겐 진입장벽이에요.
- Disqus 무료 플랜은 광고가 붙고, 제3자 추적 스크립트라 개인정보(PIPA) 관점에서 부담이 있어요.
- 둘 다 댓글 전용이라 조회수·방문자·좋아요는 따로 못 줘요.
- 자체 D1은 같은 Cloudflare 배포 안에서 댓글·조회수·좋아요·방문자를 한 번에 처리해요. 데이터는 제 D1에만 있고, 외부 추적 스크립트는 0개예요. 익명 댓글이라 독자가 로그인할 필요도 없고요. 개인 블로그 트래픽이면 D1 무료 한도로 충분해요.
1) D1 만들고 바인딩하기
먼저 정적 결과물을 올리는 그 Pages 프로젝트의 wrangler.toml에 D1을 묶어요. 바인딩 이름(DB)이 코드에서 env.DB로 그대로 쓰여요.
[[d1_databases]]
binding = "DB"
database_name = "lifecarelog-blog-db"
database_id = "..." # 아래 명령으로 생성 후 채우기
wrangler d1 create lifecarelog-blog-db
출력된 database_id를 위 설정에 붙여넣으면 연결 끝이에요.
2) 스키마 한 번에 적용하기
테이블은 마이그레이션 파일 하나로 만들어요. 조회수(post_views), 좋아요(post_likes), 댓글(comments), 방문자(visits) 네 가지를 한 파일에 담아 원격 D1에 실행해요.
wrangler d1 execute lifecarelog-blog-db --remote --file migrations/0001_init.sql
3) functions/ 폴더가 곧 API
여기가 핵심이에요. functions/ 안의 파일 경로가 그대로 엣지 API 라우트가 돼요. 따로 서버를 띄울 필요가 없어요. 예를 들어 functions/api/views/[slug].ts는 POST /api/views/:slug가 돼요. Workers 런타임이라 Node가 아닌 Web 표준(Request/Response, crypto.subtle)을 쓴다는 점만 기억하면 돼요.
// functions/api/views/[slug].ts → POST /api/views/:slug
// 같은 방문자는 하루 한 번만 카운트
const dedup = await env.DB.prepare(
'INSERT OR IGNORE INTO view_dedup (slug, visitor_hash, day) VALUES (?,?,?)',
).bind(slug, vh, todayUTC()).run();
if (dedup.meta.changes > 0) {
await env.DB.prepare(
'INSERT INTO post_views (slug, count) VALUES (?,1) ON CONFLICT(slug) DO UPDATE SET count = count + 1',
).bind(slug).run();
}
새로고침마다 조회수가 오르지 않게, view_dedup에 행이 실제로 들어갔을 때만 카운트를 올려요.
4) 시크릿은 코드에 두지 않기
방문자 해시용 솔트(HASH_SALT)와 댓글 삭제용 관리자 키(ADMIN_SECRET)는 절대 코드나 깃에 두면 안 돼요. 배포는 명령으로 주입하고, 로컬은 .dev.vars(gitignore)에 둬요.
wrangler pages secret put HASH_SALT
wrangler pages secret put ADMIN_SECRET
이렇게 네 단계면 정적 사이트 위에 동적 백엔드가 올라가요. 서버를 따로 운영하지 않고, 데이터는 내 손 안에 두면서요.
여러분은 정적 블로그 댓글을 외부 위젯으로 붙이세요, 아니면 직접 만드세요? 댓글로 어떤 방식을 쓰는지 알려주세요!
'백엔드·인프라' 카테고리의 다른 글
| Supabase 새 테이블, RLS만 켜면 안 돼요 — 2026-05-30 GRANT 변경 (0) | 2026.06.25 |
|---|---|
| 유료 크레딧 차감을 안전하게 — SELECT FOR UPDATE와 단일 트랜잭션 (0) | 2026.06.25 |