webforai.kr 공개 전 정리, API 키 서버 이전, 번들 검사 추가 #1

Open
haewonkam wants to merge 0 commits from feat/webforai-feature-flags into main
Owner

요약

2026-10-07 webforai.kr 보도자료 공개에 맞춘 정리입니다. 이 브랜치는 webforai.kr(infinith-discovery)과 데모(infinith-demo) 프로덕션에 이미 배포돼 있습니다. main 이 프로덕션보다 뒤처져 있어, main 기준으로 다시 배포하면 아래 조치가 되돌아가므로 병합합니다.

변경 내용

공개 사이트(webforai.kr) 정리

  • 실제 병원 정보 비노출: 랜딩 샘플을 가상 A성형외과 데이터로 교체, 실제 진단 리포트·내부 화면 경로는 홈으로 이동, 실제 리포트 파일·병원 스크린샷을 빌드 결과에서 제외, Supabase 접속 정보를 번들에서 제거
  • 진단 요청 버튼을 문의 서식(구글시트·메일 알림)으로 연결, 공개 폼에서 자동 빌드 큐로 가던 경로 차단
  • 요금(Pricing)·동작하지 않던 링크(Product·Use Cases·mailto) 숨김/삭제, 문구 정리
  • 개인정보처리방침·이용약관 페이지 추가 및 법무 검토 반영(국외 이전 기재사항, 법적 근거, AI 기본법 사전 고지 등), 검토 문서 docs/legal/
  • GTM·GA4 방문 측정 연결, 문의 접수 시 generate_lead 이벤트

재발 방지

  • 공개 기능 스위치 src/lib/site.ts (SHOW_PRICING·SHOW_SAMPLE_REPORT·SHOW_USE_CASES), 사용법 docs/WEBFORAI_FEATURE_FLAGS.md
  • 빌드 끝 번들 검사: 공개 배포에 실제 병원명·비밀 키·실제 파일이 있으면, 모든 배포에 서버 전용 키 값이 있으면 빌드 실패 (plugins/vite-plugin-public-bundle-guard.ts)

API 키 서버 이전

  • Gemini·Creatomate 호출을 Vercel 서버 함수(api/gemini-image.js, api/creatomate-render.js)로 이전, 키는 서버 환경변수에만
  • vite.config define 의 키 주입 제거, API 대시보드의 import.meta.env 동적 조회 제거(VITE_ 변수 전체가 번들에 들어가던 원인)
  • Edge Function 스크린샷 분석 모델 gemini-2.0-flash(Google 서비스 종료로 404)를 gemini-3.5-flash 로 교체 (운영 collect-channel-data v24 로 배포됨)

문서

  • RLS 익명 읽기 정리 SQL 초안 docs/security/ (실행 안 함, 결정 필요)
  • GTM 가져오기 파일 docs/analytics/

검증

  • npm run lint(tsc), webforai.kr·데모 빌드 통과, 번들 검사 통과
  • 라이브 확인: webforai.kr 공개 페이지·차단 경로에 실제 병원명 0건, 번들에 API 키 0건, GA4 수집 동작, 데모 이미지 생성 서버 경유 동작

운영 쪽 함께 바뀐 것 (코드 밖)

  • infinith-demo: Vercel 배포 보호 All Deployments, 환경변수 GEMINI_API_KEY·CREATOMATE_API_KEY(서버 전용), VITE_CREATOMATE_API_KEY 삭제
  • Supabase: GEMINI_API_KEY 새 키로 교체

🤖 Generated with Claude Code

