o2o-infinith-demo/docs/NEXT_SESSION_2026-09-12_AI_DISCOVERY_PRODUCT.md
Haewon Kam 8f90bbb7cd docs·tools: 이미지 육안 검토 요청서 + 핸드오버 §5-3 (사람 게이트 근거·오라클 원인 확정)
build_image_review.mjs 를 검토 요청서로 다시 만들었다. 화면에 실제로 나가는 이미지를
먼저 보여주고(노란 테두리), 빼야 하는 유형을 무엇이 어떻게 생겼는지로 설명하며,
체크하면 excludeImages 에 넣을 목록이 만들어진다. 판단이 서지 않으면 빼는 쪽으로
보라고 적었다. 뷰 17장·원진 66장·오라클 0장, 그중 19장이 화면에 나간다.

핸드오버 §5-3 신설. 파일명·alt 검사로 91장 중 0장이 걸린 것을 근거로 이미지 육안 확인을
사람 게이트로 남긴다고 적었다. 규칙 문서 §4 의 IMAGE_RULE 계획은 이 유형에 효과가 없다.

오라클 원인 확정: 근거 수집일 2026-09-10 이 EUC-KR 디코딩 반영일 2026-09-11 보다
하루 빨라 옛 수집기가 alt 를 깨뜨렸다. 코드는 이미 고쳐져 있어 재수집이면 풀리지만
병원 사이트가 응답하지 않는다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 16:50:14 +09:00

30 KiB
Raw Blame History

세션 핸드오버 · 2026-09-12(토) · INFINITH AI Discovery Product 빌드

작성 2026-09-11 · 갱신 2026-09-12(토) · 작성자 Claude (haewon 세션) · 상태: §1 확인 완료, §4-1 완료 하위 문서: 서포터즈 사이트 빌드 절차 ~/orca/workspaces/INFINITH/Productize/docs/NEXT_SESSION_2026-09-12_PRODUCT_BUILD.md, 자동 빌드 상세 …/NEXT_SESSION_SUPPORTERS_AUTOBUILD_v3.md, 자동 채점 docs/AI_DISCOVERY_BUILD2_HANDOVER.md, 회고 docs/INFINITH_AI_Discovery_Retrospective_2026-09-08.md.

0. 세션 시작 시 붙여 넣을 프롬프트

