> ## Documentation Index
> Fetch the complete documentation index at: https://supastack.dev/llms.txt
> Use this file to discover all available pages before exploring further.
> For the full documentation corpus in one file, fetch: https://supastack.dev/llms-full.txt

# 스팸 방지

공개 폼과 인증 엔드포인트의 env 전환형 Turnstile 검사.

## 초보자 연습

전제 조건: 아래 두 개의 초보자 가이드를 읽고, 웹 로컬 설정을 완료하고, 편집기의 루트에서 이 모노레포를 엽니다. 웹 설정은 `apps/web/.env.local`에 속합니다. Next.js는 ​​루트 `.env`를 읽지 않습니다. 기본 가짜 모드의 `/dashboard`는 데이터베이스가 없는 데모입니다. `/auth`에는 마이그레이션된 데이터베이스가 필요합니다.

빠른 용어: 작업 영역은 한 팀의 별도 사용자, 데이터 및 설정입니다. 서버는 신뢰할 수 있는 백엔드입니다. 제공업체 키를 브라우저 및 전화 코드에 보관하세요. 마이그레이션은 테이블을 생성하거나 업데이트하는 버전이 지정된 데이터베이스 변경입니다. AI 모델은 응답하는 엔진입니다. 모델 카탈로그는 서버의 사용 가능한 모델 ID 및 가격 목록입니다. 공급자는 AI, 이메일, 청구 서비스와 같은 외부 서비스입니다. 자격은 작업 영역에서 기능을 사용할 수 있도록 하는 부여입니다. 웹훅은 한 서비스가 다른 서비스의 URL에 보내는 메시지입니다.

1. 정확한 로컬/배포된 호스트 이름에 대한 Turnstile 테스트 위젯을 만듭니다. `apps/web/.env.local`에서 `CAPTCHA_PROVIDER=turnstile` 및 `NEXT_PUBLIC_TURNSTILE_SITE_KEY`를 설정합니다. `TURNSTILE_SECRET_KEY`를 서버 비밀 저장소에만 넣으세요.

2. 다시 시작하고 테스트 문의 양식을 제출하세요.

3. 챌린지와 성공적인 유효한 토큰 응답을 기대합니다. 모든 요청이 실패하면 호스트 이름과 키 쌍을 비교하십시오. 비밀 키를 절대 노출하지 마세요.

사용자 정의 코드의 경우 제공된 `prompts/README.md`로 시작하고 가장 가까운 프롬프트(앱 화면의 경우 `prompts/new-app-screen.md`, 공개 페이지의 경우 `prompts/new-landing-page.md`)를 복사합니다. 서버, 데이터베이스 또는 공급자 작업의 경우 코딩 에이전트에게 이 가이드의 작업을 제공하고 `AGENTS.md`, `.ai/PROJECT_CONTEXT.md` 및 일치하는 `.ai/` 미러를 읽도록 요청하세요. 여기에 이름이 지정된 정확한 소스 파일을 검사하십시오. 편집하기 전에 파일을 나열하고 확인합니다. 작업 공간 소유권과 서버 전용 비밀을 보존합니다. 차이점을 보여주세요. 원하는 동작, 입력 및 출력 필드, 허용된 역할, 예상되는 성공 및 오류, 테스트 계정, 공급자 또는 장치를 알려주십시오. 샘플 값을 사용하십시오. 절대 진짜 비밀을 붙여넣지 마세요.

