브라우저로 내려간 값은 무엇이든 공개다. VITE_LEAD_TOKEN 이 번들에 평문으로
박혀 있었고(실제로 추출해 확인했다) 토큰은 보호 장치가 되지 못했다. 토큰을
새로 발급해도 똑같이 공개된다.
- api/lead.js 신규. 토큰과 Apps Script 주소를 서버 환경변수(LEAD_TOKEN·
LEAD_ENDPOINT)로만 들고 요청을 전달한다. VITE_ 접두사를 쓰지 않아 번들에
들어가지 않는다.
- Origin 허용 목록으로 webforai.kr·www·aio2o.webforai.kr 만 받는다. 토큰과
달리 Origin 은 브라우저가 채우고 스크립트가 바꿀 수 없다. 다른 사이트에
폼을 심어 이 주소를 때리는 것을 막는다. aio2o 는 정적 배포라 자체 함수를
둘 수 없어 이 함수를 같이 쓴다(교차 출처라 CORS 를 명시).
- submitLead 는 같은 출처 /api/lead 로 보낸다. 클라이언트 환경변수가 없어졌다.
- vercel.json 의 전체 경로 리라이트에서 /api 를 제외한다. 안 그러면 함수
요청까지 index.html 로 삼킨다.
Vercel 환경변수: LEAD_ENDPOINT·LEAD_TOKEN 추가, VITE_LEAD_* 2개 삭제.
Vite 는 코드에서 안 쓰더라도 VITE_ 접두사 변수를 전부 번들에 넣기 때문에
삭제까지 해야 토큰이 사라진다(삭제 전 재배포에서 여전히 검출됐다).
검증: 운영 번들에서 토큰 0건·script.google.com 0건. /api/lead 정상 응답
{"ok":true,"mailed":true}. 다른 Origin 403. SPA 라우트(/discovery/:id·
/actions/:id) 200 유지. 실제 폼 제출 접수 확인.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .claude | ||
| .vscode | ||
| api | ||
| data | ||
| doc | ||
| docs | ||
| evidence/viewclinic | ||
| plugins | ||
| public | ||
| reference | ||
| scripts | ||
| src | ||
| supabase | ||
| supporters | ||
| templates/supporters-astro | ||
| workers/supporters-build | ||
| .env.example | ||
| .gitignore | ||
| .vercelignore | ||
| CLAUDE.md | ||
| extracted_marketing_text.md | ||
| index.html | ||
| Medical Marketing Intelligence Report Prompt_01.28.2026.md | ||
| metadata.json | ||
| package-lock.json | ||
| package.json | ||
| PRD.md | ||
| README.md | ||
| tsconfig.json | ||
| vercel.json | ||
| Viewclinic Plan.md | ||
| vite.config.ts | ||
| 뷰성형외과_Marketing_Intelligence_Report.md | ||
Run and deploy your AI Studio app
This contains everything you need to run your app locally.
View your app in AI Studio: https://ai.studio/apps/d446f5f5-e089-404a-93ce-32a72f2f5108
Run Locally
Prerequisites: Node.js
- Install dependencies:
npm install - Set the
GEMINI_API_KEYin .env.local to your Gemini API key - Run the app:
npm run dev