노션에 쓰면 자동 발행되는 블로그를 만들었다 (3) — 댓글을 직접 만들었다

정적 사이트에 댓글 붙이기. 외부 서비스(Cusdis)의 한계에 부딪혀 Cloudflare Worker+D1로 익명 댓글을 직접 만든 과정.

이 블로그 자체를 만든 이야기 (3/3) — 이 편은 댓글을 직접 만든 이야기.

개인 블로그에 댓글을 달고 싶었다. 근데 정적 사이트라 댓글을 저장할 서버가 없다. 여기서부터 또 삽질이 시작됐다.

처음엔 외부 서비스(Cusdis)를 붙였다

서버 없이 댓글을 붙이는 제일 쉬운 길은 외부 위젯이다. Cusdis(오픈소스, 익명 댓글)를 붙였다. 근데 두 가지가 걸렸다.

  1. iframe이 안 늘어났다 — 댓글이 쌓여도 위젯 높이가 220px에 고정돼 내부 스크롤이 생겼다. Cusdis가 리사이즈 신호를 안 보내서 자동 확장이 안 먹었다.
  2. 익명이라 “작성자 인증”이 안 됐다 — 누구나 내 닉네임을 똑같이 칠 수 있으니 사칭이 가능했다. 자동 승인 토글도 없었다.

1번은 우회했다. Cusdis iframe이 srcdoc이라 부모 페이지와 same-origin이길래, 내부 문서 높이를 직접 읽어 iframe 높이에 반영했다.

근데 2번(사칭)은 익명 구조의 원리적 한계라 우회가 안 됐다.

그래서 직접 만들었다 (Worker + D1)

백엔드를 내가 소유하면 익명이어도 세 가지가 풀린다.

Cloudflare Worker (/api/comments)  ←→  Cloudflare D1 (댓글 저장)
  • 자동 승인: 내 DB니까 즉시 노출 + 삭제 관리 내 맘대로.
  • 작성자 인증(사칭 불가): OAuth 대신 나만 아는 관리자 토큰. 내가 댓글 달 때 서버가 토큰을 검증해서 작성자 플래그를 서버가 박는다. 닉네임 문자열이 아니라 서버 권한이라 남이 못 따라 한다.
// 서버가 토큰을 확인해서 is_author를 정한다 (닉네임 신뢰 X)
const isAuthor = isAdmin(body.adminToken, env) ? 1 : 0;
  • 스레드(답글): parent_id로 1단계 답글.

여기에 익명 방문자 표시로 IP 앞 2옥텟(123.123)만 붙였다. 원문 IP는 저장 안 하고 마스킹한 것만 저장한다.

결과

  • 방문자는 로그인 없이 닉네임+내용만으로 바로 댓글.
  • 내 댓글은 작성자 배지 + 강조색 (서버 검증).
  • iframe이 없어서 사이트 테마·폰트가 그대로 적용된다. (Cusdis의 iframe 높이 문제도 원천 소멸)

배운 것

지금은 아무도 안 들어오는 블로그지만 나중에 방문할 누군가의 댓글에 내가 답글을 달았다는 인증을 하고 싶었다. 로그인 없이도 서버가 비밀 토큰 하나만 검증하면 됐다. 남이 흉내 못 내는 건 서버만 아는 값이니까.

스팸은 아직 IP 레이트리밋 + 허니팟 수준이고, 실제로 오면 그때 캐차를 붙일 생각이다.


여기까지가 블로그를 만든 기록 3편이다. 노션에 쓰면 자동 발행되고, 내가 고친 삽질과 댓글까지 — 이 글도 블로그에 이렇게 올라왔다.

댓글

익명 댓글입니다. 닉네임과 내용이 저장되며, 서로 존중하는 표현을 부탁드려요. 부적절하거나 광고성 댓글은 예고 없이 삭제될 수 있습니다.