# 다음 세션 핸드오버 · 2026-09-12 · 서포터즈 Product Build (회복 일정 플래너·오시는 길 지도 통합 이후) 작성 2026-09-11 · 작성자 Claude (haewon 세션) · 이전 핸드오버 `docs/NEXT_SESSION_2026-09-11_ORACLE.md`(오라클 첫 빌드), `docs/NEXT_SESSION_SUPPORTERS_AUTOBUILD_v3.md`(자동 빌드 전체). 이 문서는 2026-09-10~11 이틀간 붙인 기능(회복 일정 플래너 `/plan`·`/en/plan`, 오시는 길 지도, 전역 언어 전환, 모바일 헤더)과 그것을 워커·템플릿에 통합한 상태, 그리고 다음 병원을 Product로 빌드하는 절차를 다룬다. ## 0. 세션 시작 시 붙여 넣을 프롬프트 ``` INFINITH 저장소. 자동 빌드(워커·템플릿)는 워크트리 ~/orca/workspaces/INFINITH/Productize (브랜치 feature/supporters-autobuild), 뷰성형외과 샘플 사이트(수동 배포)는 메인 체크아웃 ~/Claude/Agentic Marketing/INFINITH/supporters (브랜치 feature/ai-sentiment-rubric). 병원별 빌드 산출물은 ~/supporters-builds//site 이고 Vercel 프로젝트는 supporters- 이다. 먼저 docs/NEXT_SESSION_2026-09-12_PRODUCT_BUILD.md 를 읽고 §4 결정 대기의 답을 받은 뒤 §3 절차대로 진행한다. 원칙: 근거 없는 사실은 생성하지 않는다("확인 대기"·"병원 확인 전"). 사람 게이트(의학 검토·게시 승인·이미지 육안·채널 확인·구조 기준선 승인)는 자동화하지 않는다. 고객 화면에 운영자 설명 없음(게이트 OPERATOR_VOCAB). 확정 디자인은 텍스트만. 존댓말, 엠대시 금지(커밋 메시지 포함), 은유 금지, 흰 배경 위 연보라 텍스트 금지(인디고 #1D0024). 데이터 타일에 웜 그라디언트 금지(CTA 카드 한 장에만). 새 페이지는 홈·영상 페이지의 섹션 리듬(다크 히어로+글래스 통계 → 틴트 카드 → 다크 통계 → 라이트 → 틴트 → 다크)으로 만든다. 배포는 병원 폴더(~/supporters-builds//site)나 메인 supporters/ 에서만 한다. Productize/supporters 는 어떤 Vercel 프로젝트에도 연결하지 않는다. ``` ## 1. 2026-09-10~11 에 끝낸 것 | 일 | 위치 | 상태 | |---|---|---| | 회복 일정 플래너 `/plan`·`/en/plan` (수술일 기준 입국·출국 계산, 외출 등급·식사 단계 필터, 큐레이션+관광공사 추천, 체류 기간 행사, 숙소·항공 딥링크, ICS, 하단 요약 바) | 템플릿 `src/components/Planner.astro`, `src/lib/plan.ts`·`tour.ts`, `src/styles/plan.css`, `src/data/planStrings.json`, `src/pages/plan.astro`·`en/plan.astro`·`404.astro` | 뷰·원진·오라클 배포. 설계 근거 메인 `docs/INFINITH_Viewclinic_Supporters_Site_Design_v0.2.md` §13 | | 워커 `planner` 단계(recovery 다음) | `workers/supporters-build/run.mjs`, `supporters/scripts/build_planner_data.mjs`, 기본표 `supporters/scripts/template/planner/procedures.{plastic,derm}.json`·`places.base.json` | 업종별 기본 규칙표 + 병원 시술 페이지 원문(recoveryNotes) 중 관리 문장만 붙임(CARE/NOT_CARE 필터, 세부 시술명 접두). 장소는 `briefs//planner.places.json`(큐레이션) 또는 범용 기본표 | | 병원별 큐레이션 장소 브리프 | `supporters/briefs/{viewclinic,oracle,wonjin}/planner.places.json` | 뷰 31·오라클 28·원진 31곳. 전부 verify(출시 전 확인) | | 오시는 길 지도·길찾기 (Leaflet+OSM, 주소 복사, 네이버·카카오 길찾기, 영어는 구글 추가) | 템플릿 `src/components/VisitMap.astro`, 방문 안내 §3, 뷰 영어 홈 Getting Here | 좌표 `factSheet.geo`. 워커 tourism 단계가 관광공사 수집 기준 좌표(네이버 지역검색)를 geo 에 기록 | | 전역 언어 전환·모바일 헤더 | 템플릿 Base.astro(langswitch, T.nav), `global.css` ≤900px 헤더 규칙 | 로고·메뉴 겹침 해결. 390px 하네스로 8페이지×3사이트 검증 | | 옛 주소 정리 | `vercel.json` redirects `/recovery`·`/stay`·`/en/recovery`·`/en/stay` → `/plan`·`/en/plan`. `recovery.astro`·`stay.astro` 는 템플릿에서 제거 | haewon 결정 2026-09-11: 메인 폴더의 `/plan` 이 정본 | | 원진 관광공사 수집·원문 수집 | `~/supporters-builds/wonjin/site/src/data/medicalTourism*.json`, `recoveryNotes.json` | 장소 123·축제 24, 원문 32문장 중 관리 문장 16건 붙임 | | Vercel 사고 재발 방지 | Productize `supporters/.vercel/project.json` → `.disabled-2026-09-11`, `supporters/DEPLOY_NOTE.md` | 두 폴더가 같은 프로젝트에 배포해 `/plan` 이 404 된 사고(09-11 10:20) 이후 | 커밋: Productize `aa5b052`(플래너 통합) → `ed8f650`(지도) → `5263593`(모바일 헤더) → `008411b`(관리 문장 필터). 메인 `65fb9be`~`93509bf`. ## 2. 격리 구조 (무엇이 무엇을 건드리는가) | 폴더 | 브랜치 | 역할 | Vercel | 워커가 건드리나 | |---|---|---|---|---| | `~/Claude/Agentic Marketing/INFINITH/supporters` | feature/ai-sentiment-rubric | 뷰성형외과 샘플(정본 `/plan`) | `view-supporters-sample` (수동 `vercel --prod`) | 아니오. 워커는 이 경로를 모른다 | | `Productize/supporters` | feature/supporters-autobuild | 템플릿 원본(개발용). `npm run export:template` 으로 `templates/supporters-astro` 생성 | 없음(연결 파일 비활성) | 아니오. 워커는 여기서 스크립트만 실행한다 | | `Productize/templates/supporters-astro` | 〃 | 워커가 복사하는 템플릿 | 없음 | 읽기만 | | `~/supporters-builds//site` | (저장소 밖) | 병원별 산출물 | `supporters-` (워커가 `vercel link --project` 로 강제 연결) | **예.** `data` 단계가 `site/` 를 지우고 템플릿을 다시 복사한다(글·videos.json 만 보존) | 따라서: 워커를 어떤 병원으로 돌려도 뷰 샘플과 다른 병원 프로젝트는 영향이 없다. 단, 같은 병원을 `--from data` 이전 단계부터 다시 돌리면 그 병원 폴더의 **손수 고친 파일은 사라진다**. 이번에 손수 넣은 것은 전부 템플릿·브리프·워커 단계로 옮겨 두었으므로 재빌드 결과가 지금 라이브와 같아야 한다. 예외 두 가지는 §5. ## 3. Product build 절차 (다음 병원) 1. **키 확인**: `Productize/.env` 에 `TOUR_API_KEY`, `NAVER_CLIENT_ID/SECRET`, `OPENAI_API_KEY`(원문 번역), `YOUTUBE_API_KEY` 값이 있는지. `grep -E "^(TOUR_API_KEY|NAVER_CLIENT_ID)=." .env`. 2. **브리프 작성** `supporters/briefs//` - `clinic.json`: 유튜브 채널 고정, 로고, `factSheet.kind`(피부과면 `"피부과"`, 이 값으로 업종 자동 판별) · `industry`(`derm`|`plastic`, 명시하면 우선), 갤러리·제외 이미지. 예시는 `briefs/oracle/clinic.json`. - `planner.places.json`(선택): 병원 기준 큐레이션 장소. 없으면 범용 기본표(약국·편의점·죽·스무디·탕류·경과 확인·호텔 라운지)에 병원 이름·지역만 치환된다. 예시는 `briefs/wonjin/planner.places.json`(뷰 목록을 기준점만 바꿔 거리 보정). 3. **워커 실행** (Productize 루트) ``` node workers/supporters-build/run.mjs --clinic --url https://<병원 홈페이지> --name "<상호>" [--industry derm] [--deploy] ``` 단계 순서: evidence → ocr → data → discover → youtube → news → images → tourism → recovery → **planner** → inputs → briefs → generate → build → deploy. 부분 재실행은 `--from <단계>`. 생성 비용 약 $0.6/병원(글 6~8편). 4. **확인**: `~/supporters-builds//status.json` 의 `report.tourism`(좌표·장소 수)·`report.planner`(붙은 원문 문장 수)·`report.recovery`. 빌드 게이트 오류 0 인지. 5. **사람 게이트**: 의료진 후보 확정, 이미지 육안 확인, 구조 기준선 승인(`node scripts/check.mjs --update-layout`, 첫 빌드는 LAYOUT_NO_BASELINE 경고), 규칙표 provisional 값 원장 확인. 6. **모바일 검증**: 헤드리스 크롬은 창 최소 폭이 약 500px 이라 400px 직접 캡처가 부정확하다. 1280 창 안에 390px iframe 을 넣은 하네스로 찍는다(스크래치 `harness*.html` 방식, 홈·영상·방문·plan·뉴스룸·목록·글·병원 정보 8페이지). 7. **배포**: `--deploy` 또는 병원 폴더에서 `vercel --prod --yes`. 메인 `supporters/`(뷰 샘플)는 별도로 `git push` 후 `vercel --prod`. 기존 병원 재빌드(플래너·지도 포함 최신 템플릿 적용): `--from data` 로 돌리면 글·영상 집계는 보존되고 나머지는 새로 만든다. 원진처럼 원문 수집을 워커 밖에서 돌린 병원도 `recovery` 단계가 같은 결과를 낸다(`recoveryNotes.cache.json` 은 병원 폴더에 남아 번역 재사용). ## 4. haewon 결정 대기 1. **규칙표 provisional 값**(출국 가능 최소일·입원·실밥 등) 원장 확인. 뷰 `procedures.json` 의 clinic 값은 뷰 주의사항 페이지 근거, 나머지 병원은 원문 문장만 clinic. 화면에는 "병원 확인 전" 배지가 붙어 있으나 공개 전 확인 필요. 2. **제휴 계정 주체**(부킹닷컴 aid, 항공): INFINITH vs 병원. 지금은 제휴 ID 없이 검색 링크만. 3. **외국인환자 유치업 등록 여부 법무 확인**: 플래너는 정보 안내로 유지 중(예약·결제 없음). 4. **뷰 샘플을 템플릿에서 다시 뽑아 통일할지**: 메인 `supporters/` Base.astro 는 템플릿과 구현이 다르다(메인: i18n.ts 전역 전환, 영어 홈 `/en`; 템플릿: langswitch, 영어 입구 `/en/plan`). 플래너·지도 코드는 동일. 통일하면 뷰도 워커 폴더에서 관리하고 `view-supporters-sample` 은 수동 배포에서 워커 배포로 바뀐다. 5. **다음 병원**: 톡스앤필·차앤박(피부과 Top3 나머지)을 같은 워커로 빌드할지. 세 병원을 한 화면에서 비교하는 산출물은 만들지 않는다. 6. **P1 남은 것**: 일본어·중국어 화면(planStrings 같은 키로 추가), 국적별 기본 칩(관광 데이터랩), 관광공사 재수집 주기. 7. 기존 미결(오라클 핸드오버 §3): 세일즈 사용 범위, sponsorNotice 문구, 주변 안내 사진 폴백, 의료진 OCR 노출, 도메인·서포터즈 실명·워커 상시 실행. ## 5. 함정 (이번 이틀) - **같은 Vercel 프로젝트에 두 폴더**: Productize/supporters 와 메인 supporters 가 둘 다 `view-supporters-sample` 에 연결돼 있어 서로 덮어썼다. 지금은 Productize 쪽 연결을 껐다. 워커 외 수동 `vercel link` 는 하지 않는다. - **재빌드 시 사라지는 손수 편집**: 원진 폴더의 `factSheetEn.json`, `lib/i18n.ts`, 메인식 Base.astro 는 인스턴스 전용이다. 재빌드하면 템플릿 Base(langswitch)로 바뀌며 이것이 의도한 상태다. 오라클 폴더의 `scripts/gate/plan.test.mjs` 는 오라클 전용(id 8종 기준)이라 재빌드 후 템플릿 범용 테스트로 바뀐다. - **전역 CSS 클래스 충돌**: 플래너 통계에 `kpi` 클래스를 쓰면 전역 `.kpi`(웜 그라디언트)가 덮어쓴다. `.stats.dates` 로 바꿨다. 새 클래스는 전역 CSS 와 이름이 겹치지 않는지 grep 한다. - **게이트 OPERATOR_VOCAB**: 좌표 출처 문구의 "실측"이 고객 화면에 나가 빌드가 막혔다. 운영 기록(source)은 데이터에만 둔다. - **관리 문장 필터가 필요한 이유**: 원진 원문 32문장 중 14건이 홍보문·정형 합병증 고지·표 조각이었다. 필터(`build_planner_data.mjs` CARE/NOT_CARE) 없이 "병원 안내 기준" 배지를 달면 의료광고 규정에 걸린다. 새 병원에서 제외된 문장 목록을 한 번 눈으로 본다(`status.report.planner`). - **zsh 에서 `set -- $var` 는 단어 분리를 안 한다**: 하네스 생성처럼 반복이 필요하면 파이썬으로 쓴다. - **엠대시**: 커밋 제목에 두 번 들어가 amend 했다. 커밋 메시지도 생성물이다. - **Nominatim 좌표는 임시**: 원진 첫 좌표는 OSM 주소 검색이었고, 관광공사 수집(네이버 지역검색)으로 바뀌었다. 좌표 출처는 `factSheet.geo.source` 에 남는다. ## 6. 관련 파일 빠른 참조 - 워커: `workers/supporters-build/run.mjs` (phase 'planner' 307행 부근), 폴러 `poll.mjs`, launchd - 플래너 데이터 생성: `supporters/scripts/build_planner_data.mjs` - 기본표: `supporters/scripts/template/planner/` - 관광 수집: `scripts/fetch_medical_tourism.py` (병원 좌표도 여기서 나온다) - 원문 수집: `supporters/scripts/collect_recovery.mjs` - 테스트: `supporters/scripts/gate/plan.test.mjs`(빈 관광 데이터면 관광 검사 건너뜀), `npm run gate:test`(41건) - 설계 문서(메인): `docs/INFINITH_Viewclinic_Supporters_Site_Design_v0.2.md` §13, HTML판 `docs/prd/…_v0.2.html` - 비교 이미지(메인): `docs/reports/viewclinic/04_supporters/planner/Recovery_Planner_Before_After_2026-09-10.png`