## 요약 2026-10-07 webforai.kr 보도자료 공개에 맞춘 정리입니다. 이 브랜치는 webforai.kr(infinith-discovery)과 데모(infinith-demo) 프로덕션에 이미 배포돼 있습니다. main 이 프로덕션보다 뒤처져 있어, main 기준으로 다시 배포하면 아래 조치가 되돌아가므로 병합합니다. ## 변경 내용 ### 공개 사이트(webforai.kr) 정리 - 실제 병원 정보 비노출: 랜딩 샘플을 가상 A성형외과 데이터로 교체, 실제 진단 리포트·내부 화면 경로는 홈으로 이동, 실제 리포트 파일·병원 스크린샷을 빌드 결과에서 제외, Supabase 접속 정보를 번들에서 제거 - 진단 요청 버튼을 문의 서식(구글시트·메일 알림)으로 연결, 공개 폼에서 자동 빌드 큐로 가던 경로 차단 - 요금(Pricing)·동작하지 않던 링크(Product·Use Cases·mailto) 숨김/삭제, 문구 정리 - 개인정보처리방침·이용약관 페이지 추가 및 법무 검토 반영(국외 이전 기재사항, 법적 근거, AI 기본법 사전 고지 등), 검토 문서 `docs/legal/` - GTM·GA4 방문 측정 연결, 문의 접수 시 `generate_lead` 이벤트 ### 재발 방지 - 공개 기능 스위치 `src/lib/site.ts` (SHOW_PRICING·SHOW_SAMPLE_REPORT·SHOW_USE_CASES), 사용법 `docs/WEBFORAI_FEATURE_FLAGS.md` - 빌드 끝 번들 검사: 공개 배포에 실제 병원명·비밀 키·실제 파일이 있으면, 모든 배포에 서버 전용 키 값이 있으면 빌드 실패 (`plugins/vite-plugin-public-bundle-guard.ts`) ### API 키 서버 이전 - Gemini·Creatomate 호출을 Vercel 서버 함수(`api/gemini-image.js`, `api/creatomate-render.js`)로 이전, 키는 서버 환경변수에만 - `vite.config` define 의 키 주입 제거, API 대시보드의 `import.meta.env` 동적 조회 제거(VITE_ 변수 전체가 번들에 들어가던 원인) - Edge Function 스크린샷 분석 모델 `gemini-2.0-flash`(Google 서비스 종료로 404)를 `gemini-3.5-flash` 로 교체 (운영 collect-channel-data v24 로 배포됨) ### 문서 - RLS 익명 읽기 정리 SQL 초안 `docs/security/` (실행 안 함, 결정 필요) - GTM 가져오기 파일 `docs/analytics/` ## 검증 - `npm run lint`(tsc), webforai.kr·데모 빌드 통과, 번들 검사 통과 - 라이브 확인: webforai.kr 공개 페이지·차단 경로에 실제 병원명 0건, 번들에 API 키 0건, GA4 수집 동작, 데모 이미지 생성 서버 경유 동작 ## 운영 쪽 함께 바뀐 것 (코드 밖) - infinith-demo: Vercel 배포 보호 All Deployments, 환경변수 GEMINI_API_KEY·CREATOMATE_API_KEY(서버 전용), VITE_CREATOMATE_API_KEY 삭제 - Supabase: GEMINI_API_KEY 새 키로 교체 🤖 Generated with [Claude Code](https://claude.com/claude-code)
haewonkam added 22 commits 2026-10-07 06:50:28 +00:00
- "URL 입력으로 시작하기" → "AEO, GEO 진단 요청하기". 문의하기와 같은 ContactModal 을 열어
  구글시트 기록·메일 알림으로 받는다 (source: discovery_hero / discovery_cta)