[시작하기 전에](https://supastack.dev/ko/docs/web/before-you-start.md)

[단말기 기본사항](https://supastack.dev/ko/docs/web/terminal-basics.md)

[웹 로컬 설정](https://supastack.dev/ko/docs/web/ship-in-5-minutes.md)

[에이전트 프롬프트 및 프로젝트 메모리](https://supastack.dev/ko/docs/web/agents.md)


## 두 키 모두 활성화

`CAPTCHA_PROVIDER=off`가 기본값입니다. `turnstile`를 선택하고 Turnstile 애플리케이션에서 일치하는 호스트 이름을 구성한 후 두 키를 모두 제공하세요. `NEXT_PUBLIC_TURNSTILE_SITE_KEY`는 공개입니다. `TURNSTILE_SECRET_KEY`는 서버 검증자에서만 사용됩니다.

```
CAPTCHA_PROVIDER=turnstile
NEXT_PUBLIC_TURNSTILE_SITE_KEY=your-site-key
# TURNSTILE_SECRET_KEY belongs in the server secret store.
```


## 보호된 표면을 보존하세요

게이트에는 연락처/뉴스레터 양식과 Better Auth 로그인, 가입, OTP 및 비밀번호 재설정 자격 증명 엔드포인트가 포함됩니다. 유효성 검사/속도 제한을 보완합니다. 이는 세션 또는 작업 공간 인증을 대체하지 않습니다.


## 거부 및 복구 확인

유효한 토큰, 누락/만료/잘못된 토큰, 확인자 실패 및 클라이언트 위젯 재설정 후 재시도를 테스트합니다. 실행 가능한 사람이 직접 확인하는 사본 및 키보드 액세스를 유지하세요. 공급자를 전환하기 전에 선택한 인증 엔진의 적용 범위를 검사하세요.

[보호된 양식](https://supastack.dev/ko/docs/web/project-structure.md)

[인증 엔진 차이점](https://supastack.dev/ko/docs/web/project-structure.md)


## 설치 및 설정

CAPTCHA_PROVIDER가 검증기를 선택합니다: off(기본값 — 로컬 개발은 자격 증명 없이 유지) 또는 turnstile. turnstile을 켜면 서버의 TURNSTILE_SECRET_KEY와 클라이언트 위젯의 NEXT_PUBLIC_TURNSTILE_SITE_KEY가 필요합니다 — 하나라도 없으면 config 스키마가 시작을 실패시킵니다.

apps/web/src/captcha.ts는 프로세스 전체의 검증기 하나를 구성해 토큰을 10초 타임아웃으로 Cloudflare siteverify 엔드포인트에 POST하고 실패 시 닫힙니다 — 검증 불가한 토큰은 사람임의 증거로 취급되지 않습니다.

```
CAPTCHA_PROVIDER=turnstile
TURNSTILE_SECRET_KEY=…           # server-only
NEXT_PUBLIC_TURNSTILE_SITE_KEY=…

Guarded: sign-in/up, OTP send, reset,
contact + newsletter forms
```


## 구현 워크플로

CaptchaWidget(src/captcha-widget.tsx)이 위젯을 렌더링하고 cf-turnstile-response 필드를 부모 폼에 주입하며, 인증 클라이언트 호출은 x-captcha-response 헤더로 토큰을 전달합니다. contact와 newsletter 액션은 쓰기 전에 검증합니다 — 실패한 검사는 lead를 만들지 않고 status=captcha를 반환합니다.

packages/auth는 프로바이더가 켜져 있을 때 better-auth의 captcha 플러그인을 마운트합니다. CAPTCHA_ENDPOINTS는 자격 증명 입력과 토큰 발급 라우트 — 로그인, 가입, OTP 발송, 비밀번호 재설정 — 를 커버합니다. check-verification-otp 같은 소비 엔드포인트는 목록에서 제외됩니다: 거기서는 OTP나 토큰 자체가 증거입니다.


## 검증 및 문제 해결

보호된 각 폼을 토큰 없이, 그리고 잘못된 토큰으로 제출하세요 — 둘 다 실패 시 닫혀야 합니다. siteverify에 도달할 수 없을 때 통과가 아닌 거부가 되는지, provider=off가 로컬 개발을 열어 두는지, 시크릿이 클라이언트 번들이나 로그에 절대 도달하지 않는지 확인하세요.


## 다음

[관리자 콘솔](https://supastack.dev/ko/docs/web/admin.md)
