언어 스위치의 KO 가 /visit 으로 가고 있었다. 같은 내용의 한국어판이 아니라 짝이
아니었다. /stay 를 만들어 /stay ↔ /en/stay 로 잇는다.
수집 (scripts/fetch_medical_tourism.py --lang ko)
- 국문은 ContentTypeId 가 다르다(관광지 12·문화시설 14·숙박 32·쇼핑 38·음식점 39).
다국어 코드로 부르면 엉뚱한 것이 온다.
- 국문 서비스는 KorService2 로 붙고, 국문 사진 폴백은 건너뛴다(국문이 원본이다).
- 출력은 medicalTourismKo.json.
국문이 훨씬 두껍다
전체 123곳(영문 101) · 도보 5분 이내 13곳(영문 2) · 걸어갈 수 있는 곳 66곳(영문 25)
설명문 146/147 · 사진 147/147
국문 관광지에는 의료관광 등록업소가 섞이지 않아 A02020500 필터가 걸리지 않는다.
영문에서 반경 5km 100건 중 92건이 병원·에이전시였던 것과 대비된다.
화면 (supporters/src/pages/stay.astro)
/en/stay 와 같은 구조에 한국어 문구를 넣었다. 이동 시간 라벨은 데이터에 영문으로
들어 있어 화면에서 만든다(도보 N분 / 차로 N분). 날씨 상태도 한국어로 옮겼고,
검색 링크는 네이버로 보낸다. 식이·회복 안내는 site.json 의 dietGuideKo /
recoveryStagesKo 를 쓰며, 없으면 병원 확인 대기로 둔다.
라우팅
- Base.astro PAIRS 에 '/stay': '/en/stay' 등록. 스위치가 서로를 가리킨다.
- 한국어 네비게이션에 "주변 안내" 추가. 스위치는 EN/KO 만 오가므로 다른 페이지에서
/stay 로 갈 길이 없었다. 이 항목 추가로 LAYOUT_CHANGED 경고 2건이 남아 있으며
haewon 승인 전까지 기준선을 갱신하지 않는다.
- 사이트맵에 /stay 추가.
템플릿은 같은 코드에 빈 데이터 스캐폴드를 둔다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
/en/stay 로 가는 길을 만들려고 Base.astro 에 언어 스위치를 넣으면서 한국어 페이지
헤더 구조가 바뀌었고, 게이트가 LAYOUT_CHANGED 로 잡고 있었다. haewon 승인 후
--update-layout 으로 기준을 갱신했다.
/index.html 266 → 269 · /posts/anesthesia-choice.html 223 → 226 · /posts.html 250 → 252
셋 다 늘어난 것은 div.langswitch 와 그 안의 KO/EN 링크다.
경고 26건 → 23건. 남은 것은 이전부터 있던 DISCLOSURE_TOP_MISSING 18건과
NUMERIC_NO_QUALIFIER 5건이다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
haewon 이 준 참고 사이트(스테이,머뭄)의 연동 범위에 맞춰 다시 만들었다. 앞서 만든 것은
거리순 표였고, 실제로 필요한 것은 설명문과 이동 시간이 붙은 카드, 계절로 묶은 축제,
시간표가 있는 동선이었다.
수집 (scripts/fetch_medical_tourism.py)
- detailCommon2 의 overview 를 가져온다. locationBasedList2 는 설명문을 주지 않아
카드에 이름과 주소만 남았다. 123/125 건 확보.
- 이동 시간을 낸다. 참고 사이트 표기를 역산해 도보는 max(1, round(m/80)), 차는
직선거리 km x 1.2 로 맞췄다(135m→2분, 566m→7분, 25km→30분). 2km 까지 도보로 보고,
짧은 거리의 차 시간은 주차·신호 때문에 의미가 없어 최소 5분으로 둔다.
- 축제를 계절로 분류하고, 도보 시간 구간별 건수를 누적으로 집계한다.
사진 (125/125, 전부 실제로 열리는 것 확인)
목록 API 의 firstimage 만 쓰면 38건이 비었다. 폴백을 넷으로 걸었다.
1) detailImage2 — 이미지 전용 오퍼레이션. 15건 회수(도산공원 7장이 여기 있었다)
2) 국문 서비스 KorService2 — 영문 항목에 없어도 국문 항목에 있다. 10건
3) 업체 공식 홈페이지 og:image — 2건
4) Naver 이미지 검색 API — 11건
og:image 는 실제로 열어 보고 쓴다. 이미지가 아니거나 인스타 CDN 처럼 핫링크를
403 으로 막으면 화면에서 빈 칸이 되기 때문이다.
imageSource 를 항목마다 남겼다. naver 출처는 제3자 저작물이므로 내부 시연 범위이며,
공개 배포 전에는 걷어내거나 라이선스 있는 사진으로 교체해야 한다(haewon 판단).
화면 (supporters/src/pages/en/stay.astro)
- Around the clinic: 도보 시간 누적 필터, 범주별 카드, 사진 위 이동시간 배지, 설명문,
공식 홈페이지가 있으면 링크하고 없으면 검색으로 보낸다.
- Festivals: 계절 탭.
- Shaping your days: 좌표로 그린 인라인 SVG 지도와 시간표. 외부 지도 라이브러리를
부르지 않는다. 시각은 가정이며 화면에 그렇게 적었다.
- 오늘 날씨: Open-Meteo, 키 불필요. 빌드가 아니라 브라우저에서 받는다. 정적 빌드에
넣으면 배포 시각의 날씨가 굳는다. 못 받으면 블록을 통째로 숨긴다.
문구는 이 페이지의 목록에만 연결한다. 무엇을 해도 되는지는 의학 판단이라 말하지 않는다.
- 섹션 점프 바(글래스, 스티키) + IntersectionObserver 스크롤 스파이.
고친 것
- 항목마다 붙던 KO 태그를 헤더 언어 스위치 하나로 바꿨다. 짝이 있는 페이지는 서로 잇고
없으면 그 언어의 입구로 보낸다. 영문 페이지가 늘면 PAIRS 표에 줄만 추가한다.
- .chip 클래스가 이미 있어 홈·뉴스룸·영상 페이지를 덮어쓰고 있었다. 새 스타일을
.stay 아래로 모두 가뒀다.
- factSheet 에 영문 주소(fullEn)와 우편번호를 넣었다. 근거는 뷰성형외과 자신의
한국관광공사 등재 항목(contentid 3364779)이며 fullEnSource 에 적었다.
템플릿은 같은 코드에 빈 데이터 스캐폴드를 둔다. 뷰성형외과 데이터가 새 병원 빌드로
새면 안 된다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
붙일 자리를 잘못 잡았다. /discovery 는 INFINITH 제품의 진단 화면이고 병원마다 쓰는
범용 도구다. 외국인 환자가 보는 페이지는 병원 서포터즈 사이트다. 그쪽으로 옮겼다.
옮긴 것
- src/components/discovery/MedicalTourismPanel.tsx, src/types/medicalTourism.ts,
src/data/medicalTourism.json 삭제. DiscoveryReportPage 원복.
- supporters/src/pages/en/stay.astro 신설. 독립 URL 과 자체 WebPage JSON-LD 를 가져
AI 인용 단위가 된다. sitemap 에 등록하고 /visit 에서 hreflang 링크로 잇는다.
- 수집 스크립트 출력을 supporters/src/data/medicalTourism.json 으로 바꿨다.
영문 페이지 지원
- Base.astro 에 lang prop 추가(기본 ko). html lang · og:locale · 머리말 · 꼬리말이
따라 바뀐다. 레이아웃을 하나로 유지해 한국어 페이지 동작은 그대로다.
- 의료광고 고지(지원 관계·부작용)는 규정 대상이라 임의로 번역하지 않는다. 병원이
sponsorNoticeEn / sideEffectNoticeEn 을 확정하기 전에는 한국어 원문을 그대로 싣고
영문 문구가 확인 대기임을 밝힌다.
- factSheet 에 nameEn / shortNameEn / shortNameEnSource 추가. 뷰성형외과 값의 근거는
병원 자신의 영문 도메인 viewplasticsurgery.com 이며 한국관광공사 등재명도 같다.
페이지가 만들지 않는 것
- 평점·리뷰·영업시간: TourAPI 미제공이라 싣지 않는다.
- 식당의 회복 적합성: 의학 판단이라 병원이 확정한 영문 문구(site.json dietGuideEn)만
싣는다. 확인 전에는 어떤 식당도 적합으로 표시하지 않는다고 페이지에 적는다.
- 회복 단계 일수: 병원 확정값(recoveryStagesEn). 단계는 이동 거리로만 정의한다.
- 하단에 이 페이지가 답하지 못하는 것 네 가지를 그대로 적었다.
템플릿 동기화
- templates/supporters-astro 에 같은 변경을 넣되 데이터는 빈 스캐폴드로 둔다.
뷰성형외과 factSheet 와 관광 데이터가 새 병원 빌드에 새어 들어가면 안 된다.
빈 데이터로 빌드해 6개 범주가 "No English listings" 로 나오는 것까지 확인했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
/discovery/:id 에 외국인 환자용 주변 정보를 붙였다. 숙박·음식점·웰니스·관광·문화·
쇼핑·축제 125건과 이동 반경 기준 회복 동선. 다음 뷰성형외과 미팅용 프로토타입이다.
데이터 (scripts/fetch_medical_tourism.py → src/data/medicalTourism.json)
한국관광공사 TourAPI 영문(EngService2) 사전 수집. 실시간 호출이 아닌 이유는 영문
커버리지가 얇아 필터링이 많이 필요하고, 시연 중 외부 API 상태에 화면이 종속되지
않게 하기 위해서다. 좌표는 Naver 지역검색 실측(뷰성형외과의원, 봉은사로 107).
실측으로 드러난 것과 대응
- 영문 관광지(76)의 대부분이 관광지가 아니다. 반경 5km 100건 중 92건이 분류코드
A02020500 "Medical Tourism Sites"(categoryCode2 로 확인)이며 병원과 유치
에이전시다. 제목 키워드로는 "하이안과", "닥파인더코리아" 를 놓쳐 코드로 걸렀다.
거리순 상위 100건이 거의 다 여기라 페이징을 넣어야 실제 관광지가 나온다.
- 스파·찜질방(A02020300/400)은 회복 여정에 맞아 wellness 로 분리했다.
- 영문 축제는 areacode 필드가 비어 있어 areaCode 필터가 0건을 반환한다. 좌표
거리로 걸렀다.
- TourAPI 이미지 URL 이 http 라 https 사이트에서 혼합 콘텐츠로 차단된다. 수집
단계에서 https 로 올린다.
- 반경을 목적별로 나눴다. 회복기에 자주 가는 숙박·식사는 5km, 관광은 10km.
만들지 않은 것
- 평점·리뷰·영업시간: TourAPI 미제공이라 null 로 두고 화면에 "미연동" 으로 적었다.
Google Places 키가 아직 비어 있다(신청 중).
- 수술 전후 식이 적합성: 의학 판단이라 병원 입력만 쓴다. ClinicInputsPanel 에
diet_guide 항목을 더해 supporter_inputs 로 받고, 입력 전에는 "병원 확인 대기"
로 둔다. 개별 식당의 적합 여부를 추론하지 않는다.
- 회복 단계가 며칠째인지: 병원 입력(recovery). 화면의 단계는 이동 반경으로만
정의해 의학적 함의를 담지 않는다.
- 한계 4가지를 meta.limits 에 담아 섹션 하단 "측정 가능 범위" 에 그대로 띄운다.
FilledIcons 에 Bed·Fork·Spa·MapPin·Ticket·Bag·Theater 7종 추가(라인 아이콘·이모지
금지 규칙에 따라 채움 SVG).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
§2 각 항목에 진행 상태를 붙이고 결과 요약표를 넣었다. §4 함정에 세 줄을 더했다
(--calibration 버그 수정, 재판정 시 --out 처리, 언급 탐지를 LLM 에 맡기지 않는다).
§5 에 monthly_ai_measure.py 명령을 넣었다. §3-1 을 오늘 결과로 다시 썼다.
두 체크아웃 모두 푸시하지 않았고, 메인 체크아웃은 feature/ai-sentiment-rubric
브랜치에 있다. 문서에 적어 두었다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 haewon 전달. 뷰성형외과 원장이 다른 병원 네트워크·파트너십이 많아
병원을 유치할 수 있다고 밝혔다. 명단·수·관계 단계가 확인되지 않았으므로 사실이
아니라 확인 대상으로 적었다.
- §04: "앵커의 병원 소개 역량이 큰 경우" 카드. 구조 판단(IP 귀속·중립성)은
소개 규모와 무관하며 바뀌는 것은 소개 목표 수치와 그 대가라고 정리했다.
앵커 계약 조항 5개(소개 목표 수치화, 성과 연동 대가, 소개 병원의 AIO2O
직접 계약, 노출 우대 배제, 앵커 이탈 시 병원 계약 존속)와 확인 질문 4개
- §05: 의료법 27조 3항(영리 목적 환자 소개·알선·유인 금지) 확인 행. 병원 간
상호 소개 관계를 허브로 옮길 때의 적용 여부는 변호사 확인 항목이다
- §08: 1단계 온보딩을 "최소 2~4곳, 앵커 소개 명단 확인 후 재산정" 으로.
CEO 결정 (1)에 소개 목표·성과 연동·직접 계약 원칙·노출 우대 배제 추가
- §10: 앵커 의존 리스크(공급이 개인 관계에 붙는다), 미결 2건 추가
v0.1 은 그대로 두었다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 작업분. GA4 에서 AI 답변엔진 유입을 채널로 갈라 보는 뼈대를 세웠다.
- data/ai_channels.json: AI 답변엔진 리퍼러 목록(채널 그룹 정의의 근거)
- scripts/ga4_ai_traffic.py: GA4 Data API 로 AI 유입을 뽑는 러너. --mock 으로 합성
데이터 검증까지 마쳤다. 실제 속성 연결은 GCP 계정이 정해진 뒤다
- supporters/src/layouts/Base.astro + 템플릿 site.json 2곳: ga4MeasurementId 태그.
쿠키 고지 배너 결정 전까지 미리보기에는 ID 를 넣지 않는다
- scripts/build_discovery_report.ts: Integrity 절에 "측정 가능 범위" 를 넣어
무엇을 재고 무엇을 못 재는지 리포트가 스스로 밝히게 했다
- 원진 진단 리포트 v2.1(HTML·PDF) 재생성분
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- scripts/generate_posts.mjs + gen/{evidence,prompt,serialize}.mjs, briefs/README.md, 새 문항 brief 예시
- 게이트 COMPARISON_CLAIM(타 병원·업계 평균 비교 수치) 신설 + 픽스처, 금칙어 부정문 예외, 직렬화 왕복 테스트
- 회귀 리포트·샘플 3편 docs/reports/viewclinic/04_supporters, v2 §11-5 기록
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- 홈+page 사이트맵에서 원문 페이지 발견 → 경로 우선·단어 경계 분류(주의사항·애프터케어·검진·안전·의료진·오시는길·시설·소개·예약·시술)
- 본문 컨테이너 선택 + 페이지 간 반복 줄(메뉴·푸터) 제거, 헤딩·문단·목록·표·이미지·링크 구조화
- doctors.json: 이름·직함·약력. 약력이 이미지 글자면 textInImages, 2줄 미만이면 '확인 대기' (뷰성형외과 27명 전원 확인 대기)
- facts.draft.json: 전화·주소·사업자번호·대표·진료시간 정규식 후보 + 출처 URL
- home_text.txt: 전 페이지 본문(29만 자). check.mjs --home-text= 로 40자 중복 검사 기준 교체 가능 → 18편 0오류
- --posts 옵션: 글에 인용된 병원 URL 커버리지 리포트 (뷰성형외과 16/16, /face/main/은 301 추적)
- robots.txt Disallow 존중, UA 명시, 요청 간 400ms
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- src/data/site.json 신설(매체 이름·로고·홈 큐레이션), factSheet에 kind·areaLabel·transitShort·transitNote·reservationUrl·doctorsUrl·youtube.title 추가
- lib.ts: PENDING('확인 대기')·v()·has()·surface()·editor() 도입, 스키마는 빈 값을 빼고 생성
- 페이지·컴포넌트 15개에서 뷰성형외과 하드코딩 제거, 빈 데이터 empty-state (글 0편·영상 0건·뉴스 0건·이미지 없음)
- 검증: 28페이지 표시 텍스트·구조 지문 이전 빌드와 동일(홈 title 마침표 1건만 정정), JSON-LD 차이는 빈 sameAs 제거뿐
- scripts/export_template.mjs + scripts/template/data(빈 데이터 세트) → templates/supporters-astro (빈 데이터로 10페이지 0오류 빌드, 게이트 통과)
- 게이트 픽스처를 자체 authors로 분리해 템플릿에서도 테스트 통과, 구조 기준선의 글 상세 페이지는 사전순 첫 글로 동적 선택
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- C 선택 기준: 가슴성형 상담 질문 10가지 체크리스트 (답 적는 칸, 병원 공개 답 병기)
- F 가격·이벤트: 견적 확인 항목 9가지 + 비용 확인 경로 (금액 미기재)
- D 시술 정보: 가슴성형 회복 일정표 (당일~1년, 주의사항·애프터케어 페이지 원문 기준, 출근 시점은 병원 확인 대기)
- E 안전·신뢰: 수면마취 vs 전신마취 (쇼츠 E-04 + 안전수술시스템 마취 프로세스)
- D 시술 정보: 보형물 교체 주기와 검진 (쇼츠 D1-11 + FDA 위험 안내 + 검진센터·애프터케어)
- 모두 reviewStatus pending, 확인 안 된 수치는 쓰지 않고 "상담 확인"으로 표기. 참고 자료 유형 태그·확인일 포함
- authors.json: 안성민 sameAs에 한국경제 CEO 인터뷰 추가
- 기획서에 1차 초안 발행 기록
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- 작성자: 가명 2명 → 안성민(편집자·편집 책임) 1명. 소개·푸터·ReviewBox에 편집 책임과 정정 요청 이메일(o2oteam@o2o.kr) 명시
- 의학 검토: 영상 출연 원장을 감수자로 표기하던 방식을 중단. 상단 메타 "설명 {원장}" + "의학 검토 대기", ReviewBox는 검토 완료 시에만 원장명·날짜 표시
- 근거 범위(G4): 촉감 글 FDA 승인 범위 한정, 표면 글 나노텍스처를 원장 의견으로 한정, 프리저베 30분·다음 날 출근 영상 사례 한정, 재수술 글 제품 권유를 임상 의견으로 한정, 안전 글 결론 문장 교체
- 원자료(G3): sources에 type 태그(병원 제공/원장 설명/제품 정보/규제·연구/플랫폼 집계/2차 자료). FDA P230005, FDA 위험 안내, ISO 14607 원문 링크 추가
- 일관성(G6): 후기 글 요약·FAQ에 플랫폼별 확인일 병기, "해외 환자 비중" 삭제. 홈 통계에 확인일
- 갱신 추적(G5): 글 frontmatter history + History 컴포넌트. 팩트 시트 checkedAt/nextCheck 표시
- 정정 경로(G8): /corrections 정정 기록 페이지(정정 7건), 푸터·소개·ReviewBox에 정정 요청 링크. 사이트맵 반영
- GEO 계획 문서에 0단계 반영 내역 기록
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- 의료진 영상: 선별 기준 설명(60초 롱폼/쇼츠 분류, 임베드·복제 고지)을 "무엇을 볼 수 있는지"로. 탭명 설명 영상 Top 10 / 1분 답변 영상, 1위 통계는 설명 영상 기준으로
- 뉴스룸: "링크 트리", 수집 질의 수 등 제거. In The News, "제목을 누르면 원문으로". 제3자 보도 미포함 사실은 고객 문장으로 유지
- 병원 정보: "홈페이지에 텍스트가 없어 강남언니 표기 사용" 사정 설명 제거, 출처 표기만 유지
- 홈 칩: "영상 1,215편을 근거로" → "원장이 직접 설명한 영상을 근거로" (채널 전체 편수를 근거 수로 읽히지 않게)
- 글 상세 영상 메모 "이 글의 주 원천" → "이 글의 바탕이 된 영상"
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- /posts: 카테고리 섹션이 글 수만큼만 칸을 차지하는 그리드 (데스크톱 3열 → 1000px 이하 2열 → 660px 이하 1열).
1편짜리 병원 소개·방문·예약·안전·신뢰·후기·평판이 데스크톱에서 나란히 배치되고 세로로 쌓이지 않음
- 헤더: 720~1040px 구간에 메뉴 간격·크기 축소, nowrap. 새 메뉴 이름 5개가 두 줄로 깨지던 문제 해결
- docs/v4-screenshots: posts 데스크톱·태블릿·좁은 폭·모바일 스크린샷 추가
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- 메뉴: 상담 전 질문(/posts) · 의료진 설명(/videos) · 병원 소식(/newsroom) · 방문 안내(/visit, 신설) · 매체 소개(/about). 기존 페이지는 그대로, 병원 정보(/clinic)는 푸터와 방문 안내에서 연결
- /visit 신설: 예약 경로 3가지 → 진료시간 → 찾아가기(지하철·주차 약도) → 도착 후 동선 → 상담 전 읽어볼 글 → 상담 예약 CTA. 값은 factSheet.json에서만
- 홈 히어로 아래 "Start Here / Where Are You Now?" 섹션: 처음 알아볼 때 · 병원을 선택할 때 · 방문을 준비할 때 카드 3개 (기존 .card 룩, 영어 세리프 헤딩 유지)
- 통계 숫자 블록 유지, 1문항 1URL 원칙 유지. 사이트맵에 /visit 추가
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>