- 공개 폼에서 supporter_builds 큐에 자동 빌드를 넣던 경로를 끊는다
- 히어로의 "샘플 리포트 보기" 버튼 제거 (실제 병원 리포트로 연결되던 링크)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 랜딩 샘플 리포트·AI 답변 예시·문의 서식 예시를 가상 A성형외과로 바꾼다 (discovery_sample, 고정 시드 무작위 판정)
- VITE_SITE=discovery 배포는 랜딩·요금·로그인·약관만 연다. 실제 병원 진단 결과와 내부 화면 경로는 홈으로 돌린다
- src/data·src/services 를 부수효과 없는 모듈로 표시해 쓰지 않는 실제 병원 목업이 공개 번들에서 빠지게 한다
- 공개 배포 번들에 GEMINI_API_KEY 를 넣지 않는다
- 헤더 Product·Use Cases 는 공개 배포에서 숨기고, 푸터에 개인정보처리방침·이용약관 페이지를 연결한다
- 기준표 설명의 실제 병원 예시 문구를 일반 예시로 바꾼다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- discovery 빌드에만 GTM(GTM-WQNTZVZH) 스니펫을 넣는다. GA4(G-013Z3BFY35)와 키 이벤트는 컨테이너 안에서 설정한다
- 문의 접수 성공 시 dataLayer 에 generate_lead(lead_source) 를 보낸다. 개인정보는 넣지 않는다
- GTM 가져오기 파일(docs/analytics/gtm_webforai_import.json): GA4 기본 태그, generate_lead·click_tel·click_email
- 개인정보처리방침 제1·5·8조에 Google 애널리틱스 분석 쿠키, 수집 항목, 국외 이전, 거부 방법을 반영한다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
public/ 은 infinith-demo 와 공용이라 reports/viewclinic(영문 진단 리포트 HTML·PDF)과
assets/clients/(병원 채널 스크린샷)가 공개 배포에도 올라가 주소만 알면 열렸다.
discovery 빌드의 writeBundle 에서 두 폴더를 지운다. infinith-demo 빌드는 그대로다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/supabase.ts 의 최상단 createClient() 가 부수효과로 남아, 쓰는 곳이 없는 공개 배포에도
Supabase URL·anon 키가 실렸다. 이 키로 marketing_reports 등 실제 병원 데이터 테이블을 읽을 수 있었다.
supabase 모듈을 부수효과 없는 모듈로 표시해 쓰지 않으면 번들에서 빠지게 한다. infinith-demo 빌드는 그대로 쓴다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
요금이 확정 전이라 공개 배포에서는 헤더 메뉴에서 빼고 /pricing 은 홈으로 돌린다.
페이지 코드가 번들에서도 빠진다. infinith-demo 배포는 그대로다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- src/lib/site.ts 의 SHOW_PRICING·SHOW_SAMPLE_REPORT·SHOW_USE_CASES 로 라우트·헤더·랜딩 버튼을 한 곳에서 켜고 끈다. 공개 배포 기본값은 모두 꺼짐
- 리포트 본문을 DiscoveryReportView 로 분리하고, 가상 데이터만 그리는 /discovery/sample 을 만든다
- 예시 리포트 경로는 병원 작업 공간 메뉴 대신 일반 헤더를 쓴다
- Use Cases 데이터(src/data/useCases.ts, 비어 있음)와 섹션을 두고, 사례가 있을 때만 섹션·메뉴가 보인다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
webforai.kr 빌드 결과에서 실제 병원명·도메인, Google·Supabase 키, reports/·assets/clients/ 파일을 찾으면
빌드를 멈춰 Vercel 배포가 진행되지 않게 한다. 목록은 plugins/public-bundle-denylist.json.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
브라우저가 키를 들고 외부 API 를 직접 부르던 구조를 api/gemini-image.js, api/creatomate-render.js 로 옮긴다.
브라우저는 채널·포맷·주제 선택값만 보내고, 서버가 허용 목록과 대조한 뒤 프롬프트·영상 구성을 만든다.
키는 서버 환경변수 GEMINI_API_KEY·CREATOMATE_API_KEY 에만 둔다. 출처는 infinith-demo·localhost 만 받는다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- vite.config define 의 GEMINI_API_KEY 를 지운다
- API 대시보드의 import.meta.env 동적 조회를 공개 변수 목록으로 바꾼다. 동적 조회 때문에 VITE_ 변수 전체(VITE_CREATOMATE_API_KEY 포함)가 번들에 들어갔다
- 모든 배포 빌드 끝에 서버 전용 키 값이 번들에 있으면 빌드를 실패시킨다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
미리보기는 Vercel 로그인 뒤에 있어 팀원만 연다. Referer 확인도 출처 단위로 비교한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 처리방침: 처리 목적별 법적 근거, 국외 이전 근거 조항·이전받는 자 연락처·거부 방법과 효과, 거래기록 보관 근거를 국세기본법으로
- 이용약관: AI 기본법 제31조 생성형 AI 사전 고지 조항 추가, 외부 서비스 면책을 회사 고의·과실 없는 경우로 한정
- 검토 문서 docs/legal/webforai_privacy_terms_review_2026-10-07.html

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gemini-2.0-flash 는 Google 이 내려 404 를 돌려주고 있었다(2026-10-07 확인). 분석이 조용히 빈 결과로 끝나던 상태다.
새 Gemini 키(서비스 계정 바인딩) 프로젝트에서도 호출되는 3.5-flash 로 바꾸고, 내부 추론 토큰을 감안해 출력 한도를 4096 으로 올린다.
운영 collect-channel-data v24 로 배포(운영 index.ts 는 로컬과 달라 운영 소스에 이 파일만 바꿔 배포), Supabase GEMINI_API_KEY 는 새 키로 교체.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
메일 앱이 없는 환경에서는 눌러도 아무 일이 없었다. 문의는 헤더·푸터의 문의하기(서식)로 받는다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
메일 앱이 없으면 동작하지 않고, 옆의 진단 요청 버튼이 같은 문의 서식을 연다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge conflict checking is in progress. Try again in few moments.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/webforai-feature-flags:feat/webforai-feature-flags
git checkout feat/webforai-feature-flags
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: castad/o2o-infinith-demo#1
No description provided.