INFINITH AI Discovery Product 빌드 세션. 제품은 "병원 URL 하나 → AI 답변 준비도 진단(AEO/GEO v2) → 서포터즈 사이트 자동 빌드(글·영상·뉴스룸·회복 일정 플래너·오시는 길) → 병원 확인·재빌드 → 측정(질문뱅크·감성·GA4·크롤러 로그)" 파이프라인이다.
코드 위치: 프런트·스크립트·문서는 메인 체크아웃 ~/Claude/Agentic Marketing/INFINITH (브랜치 feature/ai-sentiment-rubric, 프로덕션 main → infinith-demo.vercel.app),
워커·템플릿·큐는 워크트리 ~/orca/workspaces/INFINITH/Productize (브랜치 feature/supporters-autobuild), 랜딩 리드 CTA 는 브랜치 feature/discovery-url-cta(미머지).
먼저 docs/NEXT_SESSION_2026-09-12_AI_DISCOVERY_PRODUCT.md 를 읽는다(§8 인사이트 포함). 시작 절차: (1) 두 저장소 git status 와 .vercel 연결을 확인하고 다른 세션이 열려 있지 않은지 haewon 에게 묻는다 (2) §1 표의 "확인" 칸을 git log·Supabase 로 실제 확인한다 (3) §5 결정 대기의 답을 받는다 (4) §4 순서대로 진행하되 1번 브랜치 통합을 먼저 끝낸다. 한 세션은 한 저장소·한 배포 대상만 다룬다.
원칙: 근거 없는 사실은 생성하지 않는다("확인 대기"). 사람 게이트(의학 검토·게시 승인·이미지 육안·채널 확인·구조 기준선)는 자동화하지 않는다. 언급률·점수는 "스키마를 넣으면 인용된다"고 약속하지 않는다(정직성 규약).
고객 화면에 운영자 어휘 금지. 존댓말, 엠대시 금지(커밋 메시지 포함), 은유 금지, 흰 배경 위 연보라 텍스트 금지(인디고 #1D0024). INFINITH 리포트 PDF 는 PPTX 덱(infinith-deck 스킬)으로 만든 뒤 변환한다.
클라이언트 격리: INFINITH 문서·코드에 다른 서비스 이름을 쓰지 않는다. 산출 전 grep.

1. 제품 여정과 현재 상태

2026-09-12 확인 결과. 아래 표에서 "확인"으로 남겨 둔 두 항목은 이미 해결된 상태였다. 다음 세션은 이 전제로 시작한다.

항목 이전 기재 실제 근거
랜딩 리드 CTA 미머지 main 에 있음. feature/discovery-url-cta 는 main 대비 ahead 0 / behind 22 인 낡은 포인터라 머지 대상이 아니다 DiscoveryLeadModal.tsx·DiscoveryLandingPage.tsx·20260831_discovery_leads.sql 이 main 에 있고 blob 해시가 세 브랜치 동일
AEO/GEO v2 기준표 main 머지 여부 확인 필요 main 에 있음 aeoGeoRubricV2.ts·discoveryScoreV2.ts blob 해시 세 브랜치 동일
Supabase 마이그레이션 적용 상태 확인 필요 전부 적용됨. discovery_leads 0행, supporter_builds 2행, supporter_inputs 0행 REST 조회 HTTP 200
discovery_results (§4-3 대상) 없음(HTTP 404). §4-3 미착수 확정 REST 조회
launchd 폴러 설치됨 로드됨, 마지막 종료 코드 0 launchctl list
배포 3곳 4곳 모두 200.supporters-viewclinic/plan 은 404(2026-09-07 빌드라 플래너 이전 판) HTTP 확인
단계 고객이 보는 것 구현 위치 상태
1 진입 /discovery 랜딩, "URL 입력으로 시작" DiscoveryLandingPage.tsx, DiscoveryLeadModal → Supabase discovery_leads 메인, 브랜치 feature/discovery-url-cta 프리뷰만. 미머지, 마이그레이션 20260831_discovery_leads.sql 적용 여부 확인
2 진단 /discovery/:id 리포트 (AEO 100 + GEO 100, v2 기준표), 덱·PDF scripts/audit_aeo_geo.py(auto 22항목) → src/data/discovery_<id>.tsDiscoveryReportPage.tsx; scripts/build_discovery_report.ts → HTML/PDF; 덱 빌더 docs/reports/<clinic>/01_readiness_report/build_*_deck*.py 메인 + Productize(v2 기준표 src/data/aeoGeoRubricV2.ts, src/lib/discoveryScoreV2.ts) 반자동. 결과가 소스 파일 커밋 방식이라 병원마다 코드 배포가 필요하다. v2 기준표가 main(프로덕션)에 머지됐는지 확인
3 서포터즈 사이트 supporters-<clinic>.vercel.app 미리보기(noindex): 글·영상·뉴스룸·방문 안내(지도·길찾기)·회복 일정 플래너 /plan·/en/plan 워커 workers/supporters-build/run.mjs 15단계(evidence→…→tourism→recovery→planner→…→deploy), 템플릿 templates/supporters-astro, 게이트 scripts/gate/rules.mjs Productize 동작. 뷰(수작업 샘플 view-supporters-sample)·원진·오라클 3곳 배포. 병원당 약 $0.6, 30분
4 병원 확인 /supporters/:id 또는 리포트 안 ClinicInputsPanel: 채널 확인, 의료진, 검토·승인, 자유 답변 Supabase supporter_builds·supporter_inputs, apply_inputs.mjs, 재빌드 run.mjs --from data --from-supabase --build-id 메인(UI) + Productize(반영) 동작하되 재빌드 자동 트리거 없음(supporter_inputs insert → 큐 연결 필요)
5 운영 큐 → 빌드 → 미리보기 링크 poll.mjs + Mac launchd 5분 폴러, supporter_builds Productize 파일럿 수준. Mac 이 켜져 있어야 돈다. 실제 랜딩 신청 1건이 큐 → 완주까지 간 적 없음
6 측정 질문뱅크 언급률(2엔진), 감성, GA4 AI 유입, AI 크롤러 히트, 공식 vs 서포터즈 재채점 scripts/run_question_bank_openai.py·merge_qb_results.py·sentiment_qb.py·ga4_ai_traffic.py, data/ai_channels.json, 리포트 Integrity 절 "측정 가능 범위" 메인(QB·감성) + Productize(GA4) 스크립트 단위. 리포트 카드 자동 갱신 없음. GA4 는 GCP 계정 대기
7 계약·가격 상담 기반 계약 가격 문서 docs/INFINITH_가격정책_사업부보고서_v1.1.docx(2026-04, 이전 제품 INSIGHT/INTELLIGENCE 티어), AI Discovery 가격 제안은 docs/INFINITH_vs_FrostAI_비교_및_가격제안_2026-09-08.html 메인 AI Discovery 전용 티어 미확정

2026-09-10~11 추가: 회복 일정 플래너 /plan(설계 v0.2 §13, 관광공사 데이터 합침), 주변 안내 /stay(장소·축제·동선 지도·날씨, 플래너와 별개 페이지로 복원), 오시는 길 지도·길찾기, 전역 언어 전환·영어 홈(뷰), 모바일 헤더, 발행(색인) 단계. 전부 템플릿·워커에 통합됨.

2. 코드·브랜치·배포 지도

무엇 어디 브랜치 배포
제품 프런트(랜딩·리포트·확인 패널) 메인 src/ main(프로덕션), feature/ai-sentiment-rubric(감성·플래너 작업), feature/discovery-url-cta(리드 CTA) infinith-demo.vercel.app (main 에서 vercel --prod, Gitea 자동 트리거 없음)
채점·질문뱅크·감성·리포트 스크립트 메인 scripts/, docs/reports/ feature/ai-sentiment-rubric 로컬 실행
워커·템플릿·게이트·GA4 뼈대·v2 기준표 Productize workers/, supporters/, templates/, scripts/fetch_medical_tourism.py feature/supporters-autobuild 병원별 supporters-<clinic> (워커가 강제 link)
뷰 수작업 샘플 메인 supporters/ feature/ai-sentiment-rubric view-supporters-sample 수동
Supabase supabase/migrations/ (supporter_builds, supporter_builds_queue, discovery_leads) + Edge Functions(기존 리포트 파이프라인) 메인 적용 상태 확인 필요(CLI 토큰 만료 이력)
Productize .env(TOUR_API·NAVER·OPENAI·YOUTUBE), 메인 .env(진단·QB) 회사 계정. 세션 시작 때 grep -E "^KEY=." .env 로 값 존재만 확인

2026-09-12 갱신: feature/supporters-autobuild 와 feature/ai-sentiment-rubric 을 feature/product-1.0 으로 합쳤다. feature/discovery-url-cta 는 main 에 이미 담겨 있어 제외했다. 핸드오버가 적지 않은 네 번째 브랜치 Productize 가 있다. 고유 커밋 1개(랜딩 SSR 프리렌더·메타/JSON-LD·robots/sitemap/llms.txt)를 갖고 main 대비 74 뒤이며 origin 에 올라가 있다. 랜딩의 AI 크롤러 가독성이라 AEO 와 직접 닿는데, 합칠지 버릴지 아직 안 정했다.

(아래는 머지 전 상태 기록) 세 브랜치는 서로 머지되지 않았다. supporters/ 폴더가 양쪽에 있고 Base.astro 구현이 다르다(메인: i18n.ts 전역 전환·영어 홈; Productize: langswitch·영어 입구 /en/plan). 플래너·지도·헤더 CSS 는 같다.

3. 지금 되는 것 / 안 되는 것 (한 줄씩)

되는 것

  • 병원 이름·URL 로 채널 발견·근거 수집·자동 채점·리포트 HTML/PDF·덱(뷰·원진·오라클·태하 사례).
  • 워커 한 번으로 서포터즈 사이트 초안 발행(글 6~8편, 영상, 뉴스룸, 이미지 규칙, 지도, 플래너, 관광공사 데이터). 게이트 41건 테스트.
  • 병원 확인 패널 입력 → 수동 재빌드.
  • 질문뱅크 120문항 2엔진 실측, 감성 판정, Before/After 페이지(scripts/build_before_after.py).

안 되는 것

  • 랜딩 신청 → 큐 → 빌드 → 미리보기 링크 회신이 사람 손 없이 이어지지 않는다(리드 테이블과 큐가 분리, CTA 브랜치 미머지).
  • 진단 결과가 코드 파일(discovery_<id>.ts)이라 병원마다 프런트 배포가 필요하다. 런타임 데이터(Supabase 또는 JSON 스토리지)로 옮겨야 "URL 입력 → 리포트 링크"가 된다.
  • 측정 지표가 리포트 카드에 자동으로 들어가지 않는다(스크립트 산출물을 사람이 옮긴다).
  • 워커가 Mac 에 묶여 있다. 규칙표 잠정값·큐레이션 장소·의료진 후보·이미지·채널 12건은 사람 확인 대기.
  • 색인 작업의 사람 몫(네이버 등록·GSC 소유자·도메인·법무)이 체크리스트 파일로만 나오고, 담당자에게 알림·요청하는 UI 가 아직 없다(§4-9).
  • AI Discovery 가격·계약 조건 미확정. 랜딩 FAQ 의 해지·환불 항목 삭제 상태.

4. Product 빌드 순서 (권장)

  1. 브랜치 정리 완료 (2026-09-12, 브랜치 feature/product-1.0). feature/supporters-autobuild 는 main 의 상위집합이라 fast-forward 했고, feature/ai-sentiment-rubric 머지에서 충돌 8건이 났다. 겹친 22개 파일 중 실제로 다른 것은 9개뿐이었다. feature/discovery-url-cta 는 낡은 포인터라 제외했다.
    • 정본 결정(haewon): supporters/(뷰 수작업 샘플)를 정본으로 한다. 핸드오버 초안의 "템플릿을 정본으로" 와 반대 방향이다. templates/supporters-astro/npm run export:templatesupporters/ 에서 생성되는 파생물이므로 구조적으로 맞아떨어진다.
    • Productize 쪽에만 있던 GA4 태그와 영문 법적 고지 처리를 정본으로 이식했다.
  2. 리드 → 큐 연결: discovery_leads 마이그레이션 적용 → insert 시 supporter_builds 큐에 행 생성(DB 트리거 또는 폴러가 leads 도 읽기) → 워커가 evidence 부터 완주 → 미리보기 URL 을 supporter_builds.preview_url 에 기록 → 신청자에게 링크 회신(초기에는 수동 메일, o2oteam@o2o.kr).
  3. 진단 결과 런타임화: audit_aeo_geo.py 출력 JSON 을 Supabase(discovery_results) 또는 스토리지에 저장하고 /discovery/:id 가 런타임에 읽는다. 기존 DISCOVERY_RESULTS 레지스트리는 샘플(뷰) 전용으로 남긴다. 사람 판정(v2Results 4항목)은 확인 패널에서 입력.
  4. 재빌드 자동화: supporter_inputs insert → 큐 → run.mjs --from data --from-supabase. 색인 허용 빌드(PUBLIC_INDEXABLE=true)는 approvedAt 있는 글만 낸다는 규칙 유지.
  5. 측정 카드: 질문뱅크·감성·GA4·크롤러 히트 결과를 discovery_results 에 붙이고 리포트 Integrity 절과 Before/After 에 자동 표시. 언급률은 신뢰구간과 함께.
  6. 운영 이관: Mac launchd 폴러 → Trigger.dev(또는 동등)로. 키·비용 로그(status.json costUsd)·실패 알림.
  7. 가격·계약: AI Discovery 티어(진단만 / 진단+서포터즈 / +측정·관리) 확정, 랜딩 FAQ·계약서·해지 조건. FrostAI 비교 문서의 제안을 출발점으로.
  8. 다음 병원: 톡스앤필·차앤박(피부과), 레지스트리 73곳 중 회귀 병원. 한 화면 비교 산출물은 만들지 않는다.
  9. 발행(색인) 단계: "서포터즈 사이트 완료"의 정의는 배포가 아니라 색인 작업과 사람 체크리스트까지 끝난 상태다(haewon 결정 2026-09-11). 워커 publish 단계(supporters/scripts/publish_site.mjs)가 자동으로 하는 것: 라이브 확인(홈·robots·sitemap·noindex 헤더), IndexNow 로 사이트맵 URL 전부 알림(빙·네이버 공용, 색인 허용 빌드일 때만), Google Search Console 사이트맵 제출과 URL 색인 상태 조회(서비스 계정 GOOGLE_SERVICE_ACCOUNT_JSON 있을 때), 검색엔진 소유 확인 메타 태그(site.json googleSiteVerification·naverSiteVerification), IndexNow 키 파일(public/<key>.txt) 자동 생성, --indexable 로 noindex 헤더 제거·승인 글만 발행, --domain 으로 정식 도메인 연결. 사람에게 남기는 것(~/supporters-builds/<clinic>/publish-checklist.md, status.humanTasks): 네이버 서치어드바이저 등록·소유 확인·사이트맵/RSS 제출(공개 API 없음), Google Search Console 소유자 추가(첫 1회), 정식 도메인 결정, 색인 허용 전환 전 법무 3건·게시 승인, 병원 자산에서 백링크·sameAs, 네이버 블로그 재작성 트랙. 하지 않는 것: Google Indexing API(채용·라이브 방송 전용), 색인 보장 약속. 제품에서는 이 체크리스트를 확인 패널(ClinicInputsPanel) 또는 운영자 알림으로 사람에게 요청하게 만드는 것이 다음 일이다.

5. haewon 결정 대기

  1. Product 1.0 범위 결정 (2026-09-12, haewon): (b) 진단 + 서포터즈 사이트 초안. 랜딩 CTA 는 여기까지 약속한다. 측정·관리는 내부 참고로만 쓰고 약속하지 않는다. 남은 일은 §4-2 리드→큐 연결과 §4-3 진단 런타임화다.
  2. 가격 티어(§4-7)와 계약 최소 기간·해지 조건(2026-04 문서의 P0 두 항목이 그대로 미결).
  3. 뷰 샘플 통일 결정 (2026-09-12, haewon): 메인 supporters/ 가 정본. 템플릿은 npm run export:template 로 여기서 생성한다. 영어 홈 /en 은 템플릿에 추가했고 영문 사실이 없는 병원에서도 문장이 성립하도록 조각 단위로 조립한다(§5-2 판단 2). view-supporters-sample 배포 자리를 워커로 옮길지는 아직 안 정했다.
  4. 법무: 외국인환자 유치업 등록 여부(플래너·숙소 링크), 의료광고 사전심의 대상 여부, 지원 관계 고지 문구(sponsorNotice). 이 세 가지는 색인 허용 전환의 전제.
  5. 도메인: 별도 도메인 vs 병원 서브도메인(설계 v0.1 §3 2안). 서포터즈 실명 모집 방식.
  6. 워커 호스팅과 GCP 계정(GA4 서비스 계정).
  7. 규칙표 잠정값: 뷰·원진·오라클 procedures.json 의 provisional 값(출국 최소일·입원·실밥)을 병원 확인 뒤 공개할지, 공개 전까지 "병원 확인 전" 배지로 둘지.
  8. 서포터즈 빌드 하위 결정(하위 문서 §4)과 오라클 핸드오버 §3 미결은 그대로.

5-2. 2026-09-12 세션에서 내린 판단 (기록)

핸드오버에 없던 것을 작업 중에 발견해 판단한 두 가지다. 되돌리려면 아래 "되돌리는 법"대로 하면 된다.

판단 1. 영문 의료광고 고지를 병원 승인 없이 번역하지 않는다

  • 발견: 정본이 된 supporters/src/lib/i18n.ts 가 지원 관계 고지와 부작용 고지를 영문으로 번역해 푸터에 싣고 있었다. site.jsonsponsorNoticeEn 은 없었고, 어디에도 병원 승인 표시가 없었다. Productize 쪽 구현은 같은 자리에서 번역을 거부하고 한국어 원문에 확인 대기 표기를 붙이고 있었다.
  • 왜 문제인가: 지원 관계 고지와 부작용 고지는 의료법 56조와 추천보증 심사지침의 규율 대상이다. 문구를 임의로 번역하면 병원이 승인하지 않은 문장이 병원 이름으로 나간다. §5-4 법무가 미결이고 색인 허용의 전제로 적혀 있는 항목이다.
  • 한 것: Base.astrosite.jsonsponsorNoticeEn 과 factSheet 의 sideEffectNoticeEn 을 먼저 읽고, 없으면 한국어 원문을 싣고 "The English wording of these notices is pending clinic approval." 을 함께 낸다. i18n.ts 의 영문 foot_sponsor·foot_side 는 이 자리에 쓰지 않는다고 주석으로 표시했다.
  • 되돌리는 법: 병원이 영문 문구를 확정하면 site.jsonsponsorNoticeEn, factSheet 에 sideEffectNoticeEn 을 넣는다. 코드 수정은 필요 없고 확인 대기 표기가 자동으로 사라진다.

판단 2. 누락 탐지기를 고쳐 상호 밖의 고유 사실까지 잡는다

  • 발견: export_template.mjsCLINIC_RE 가 상호(뷰성형외과·viewclinic)만 찾아서 지명으로 적힌 사실을 놓쳤다. 빈 데이터로 템플릿을 빌드하니 영어 홈이 Founded 확인 대기 · Sinnonhyeon Station Exit 3 를 냈다. 또 이 검사는 빌드 도구의 기본 인자(--clinic viewclinic) 때문에 늘 실패해 신호가 되지 못했다.
  • 왜 문제인가: 템플릿은 모든 병원 사이트의 원본이다. 화면을 그리는 코드에 한 병원의 사실이 문장으로 박히면 다른 병원 화면에 틀린 사실이 나간다. 값이 비어 화면이 비는 것과 다르다.
  • 한 것: 지명·건물 표현(Sinnonhyeon·Bongeunsa·Gimpo·신논현·봉은사·19-storey·View Plastic)을 패턴에 넣었다. 그리고 심각도를 나눠, 문장을 그리는 코드(src/pages·layouts·components·lib)에 남으면 내보내기를 멈추고, 데이터(src/data)와 빌드 도구(scripts)는 알림만 한다. 데이터는 워커가 병원마다 갈아끼우고 빌드 도구는 고객이 보지 않기 때문이다.
  • 곁가지로 잡은 것: 같은 점검에서 영어 홈의 하드코딩 7곳(공항 경로·건물 층수·히어로 alt·영문 병원명·404 상호·히어로 칩·머리말 기본값 VIEW SUPPORTERS)과, 영문 사실이 없는 병원에서 문장이 is a at . 로 깨지는 문제를 함께 고쳤다. 게이트는 두 가지 모두 오류로 잡지 못한다.

여기서 배운 규칙

  • 템플릿에 넣기 전 빈 데이터로 빌드해 본다. 한 병원의 데이터로만 확인하면 하드코딩과 데이터 참조가 구별되지 않는다. 화면이 같아 보이기 때문이다.
  • 게이트가 통과해도 화면은 깨질 수 있다. 게이트는 의료광고 문구와 금칙어를 보지, 빈 값이 만든 비문을 보지 않는다. 배포 전 로컬 확인이 필요한 이유다.

5-3. 이미지 (2026-09-12) · 사람 게이트와 남은 일

자동 분류를 믿을 수 없다

뷰성형외과 수집 이미지 12장 중 6장이 의료광고 금지 유형인데 전부 시설(clinic)로 분류돼 있었다. 전후 사진(밑선 절개 흉터 1개월·6개월 경과), 시술 행위 사진(팔 주사·드레싱), 광고 모델 신체 사진 4장, 장비 제조사 성능 주장 그래픽, 가슴 라인 일러스트(랜딩 카드 썸네일로 노출)다.

파일명·alt 로는 한 장도 걸리지 않는다. 91장을 그 방식으로 검사해 0장이 걸렸다. 파일명이 img02 이고 alt 가 "가슴확대 시설 사진" 이면 어떤 규칙도 전후 사진임을 알 수 없다. 규칙 문서 §4 의 IMAGE_RULE(파일명·alt 검사) 계획은 이 유형에 효과가 없다.

이미지 육안 확인은 사람 게이트로 남긴다. scripts/build_image_review.mjs 가 검토 요청서를 만든다. 화면에 실제로 나가는 것을 먼저 보여주고, 체크하면 excludeImages 에 넣을 목록이 만들어진다. node scripts/build_image_review.mjs --out <파일.html> --site <id>=<siteDir>

대표 이미지 배정 (워커 heroes 단계)

PostCard 의 대체 순서가 건물 사진 하나로 수렴해 목록에 같은 사진이 나란히 섰다. scripts/assign_post_heroes.mjs 가 글 분류별로 어울리는 유형을 골라 글마다 다른 사진을 배정한다. 의료진 사진은 쓰지 않고(저자·검토자 표시가 지정 용도), 수집 alt 가 효과·결과를 주장하면 중립 문구로 바꾸며, 이미지가 모자라면 다시 쓰지 않고 비운다.

남은 일

항목 상태
원진 66장 육안 검토 요청 상태. 그중 15장이 화면에 나간다. 아직 아무도 보지 않았다
뷰 17장 12장 확인 완료(6장 제외). 의료진 13장은 검토자 표시 용도라 별도
오라클 이미지 0장. 근거 수집일 2026-09-10 이 EUC-KR 디코딩(2026-09-11 반영)보다 하루 빨라 images[].alt 가 전부 ???? 로 깨졌고 분류기가 한 장도 고르지 못한다. 코드는 이미 고쳐져 있으므로 --from evidence 재수집이면 풀린다. 다만 oracleclinic.com 이 응답하지 않는다(포트 80 연결 거부, 2026-09-12 기준). 그룹 사이트는 살아 있으나 Next.js 이미지 최적화 뒤에 있고 내용이 브랜드 배너·인증 마크라 대부분 제외 대상이다
뷰 이미지 부족 제외 후 쓸 수 있는 것이 4장이라 글 5편 중 2편이 건물 사진으로 떨어진다. 병원 제공 시설 사진이 필요하다

6. 함정 (제품 관점)

  • 한 Vercel 프로젝트에 두 폴더: 2026-09-11 Productize/supporters 와 메인 supporters 가 같은 프로젝트에 배포해 /plan 이 404 됐다. 지금은 Productize 쪽 연결을 껐다. 배포는 병원 폴더와 메인 supporters 에서만.
  • 페이지를 덮어쓰지 않는다: 플래너 통합 때 /stay(주변 안내)를 /plan 으로 리다이렉트해 세 사이트에서 주변 안내가 사라졌다(09-11 17시 복원). 새 기능이 기존 페이지와 '같은 주제'로 보여도 haewon 확인 전에는 기존 페이지를 지우거나 리다이렉트하지 않는다.
  • 세 브랜치 분산: 같은 파일(supporters/)이 두 브랜치에서 다르게 진화했다. 머지 전에 "템플릿이 정본"을 정하고 뷰 샘플을 옮긴다.
  • 진단 결과가 코드: discovery_<id>.ts 커밋 방식은 병원 수가 늘면 배포 병목이다(§4-3).
  • 게이트는 고객 화면 전체를 본다: 운영 어휘("실측"·"API 집계"·"임베드")가 데이터 값을 타고 화면에 나가면 빌드가 막힌다. 운영 기록은 데이터에만.
  • 원문 문장은 걸러야 한다: 병원 페이지 원문 32문장 중 14건이 홍보문·정형 고지였다. 워커 planner 단계 필터(CARE/NOT_CARE) 없이는 "병원 안내 기준" 배지가 의료광고 위반이 된다.
  • 헤드리스 크롬 모바일 캡처: 창 최소 폭 때문에 400px 직접 캡처가 틀린다. 1280 창 안 390px iframe 하네스로.
  • lint: 메인 체크아웃은 한때 tsc 가 없어 npm run lint 가 가짜 통과였다. 실제 0 에러인지 npx tsc --noEmit 로 본다.
  • 엠대시·타 서비스 이름: 커밋 메시지와 문서에서 두 번 잡혔다. 산출 전 엠대시 검색(grep -cP "\x{2014}")과 타 서비스명 격리 grep(전역 CLAUDE.md 의 목록).

7. 파일 참조

  • 진단: src/data/aeoGeoRubricV2.ts, src/lib/discoveryScoreV2.ts, src/pages/DiscoveryReportPage.tsx, scripts/audit_aeo_geo.py, docs/AEO_GEO_RUBRIC_v2.md
  • 랜딩·리드: src/pages/DiscoveryLandingPage.tsx, src/components/discovery/, supabase/migrations/20260831_discovery_leads.sql
  • 확인 패널·큐: src/components/discovery/ClinicInputsPanel.tsx, src/pages/SupportersBuildPage.tsx, supabase/migrations/20260907_supporter_builds*.sql
  • 워커·템플릿: Productize workers/supporters-build/, supporters/scripts/, templates/supporters-astro/, 브리프 supporters/briefs/<clinic>/
  • 플래너·지도: 템플릿 src/components/Planner.astro·VisitMap.astro, src/lib/plan.ts·tour.ts, supporters/scripts/build_planner_data.mjs, 설계 docs/INFINITH_Viewclinic_Supporters_Site_Design_v0.2.md §13
  • 측정: scripts/run_question_bank_openai.py, scripts/sentiment_qb.py, docs/AI_ANSWER_SENTIMENT_RUBRIC_v0.1.md, Productize scripts/ga4_ai_traffic.py, data/ai_channels.json
  • 가격·경쟁: docs/INFINITH_vs_FrostAI_비교_및_가격제안_2026-09-08.html, docs/INFINITH_가격정책_사업부보고서_v1.1.docx
  • PRD: docs/prd/INFINITH_AI-Discovery_PRD_20260828_v02.md, docs/prd/INFINITH_Global_Medical_Hub_PRD_v0.1.html(Productize 에 v0.2), docs/prd/INFINITH_Dermatology_Supporters_PRD_v0.1.html

8. 이번 이틀(09-10~11)의 인사이트 · 다음 개발에 그대로 적용할 것

  1. 한 세션 = 한 저장소 = 한 배포 대상. 두 세션이 같은 Vercel 프로젝트와 같은 supporters/ 폴더를 다른 브랜치에서 건드려 /plan 404 와 주변 안내 실종이 났다. 세션 시작 때 git status·.vercel/project.json·열린 세션 여부를 확인하고, 그 세션이 맡지 않은 자산은 손대지 않는다. 브랜치 통합(§4-1)이 이 문제의 근본 해결이므로 첫 일로 했다. 2026-09-12 완료.
    • 다만 통합 중에 같은 사고를 한 번 더 냈다. 머지 기준으로 삼은 브랜치 끝이 세션 도중 9개 커밋만큼 앞서 있었고(주변 안내 복원·워커 publish 단계), 그것을 모르고 올린 첫 머지가 둘을 떨어뜨렸다. 푸시 전에 발견해 되돌렸다.
    • 머지 직전에 브랜치 끝을 다시 읽는다. 세션 시작 때 읽은 git rev-parse/git log 값은 머지 시점에 낡아 있을 수 있다. 다른 워크트리가 열려 있으면 특히 그렇다. 머지 뒤에는 git rev-list --count main..<branch> 가 0 인지 확인한다.
  2. "완료"를 산출물이 아니라 고객 결과로 정의하면 자동·사람 경계가 드러난다. 서포터즈 사이트 완료 = 색인 작업 + 사람 체크리스트로 바꾸자 IndexNow·GSC 는 자동, 네이버 등록·소유자 추가는 사람으로 갈렸고 워커 단계가 그 경계를 코드로 가졌다. 진단(사람 판정 4항목), 병원 확인(재빌드 트리거)도 같은 방식으로 "완료 정의 → 자동 부분 → 사람 요청"을 명시한다.
  3. 병원 원문은 인용 전에 걸러야 한다. 원문 32문장 중 14건이 홍보문·정형 고지·표 조각이었다. 원문을 데이터로 쓰는 모든 경로(recoveryNotes, OCR, 뉴스 제목)에 화이트리스트 필터와 "제외된 문장 목록 눈으로 보기"를 둔다. 필터 없는 "병원 안내 기준" 배지는 의료광고 위반이다.
  4. 게이트는 데이터 값도 본다. 좌표 출처의 "실측"이 화면에 새어 나가 빌드가 막혔다. 데이터 필드마다 고객 노출 여부를 정하고 운영 기록(source·coordSource·note)은 렌더하지 않는다.
  5. 규칙표를 먼저 쓰면 코드·테스트가 따라온다. 설계 v0.2 §13 의 status(clinic/provisional)·출처 필수 규칙이 그대로 procedures.json 스키마와 게이트 테스트가 됐다. 새 기능은 데이터 규칙표부터 문서화한다.
  6. 관광공사 데이터는 공급이지 수요가 아니다. 선호는 화면에서 직접 묻고, 큐레이션이 1순위, 외부 데이터는 보강(2순위)이라는 우선순위를 점수로 코드화했다. 외부 API 를 붙일 때마다 같은 질문(공급인가 수요인가, 누가 1순위인가)을 먼저 한다.
  7. 디자인 규칙은 텍스트가 아니라 리듬이다. "흰 카드만 쌓인 페이지"는 홈·영상 페이지의 섹션 리듬(다크 히어로+글래스 통계 → 틴트 → 다크 → 라이트 → 틴트 → 다크)을 안 따라서 완성도가 낮아 보였다. 새 페이지는 기존 페이지 두 개의 구성을 먼저 분석하고 같은 리듬으로 짠다. 웜 그라디언트는 CTA 카드 한 장에만.
  8. 전역 CSS 와 컴포넌트 클래스는 접두어로 분리한다. .kpi 충돌로 그라디언트가 되살아났다. 컴포넌트 클래스는 plan-·vm- 처럼 접두어를 쓰고, 새 클래스는 전역 CSS 에 grep 한다.
  9. 모바일 검증은 하네스로. 헤드리스 크롬 창 최소 폭 때문에 400px 캡처가 틀렸고, 실제 문제(헤더 겹침)는 아이프레임 하네스에서만 보였다. 8페이지×3사이트 그리드 캡처를 배포 전 기본 절차로 둔다.
  10. 언어 전환은 전역 하나. 페이지별 토글은 사용자 관점에서 틀렸다. 영어 홈이 없는 사이트는 영어 입구(/en/plan)를 정해야 하고, 템플릿에 영어 홈을 넣을지는 §5-3 결정에 달렸다.
  11. 기존 페이지는 haewon 확인 전에 지우거나 리다이렉트하지 않는다. 새 기능이 기존 페이지와 같은 주제로 보여도 병존이 기본이다(주변 안내 /stay 와 회복 일정 /plan). 2026-09-12 재발. 브랜치 통합 머지가 /stay 를 떨어뜨렸다. 페이지를 지우려는 의도가 없어도 머지 기준을 잘못 잡으면 같은 결과가 난다. 통합 뒤 페이지 목록을 이전 배포와 대조한다.
  12. 제품 병목은 세 가지로 좁혀졌다. 진단 결과가 코드 파일, 리드→큐 미연결, 브랜치 3개 분산. 이 셋을 풀어야 "URL 입력 → 리포트 링크 → 서포터즈 미리보기"가 사람 손 없이 이어진다.