작은 블로그 댓글은 방문자가 많지 않아도 스팸이 먼저 옵니다.
영문 광고, 카지노 링크, 가짜 문의, 자동화된 POST 요청이 쌓이면 댓글 기능을 켜두기 어려워집니다.
Cloudflare Turnstile은 이런 폼 스팸을 줄이는 데 쓸 수 있는 가벼운 선택지입니다.
다만 프론트엔드에 위젯만 붙이면 끝나는 기능은 아닙니다. Cloudflare 문서도 Turnstile 구현은 서버에서 Siteverify API를 호출해 토큰을 검증해야 완료된다고 안내합니다.
이 글은 2026년 5월 28일 기준 Cloudflare 공식 문서를 바탕으로, 작은 블로그 댓글 폼에 Turnstile을 붙일 때 필요한 흐름을 정리합니다.
먼저 결론
댓글 스팸 방지는 Turnstile 하나로 끝내기보다 아래 4개를 같이 둬야 합니다.
- Turnstile client widget
- server-side token validation
- IP 또는 fingerprint 기준 rate limit
- 댓글 moderation 또는 링크 제한
Turnstile은 “사람인지 확인하는 관문”이고, 댓글 시스템의 정책 전체를 대신하지는 않습니다.
기본 흐름
작은 블로그 댓글 폼에서는 보통 이런 순서로 붙입니다.
- Cloudflare 대시보드에서 Turnstile widget을 만듭니다.
- 댓글 폼에 sitekey를 넣어 widget을 렌더링합니다.
- 사용자가 댓글을 제출하면
cf-turnstile-response토큰을 서버로 보냅니다. - 서버는 secret key와 token을 Cloudflare Siteverify API로 검증합니다.
success가 true일 때만 댓글 저장 로직으로 넘어갑니다.- 실패하면 댓글을 저장하지 않고 다시 시도하게 합니다.
중요한 점은 4번입니다.
브라우저에서 위젯이 보였다는 사실만으로는 보호가 끝나지 않습니다.
1. Managed widget부터 시작합니다
Cloudflare Turnstile widget에는 Managed, Non-Interactive, Invisible 모드가 있습니다.
Cloudflare 문서 기준 Managed는 방문자 위험도에 따라 비대화형 또는 체크박스 challenge를 자동으로 선택하는 권장 모드입니다.
작은 블로그 댓글에는 보통 Managed가 가장 무난합니다.
- 스팸이 적을 때는 방문자 마찰이 낮습니다.
- 의심스러운 요청에는 추가 확인을 요구할 수 있습니다.
- 구현과 설명이 단순합니다.
Invisible 모드는 화면을 깔끔하게 만들 수 있지만, 개인정보 처리방침에 Turnstile Privacy Addendum 참조가 필요하다는 조건이 있습니다.
처음 붙일 때는 Managed로 시작하고, 실제 실패율과 댓글 전환을 본 뒤 조정하는 편이 안전합니다.
2. secret key는 서버에만 둡니다
Turnstile에는 sitekey와 secret key가 있습니다.
- sitekey: 브라우저에 노출돼도 되는 공개 키
- secret key: 서버 검증에 쓰는 비공개 키
작은 사이트에서 흔한 실수는 secret key를 프론트엔드 코드나 정적 빌드 결과에 넣는 것입니다.
Astro 정적 페이지, React 컴포넌트, HTML 안에 secret key가 들어가면 그대로 공개됩니다.
권장 구조는 이렇습니다.
브라우저 댓글 폼
-> cf-turnstile-response 포함해 /api/comments 로 POST
-> Node.js API가 TURNSTILE_SECRET으로 Siteverify 호출
-> 성공 시 댓글 저장
환경 변수 이름은 예를 들어 이렇게 둘 수 있습니다.
PUBLIC_TURNSTILE_SITE_KEY=0x...
TURNSTILE_SECRET_KEY=0x...
PUBLIC_ 접두어가 붙는 값은 노출돼도 되는 값에만 사용해야 합니다.
3. 서버 검증은 필수입니다
Cloudflare Siteverify API의 endpoint는 다음과 같습니다.
POST https://challenges.cloudflare.com/turnstile/v0/siteverify
서버는 최소한 아래 값을 보냅니다.
secret: Cloudflare 대시보드의 secret keyresponse: 브라우저가 보낸 Turnstile tokenremoteip: 선택 사항이지만 가능하면 방문자 IP
검증 결과가 success: true일 때만 댓글을 저장합니다.
의사 코드는 이렇습니다.
async function verifyTurnstile(token, remoteip) {
const response = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: process.env.TURNSTILE_SECRET_KEY,
response: token,
remoteip,
}),
});
const result = await response.json();
return result.success === true;
}
여기서 중요한 규칙은 실패 시 “일단 저장하고 나중에 지우기”가 아니라 저장 전 차단입니다.
4. 토큰은 짧고 한 번만 쓴다고 봐야 합니다
Cloudflare 문서 기준 Turnstile token은 300초 동안 유효하고, 한 번만 검증할 수 있습니다.
이미 검증한 token을 다시 쓰면 timeout-or-duplicate 오류가 날 수 있습니다.
댓글 폼에서는 이 점 때문에 아래 처리가 필요합니다.
- 사용자가 오래 머문 뒤 제출하면 token이 만료될 수 있습니다.
- 제출 실패 후 다시 제출할 때 widget reset이 필요할 수 있습니다.
- 브라우저 새로고침이나 중복 클릭을 고려해야 합니다.
- 서버가 retry할 수 있다면 idempotency key를 고려합니다.
즉 “댓글 쓰고 한참 뒤 제출” 시나리오를 꼭 테스트해야 합니다.
5. Turnstile만으로 링크 스팸은 다 막히지 않습니다
Turnstile은 자동화된 요청을 줄여주지만, 사람이 직접 넣는 스팸이나 저품질 댓글까지 모두 막지는 않습니다.
작은 블로그라면 아래 규칙을 같이 두는 편이 현실적입니다.
- 댓글 본문 링크 개수 제한
- 같은 IP의 짧은 시간 내 반복 제출 제한
- 새 댓글은 기본 pending 상태로 저장
- 금칙어보다 URL 패턴과 반복 문구를 우선 확인
- 관리자 댓글 승인 UI 제공
- 너무 긴 댓글, 빈 댓글, 동일 댓글 재제출 차단
댓글 스팸은 보안 문제이면서 운영 문제입니다.
처음부터 완전 자동 공개보다 검증 통과 후 moderation 흐름이 안전합니다.
6. Cloudflare WAF와 섞을 때는 역할을 나눕니다
Cloudflare에는 Turnstile 외에도 WAF, managed challenge, rate limiting 같은 기능이 있습니다.
작은 블로그에서는 처음부터 복잡하게 묶기보다 역할을 나누는 편이 좋습니다.
- 댓글 제출 endpoint: Turnstile server validation
- 너무 잦은 POST: rate limit
- 관리자 경로: Access 또는 별도 인증
- 사이트 전체 공격: WAF rule
Turnstile pre-clearance는 Cloudflare 보호 도메인에서 clearance cookie를 활용하는 기능입니다.
일반 댓글 폼만 막는 목적이라면 먼저 기본 Siteverify 검증부터 붙이는 편이 낫습니다.
적용 전 체크리스트
Turnstile을 댓글에 붙이기 전에 아래를 확인합니다.
- sitekey와 secret key를 분리했는가
- secret key가 정적 빌드 결과에 들어가지 않는가
- 서버에서 Siteverify API를 호출하는가
- 검증 실패 시 댓글 저장이 차단되는가
- token 만료와 중복 제출을 처리하는가
- 댓글 POST endpoint에 rate limit이 있는가
- 링크 스팸과 moderation 정책이 있는가
- Invisible mode를 쓰면 privacy policy 조건을 확인했는가
한 줄 결론
Cloudflare Turnstile은 작은 블로그 댓글 스팸을 줄이는 좋은 출발점입니다.
하지만 진짜 보호는 위젯 표시가 아니라 서버 검증, rate limit, 댓글 정책까지 이어질 때 완성됩니다.
같이 보면 좋은 글
출처
- Cloudflare Turnstile Docs: Turnstile widgets
https://developers.cloudflare.com/turnstile/concepts/widget/ - Cloudflare Turnstile Docs: Validate the token
https://developers.cloudflare.com/turnstile/get-started/server-side-validation/ - Cloudflare Turnstile Docs: Pre-clearance configuration
https://developers.cloudflare.com/turnstile/additional-configuration/hostname-management/pre-clearance/ - Cloudflare Turnstile Docs: Token validation analytics
https://developers.cloudflare.com/turnstile/turnstile-analytics/token-validation/
의견 남기기
댓글은 서버 API에 저장되며, 기본 설정에서는 검토 후 공개됩니다.