366 lines
49 KiB
Markdown
366 lines
49 KiB
Markdown
# 다음 세션 프롬프트 v2 · "병원 URL 하나로 서포터즈 사이트까지 자동 빌드"
|
||
|
||
작성 2026-09-07 · 작성자 Claude (haewon 세션 핸드오버) · v1(2026-09-04)을 대체한다. v1의 §1 자산 위치·§3 파이프라인·§4 이식 코드·§6 함정은 여전히 유효하므로 그 부분은 v1을 참조하고, 이 문서는 **v1 이후 사람 판단이 들어간 지점을 규칙으로 바꾼 기록**이다.
|
||
|
||
왜 이 문서가 중요한가: 뷰성형외과 샘플은 URL 하나로 시작했지만, 실제로는 기획·설계·편집의 상당 부분을 사람이 판단했다. 자동 빌드가 같은 품질을 내려면 그 판단을 (1) 코드로 강제할 규칙, (2) 자동 검사, (3) 사람 승인 게이트 세 가지로 분해해 둬야 한다. 이 문서의 §3이 그 분해표다.
|
||
|
||
---
|
||
|
||
## 0. 세션 시작 시 그대로 붙여 넣을 프롬프트
|
||
|
||
```
|
||
INFINITH 저장소(브랜치 feature/discovery-url-cta)에서 "AI Discovery 자동 빌드" 기능을 개발한다.
|
||
목표: /discovery 랜딩의 URL 입력 CTA에 병원 홈페이지 URL을 넣으면, 진단 리포트(/discovery/:id)에 이어
|
||
서포터즈 사이트(supporters/ Astro 프로젝트와 같은 구조)까지 자동 생성·미리보기 배포하는 것이다.
|
||
|
||
먼저 다음 순서로 읽는다.
|
||
1. docs/NEXT_SESSION_SUPPORTERS_AUTOBUILD_v2.md (이 문서. §3 판단 분해표와 §4 근거 프로토콜이 핵심)
|
||
2. docs/NEXT_SESSION_SUPPORTERS_AUTOBUILD.md (v1. 자산 위치·파이프라인·이식 코드·함정)
|
||
3. supporters/ (정답지. 글 18편, 팩트 시트, 발행 게이트, 편집 기준 /editorial)
|
||
4. docs/reports/viewclinic/04_supporters/ (GEO 계획, 2단계 콘텐츠 기획)
|
||
|
||
원칙: 이 문서 §3에서 "규칙"으로 분류된 항목은 코드로 강제하고, "검사"는 발행 게이트에 넣고, "사람"은 승인 UI로 남긴다.
|
||
사람 게이트를 자동화하려고 하지 않는다. 근거가 없는 사실은 생성하지 않고 "확인 대기"로 표기한다(§4).
|
||
작업 순서는 §7. 결정이 필요한 것은 §9를 보고 haewon에게 묻는다. 존댓말, 엠대시 금지, 은유 금지.
|
||
```
|
||
|
||
---
|
||
|
||
## 1. v1 이후 달라진 것 (2026-09-04 → 09-07)
|
||
|
||
| 항목 | v1 (09-04) | 지금 (09-07) |
|
||
|---|---|---|
|
||
| 글 | 8편, 가명 작성자 2명, 감수 예정 | 18편. 작성자 안성민(AI오투오 대표·편집 책임) 1명. 검토 완료 10편(reviewedAt 2026-09-07), 검토 대기 5편 |
|
||
| 메뉴 | 글 / 영상 / 뉴스룸 / 병원 정보 / 운영 원칙 | 상담 전 질문 / 의료진 영상 / 뉴스룸 / 방문 안내(/visit 신설) / 매체 소개. 병원 정보(/clinic)는 푸터 |
|
||
| 화법 | 제작 원칙이 홈·소개에 노출 | 고객 화면에서 운영자 설명 전부 제거. 운영자용은 /editorial(noindex) |
|
||
| 신뢰 층 | 감수 예정 배지, 참고 자료 링크 | 참고 자료 유형 태그, 규제 원문 링크, 글별 갱신 기록, 팩트 시트 확인일·다음 확인일, /corrections 정정 기록, 정정 요청 이메일 |
|
||
| 의료진 데이터 | 원장 4명 | 10명(성형외과 8, 이비인후과 1, 마취통증의학과 1) |
|
||
| 스키마 | Article·FAQPage·Person·Physician·MedicalClinic | + reviewedBy·lastReviewed(검토 완료 글만), Person sameAs(한경 인터뷰) |
|
||
| 외부 평가 | 자체 감사 엑셀 | Astra 개선안(AS IS/TO BE), Codex 비교평가(공식 70.5 vs 서포터즈 76.5, GEO 67.5) 반영 |
|
||
| 진단 리포트 | 50/C | 54/C (v1.1 정정: 블로그 활발, 프리저베 FAQ 존재, 시술 상세 수치 존재) |
|
||
|
||
---
|
||
|
||
## 2. 이번 세션에서 사람 판단이 필요했던 순간 (시간순)
|
||
|
||
자동화 설계자가 알아야 할 "왜 그때 사람이 개입했는가"의 기록이다.
|
||
|
||
1. **"사이트가 제안서처럼 읽힌다"** (haewon). 홈에 "답변엔진이 인용하는 단락", "질문 뱅크 120문항", "홈페이지 문장을 복사하지 않는다"가 있었다. 기획 문서의 논리가 고객 화면에 그대로 새어 나온 것. → 고객/운영자 화면 분리 규칙(§3-1).
|
||
2. **"룩앤필이 바뀌었다, 돌려놓고 텍스트만"**. 화법을 고치면서 섹션 구조·영어 헤딩·통계 블록까지 바꿨더니 거부됨. → 확정 디자인은 텍스트 교체만(§3-2).
|
||
3. **"합니다/하지 않습니다/밝힙니다는 영어 직역"**. 카드 제목은 명사구로. → §3-3.
|
||
4. **외부 개선안 2건의 선별 수용**. Astra 문서 44개 제안 중 소스 대조로 사실 지적(FDA 승인 일반화, 30분·다음날 출근, 특정 제품 권유, 후기 확인일 불일치, 영상 탭에 전후·후기 제목)은 수용, 기획 취향(영어 헤딩 제거, 숫자 제거, 120문항 묶기)은 haewon 결정으로 반려. → 제안 분류 기준(§3-9).
|
||
5. **작성자 실명 확정**(안성민 대표, sameAs 한경 인터뷰). 자동화가 정할 수 없는 값. → 사람 입력(§6).
|
||
6. **의학 검토자 지정과 검토일**. 영상 출연 원장을 감수자로 자동 표기하던 것을 중단했다가, haewon 지시로 검토일을 확정. 검토자 배정은 기사·프로필 근거로 제안하고 사람이 확정. → 사람 게이트(§3-7).
|
||
7. **근거 없는 수치 처리**. 출근 기준, 견적 포함 항목, 리프팅 지속 기간, 코·윤곽 재수술 시점, 타원 재수술 정책은 어떤 소스에도 없었다. 지어내지 않고 "자료에 없음 / 상담 확인 / 병원 확인 대기"로 표기. → 근거 프로토콜(§4).
|
||
8. **보고서 오판 3건 발견**. 08-28 진단이 2개 URL 샘플과 요약 도구에 의존해 블로그 정지·FAQ 0개·수치 없음으로 오판. 원본 HTML 파싱으로 정정. → 실측 규칙(§3-10).
|
||
9. **고객용 덱 제목의 반말**. "~다" 헤드라인이 병원에 단정적으로 읽힘. → 존댓말 규칙(§3-3).
|
||
|
||
---
|
||
|
||
## 3. 판단 분해표: 규칙 / 검사 / 사람
|
||
|
||
분류 기준. **규칙** = 템플릿·프롬프트·코드에 고정. **검사** = 발행 게이트(check.mjs 확장)에서 자동 판정. **사람** = 승인 UI에서 사람이 확정해야 다음 단계로 감.
|
||
|
||
### 3-1. 고객 화면과 운영자 설명의 분리
|
||
- 규칙: 고객 화면(홈·글·영상·뉴스룸·방문·병원 정보·소개)에는 "무엇을 볼 수 있는가"와 "어떻게 쓰는가"만 쓴다. 제작 방식·선별 기준·수집 방법·기술 처리·법 조문 번호·내부 분류 코드(QB 번호)는 /editorial에만.
|
||
- 검사: 고객 화면 빌드 결과에서 금칙 어휘 검출 → `답변엔진|AI 인용|AEO|GEO|질문 뱅크|QB [A-G]|실측|단일 원본|수집 기준|API 집계|임베드|복제|의료법 제\d+조|롱폼|쇼츠 분류`. /editorial은 검사 제외.
|
||
- 사람: 없음.
|
||
|
||
### 3-2. 확정 디자인의 보존
|
||
- 규칙: 디자인이 확정된 뒤의 카피 수정은 텍스트 노드만 바꾼다. 섹션 순서·헤딩 언어(영어 세리프)·통계 블록·카드 규격은 유지. 영어 헤딩은 디자인 요소다.
|
||
- 검사: 스크린샷 회귀(홈·글 목록·글 상세 3장, 1360px)를 이전 버전과 픽셀 차이로 비교해 텍스트 외 변화가 임계 초과면 경고.
|
||
- 사람: 룩앤필 변경은 haewon 승인.
|
||
|
||
### 3-3. 한국어 화법
|
||
- 규칙: 카드·섹션 제목은 명사구(답하는 방식 / 싣지 않는 것). 고객용 덱·문서의 판단 제목은 "~합니다/~입니다", 목차성 제목은 명사구. 본문 개조식("~없음")은 허용, 반말 서술("채운다")은 금지. 엠대시·은유 금지.
|
||
- 검사: 제목 텍스트가 `(합니다|하지 않습니다|밝힙니다)$`처럼 동사 종결이면 경고. 본문에서 `[가-힣]다\.` 문장 검출(개조식 명사 종결은 제외 어렵기 때문에 경고 수준).
|
||
- 사람: 최종 문안 확인.
|
||
|
||
### 3-4. 근거 유형과 원문 링크
|
||
- 규칙: 참고 자료마다 유형(clinic 병원 제공 / doctor 원장 설명 / product 제품 정보 / regulation 규제·연구 / platform 플랫폼 집계 / secondary 2차 자료)을 붙인다. 규제·연구 주장은 영상 재진술이 아니라 원문 URL(FDA, ISO, 법령)까지 연결한다. 원장 발언은 "영상에서 설명한다"로 화자를 밝힌다.
|
||
- 검사: sources에 type 없는 항목 실패. 본문에 `FDA|ISO|승인|연구`가 있는데 regulation 타입 소스가 없으면 실패.
|
||
- 사람: 없음.
|
||
|
||
### 3-5. 근거 범위 표현
|
||
- 규칙: 제품 승인은 "특정 제품·해당 국가 적응증"으로 한정하고 "위험이 없다는 뜻이 아니다"를 붙인다. 원장의 제품 선호·비교우위는 "임상 의견"으로 표기. 수술 시간·회복·복귀 시점은 "영상 사례"로 한정하고 개인차 조건을 답 옆에 둔다. "~하면 안전하다고 볼 수 있다"류 결론 금지. 특정 제품 권유는 "진료에서 정한다"로 닫는다.
|
||
- 검사: 금칙 패턴 확장 → `안정성이 확인|안전이 보장|비교우위|장점을 합친|돌아가고 있다고 볼 수|다음 날 출근할 수 있을 정도` 등. 수치(`\d+분|\d+일|\d+주`) 문장에 `개인차|상담|영상 기준|사례` 중 하나가 같은 문단에 없으면 경고.
|
||
- 사람: 담당 원장 검토.
|
||
|
||
### 3-6. 수치·확인일 일관성
|
||
- 규칙: 플랫폼 집계(강남언니·구글·네이버)는 값마다 확인일을 붙이고, 요약·FAQ·표에서 같은 값은 같은 확인일로. 팩트 시트에 checkedAt·nextCheck.
|
||
- 검사: 같은 수치 문자열(예 19,373)이 글 안에서 서로 다른 날짜와 붙어 있으면 실패. nextCheck가 지났으면 빌드 경고.
|
||
- 사람: 없음.
|
||
|
||
### 3-7. 작성자·검토자·검토일
|
||
- 규칙: 영상 출연 원장을 검토자로 자동 배정하지 않는다. 검토자 미확정이면 "설명 {원장}" + "의학 검토 대기". reviewedBy·lastReviewed 스키마는 reviewStatus=reviewed일 때만. 검토일은 reviewedAt 필드(갱신일과 분리).
|
||
- 검사: reviewStatus=reviewed인데 reviewedAt 없으면 실패. reviewer가 physicians에 없으면 실패.
|
||
- 사람: 검토자 확정과 검토일은 병원 또는 haewon이 입력. 자동화는 후보(기사·프로필 근거)만 제안한다.
|
||
|
||
### 3-8. 싣지 않는 것
|
||
- 규칙(v1 유지): 전후 사진, 환자 경험담, 타 병원 비교, 효과 보장, 가격 금액, 후기·전후·변신 제목 영상. 이유는 고객 화면에서 한 문장으로만("병원 지원을 받는 곳이 경험담으로 설득하면 광고가 된다"), 조문은 /editorial.
|
||
- 검사: 기존 BANNED + 영상 제목 필터(`전후|리뷰|성공|번호따|변신|역대급`)를 영상 목록 빌드에 적용. **미결: "채널 인기 전체" 탭 제거 여부(haewon 결정 대기)**.
|
||
- 사람: 탭 제거 결정.
|
||
|
||
### 3-9. 외부 개선안·평가의 수용 기준
|
||
- 규칙: 제안을 세 갈래로 나눈다. (a) 사실 지적(소스 대조로 확인되면 수용), (b) 구조 제안(기존 페이지 보존 + 없는 것만 추가), (c) 기획 취향(haewon 결정). 점수 평가는 "무엇을 고칠지"에는 쓰고 "효과가 얼마인지"의 근거로는 쓰지 않는다.
|
||
- 검사: 없음.
|
||
- 사람: (c) 전부.
|
||
|
||
### 3-10. 실측 규칙
|
||
- 규칙: 사이트 판정은 원본 HTML을 받아 파서로 확인한다(JSON-LD json.loads, H1 정규식, table 카운트, robots 원문, sitemap lastmod). 요약 도구(WebFetch 등 소형 모델)는 JSON-LD 타입을 틀리게 답한 전례가 있어 판정 근거로 쓰지 않는다. 표본 2개 URL의 결과를 사이트 전체로 일반화하지 않는다(최소: 홈 + 시술 상세 3개 + 오시는길 + 블로그 서브도메인).
|
||
- 검사: 자동 채점기 입력 URL 수 5개 미만이면 경고 표기.
|
||
- 사람: 없음.
|
||
|
||
### 3-11. 원천 콘텐츠의 정의 (G7)
|
||
- 규칙: "홈페이지를 다시 쓰는 글"은 만들지 않는다. 원천으로 치는 5유형만 기획한다. 체크리스트(상담 질문·견적 항목), 조건 표(회복 일정·마취 선택·검진 주기), 협진·동선 설명, 발언 대본 인용(타임스탬프), 실측 기록(방문). 주제 선정 근거 = 질문 뱅크 ✕ 문항 × 유튜브 조회수 × 뉴스 주제 × 홈페이지에 없는 정보 유형.
|
||
- 검사: 글 본문의 홈페이지 40자 연속 일치(기존). 표 또는 체크리스트가 하나도 없는 D·E 카테고리 글은 경고.
|
||
- 사람: 기획 목록 승인.
|
||
|
||
---
|
||
|
||
## 4. 근거 프로토콜 (글 생성기가 지켜야 할 것)
|
||
|
||
이번 세션 10편은 아래 순서로만 사실을 가져왔다. 자동 생성기는 이 순서를 프롬프트 컨텍스트로 강제한다.
|
||
|
||
1. **병원 공식 페이지 원문**: 수술 전·후 주의사항(부위별 문장 전부), 애프터케어(부위별 프로그램·기간), 검진센터(항목·담당), 안전수술시스템(마취 프로세스·장비), 시술 상세(수술시간·마취·실밥·일상 복귀), 의료진 프로필(직함·경력). 문장은 옮기되 40자 연속 복사 금지.
|
||
2. **쇼츠 정리 답**: `videos.json.shortsInfo[].answer`처럼 이미 사람이 정리한 한 문단. 영상 발언의 근거는 이것만 쓴다(자막이 없으면 발언을 새로 만들지 않는다).
|
||
3. **원장 기고·인터뷰 기사**: 원장 이름과 매체·날짜를 밝히고 인용. 이름이 불확실하면(예: "정진우"로 읽힌 코재수술 칼럼) 이름 없이 "원장 칼럼"으로.
|
||
4. **규제·연구 원문**: FDA, ISO, 법령. 요약 도구가 수치를 확인하지 못하면 수치를 쓰지 않는다(예: FDA 검진 주기).
|
||
5. **플랫폼 집계**: 확인일 병기.
|
||
|
||
없는 것은 없다고 쓴다. 실제로 이번에 "자료에 없음"으로 남긴 것: 가슴성형 후 출근 기준, 견적 기본 포함 항목·결제 방식, 리프팅 효과 지속 기간, 코·윤곽 재수술 대기 기간, 윤곽 신경 손상 확률, 타원 수술 재수술 상담 정책. 페이지 간 표기가 다르면 둘 다 쓴다(코 실밥 제거 7일 vs 3일).
|
||
|
||
---
|
||
|
||
## 5. 신뢰 층 스펙 (템플릿이 기본으로 갖춰야 할 것)
|
||
|
||
| 요소 | 데이터 | 화면 | 스키마 |
|
||
|---|---|---|---|
|
||
| 작성자 | authors.supporters[id]: name·role·bio·email·sameAs | 글 상단 "작성", 하단 ReviewBox, /authors/:id | Person + sameAs |
|
||
| 편집 책임·정정 경로 | corrections.json: owner·contact·items | 소개, 푸터, ReviewBox, /corrections 표 | WebPage dateModified |
|
||
| 검토 | reviewer·reviewStatus·reviewedAt | 상단 "의학 검토 {원장} ({일})" 또는 "설명 {원장} · 의학 검토 대기", ReviewBox 배지 | reviewedBy(Physician @id) + lastReviewed, reviewed일 때만 |
|
||
| 근거 | sources[].type·accessed | "참고한 자료" 유형 태그 + 확인일 + 한 줄 해설 | (없음) |
|
||
| 갱신 | history[] | "갱신 기록" 역순 목록 | dateModified |
|
||
| 팩트 | factSheet.checkedAt·nextCheck | FactBlock 각주 | MedicalClinic |
|
||
| 지원 관계 | Disclosure 문구 | 모든 글 하단 | (없음) |
|
||
|
||
---
|
||
|
||
## 6. 병원(고객)이 입력해야 하는 것 (자동화가 만들 수 없는 값)
|
||
|
||
입력 폼으로 받는다. 받기 전까지 해당 표기는 "확인 대기"로 발행된다.
|
||
|
||
1. 작성자 실명·직함·공개 프로필 URL(sameAs), 편집 책임자, 정정 요청 이메일
|
||
2. 글별 의학 검토 원장과 검토일 (후보는 자동 제안)
|
||
3. 지원 관계 문구(금전·자료·기타)
|
||
4. 견적 기본 포함 항목과 결제 방식 (금액은 받지 않는다)
|
||
5. 회복 일정표의 병원 확정값 (출근 기준 등)
|
||
6. 재수술 정책 (타원 수술 상담 가능 여부, 부위별 대기 기간)
|
||
7. 페이지 간 표기 불일치의 정답 (예: 코 실밥 제거일)
|
||
8. 진료 분야별 담당 원장 (눈·코·윤곽·리프팅·마취)
|
||
9. 정식 도메인, 색인 허용 시점, 홈페이지에서의 링크 위치
|
||
|
||
이 목록은 진단 리포트 v1.1의 마지막 "부탁드리는 것" 슬라이드와 같다. 리포트와 폼이 같은 항목을 가리키게 유지한다.
|
||
|
||
---
|
||
|
||
## 7. 작업 순서 (v1 §5를 이 순서로 대체)
|
||
|
||
1. **게이트 확장** (`supporters/scripts/check.mjs`): §3-1·3-4·3-5·3-6·3-7의 "검사"를 추가하고, 현재 18편이 통과하는지 확인. 실패 케이스 픽스처 6개(운영자 어휘, type 없는 source, reviewed인데 reviewedAt 없음, 확인일 불일치, 영상 제목 금칙, 결론 문장)를 만든다.
|
||
2. **템플릿화**: `supporters/`에서 뷰성형외과 고유값을 데이터 파일로 몰고 `templates/supporters-astro/`로 복제. 신뢰 층(§5)이 빈 데이터로도 "확인 대기"로 렌더되게 한다.
|
||
3. **근거 수집기**: 병원 페이지 원문(주의사항·애프터케어·검진·안전·시술 상세·의료진)을 구조화해 `evidence/<clinic>/*.json`으로 저장. 40자 중복 검사용 home_text도 여기서.
|
||
4. **글 생성 프롬프트**: §4 순서의 컨텍스트만 주고, 출력은 frontmatter 규격 + sources type + history. 뷰성형외과 18편을 정답지로 회귀(같은 문항·같은 근거로 생성 → 게이트 통과 + 세 줄 요약·표·FAQ 규격).
|
||
5. **승인 UI**: §6 입력 폼 + 글별 검토 승인(검토자·검토일 입력 → reviewedAt 기록). 승인 전 글은 "검토 대기" 배지로 미리보기에만.
|
||
6. **워커·배포·랜딩 연결**: v1 §3·§5-2·5-5·5-6 그대로.
|
||
7. **두 번째 병원 회귀**: `data/plastic surgery clinics url.json`에서 한 곳. 사람 개입은 §6 입력과 §3 "사람" 항목만.
|
||
|
||
---
|
||
|
||
## 8. 이번 세션의 함정 (v1 §6에 추가)
|
||
|
||
- Astro `getCollection` 스키마에 필드를 추가하면 기존 md 전부에 기본값이 필요하다. `history`·`sources[].type`은 `.default([])`·`.optional()`로.
|
||
- YAML frontmatter 안에 큰따옴표 문자열 속 큰따옴표(`"근거 없는 "해외 환자 비중" 표현"`)는 파싱 실패. 생성기는 따옴표를 「」로 바꾸거나 이스케이프.
|
||
- `sed -n` 결과를 근거로 파일 상태를 추정하지 말 것. 이전 python 스크립트가 이미 적용된 상태에서 재실행하면 assert가 깨진다. 멱등 처리 또는 사전 검사.
|
||
- WebFetch 소형 모델은 JSON-LD 타입(LocalBusiness·MedicalBusiness가 있다고 답함)과 H1 목록을 틀리게 요약했다. 판정은 curl + 파서로만.
|
||
- 뉴스 데이터에 병원과 무관한 기사(AI오투오 출시 기사 등)가 섞인다. 본문 관련성 필터 필요(Astra 지적, 미반영).
|
||
- 헤더 메뉴 이름이 길어지면 720~1040px에서 두 줄로 깨진다. nowrap + 구간별 축소 규칙 추가함.
|
||
- 글 목록은 카테고리별 글 수가 1편이면 세로로 쌓인다. 글 수만큼 span하는 그리드로 해결(`.cat-grid`, 3→2→1열).
|
||
- 덱 빌더(ifd)는 폰트 확정 기준(본문 20)에서 카피 분량 검사를 강제한다. 3열 카드 불릿은 약 30자, 2열 rows 본문은 약 55자, 리드는 약 60자, 제목은 약 20자. 폰트를 줄이지 말고 카피를 줄인다.
|
||
- LibreOffice PDF 변환은 pptx 재빌드 실패 시에도 이전 파일로 조용히 성공한다. 빌드 → 축소 → PDF를 `&&`로 묶는다.
|
||
|
||
---
|
||
|
||
## 9. haewon에게 물어볼 것
|
||
|
||
1. 영상 페이지 "채널 인기 전체" 탭(전후·후기 제목 포함) 제거 여부.
|
||
2. §6 입력 폼을 어디에 둘지: 서포터즈 사이트 내 관리자 페이지 / INFINITH 랜딩 / 노션·이메일.
|
||
3. 검토 승인의 법적 책임 주체(병원 원장 서명 형태가 필요한지).
|
||
4. 두 번째 검증 병원.
|
||
5. 생성 모델과 키(Claude API 회사 키 유무), 글 생성 단가 상한.
|
||
6. v1 §7의 워커 위치·배포 방식.
|
||
|
||
---
|
||
|
||
## 10. 완료 기준 (v1 §8에 추가)
|
||
|
||
- §3의 "검사" 11개가 게이트에 있고, 픽스처로 각각 실패를 재현한다.
|
||
- 뷰성형외과 18편이 확장된 게이트를 0오류로 통과한다.
|
||
- 자동 생성 글이 §4 순서 밖의 사실을 포함하지 않는다(근거 없는 수치 = 0건, 수동 대조 10편).
|
||
- §6 입력이 비어 있어도 사이트가 "확인 대기" 표기로 빌드·배포된다.
|
||
- 병원이 §6을 채우면 코드 수정 없이 데이터만으로 검토 완료·스키마가 켜진다.
|
||
|
||
---
|
||
|
||
## 11. 진행 기록 (2026-09-07 세션 2 · 브랜치 `feature/supporters-autobuild`, 워크트리 `orca/workspaces/INFINITH/Productize`)
|
||
|
||
§7의 1·2단계를 마쳤다. 3단계부터는 §9의 답이 필요한 항목이 섞여 있어 아래 "남은 결정"을 먼저 본다.
|
||
|
||
### 11-1. 게이트 확장 (§7-1) · 커밋 49c5e46
|
||
- `supporters/scripts/gate/rules.mjs`: §3의 "검사"를 순수 함수로. error(배포 차단) 11종 + warn 6종.
|
||
- error: OPERATOR_VOCAB(3-1) · SOURCE_TYPE_MISSING/UNKNOWN(3-4) · REGULATION_SOURCE_MISSING(3-4) · CONCLUSION_PHRASE(3-5) · NUMBER_DATE_MISMATCH(3-6) · REVIEWED_WITHOUT_DATE/REVIEWER · REVIEWER_UNKNOWN · AUTHOR_UNKNOWN(3-7) · BANNED_VIDEO_TITLE(3-8) · BANNED_PHRASE · HOME_DUPLICATE(기존)
|
||
- warn: LAYOUT_CHANGED(3-2, 픽셀 대신 텍스트를 뺀 tag.class 구조 지문 비교) · HEADING_VERB · PLAIN_ENDING(3-3) · NUMERIC_NO_QUALIFIER(3-5) · FACT_NEXTCHECK_PASSED(3-6) · NO_TABLE_OR_CHECKLIST(3-11)
|
||
- 결론 문장 검사는 문장 단위이고 부정문("보장되는 것은 아닙니다")과 임상 의견 표기("원장의 임상 판단")는 통과시킨다. 정답지 18편이 이 예외 없이는 걸린다.
|
||
- `scripts/check.mjs`: dist + 소스 frontmatter + 데이터 JSON 검사. `--update-layout`은 haewon이 룩앤필 변경을 승인한 뒤에만.
|
||
- `scripts/gate/test.mjs` + `fixtures/` 9개: 실패 재현 7건(운영자 어휘·type 없는 source·reviewed인데 reviewedAt 없음·검토자 미등록·확인일 불일치·영상 제목 금칙·결론 문장·규제 원문 없음) + 18편 회귀 + 부정문 통과. `npm run gate:test`.
|
||
- 18편 결과: 오류 0, 경고 10(수치 한정 없음 5, 「채널 인기 전체」 탭 영상 제목 5). corrections.json의 「답변엔진」과 반말 문장 1건은 고쳤다.
|
||
- `scripts/audit_aeo_geo.py`: 표본 URL 5개 미만 경고(§3-10). 채점기 자체는 아직 2개 URL만 읽는다.
|
||
|
||
### 11-2. 템플릿화 (§7-2) · 커밋 622441e
|
||
- 병원 고유값은 `factSheet.json`(사실) · `authors.json`(사람) · `site.json`(매체 이름·로고·홈 큐레이션·방문 약도·추천 글) 세 파일로만 들어간다. 페이지 15개에서 하드코딩을 뺐다.
|
||
- `lib.ts`: `PENDING = '확인 대기'`, `v()`(표시), `has()`(스키마·링크), `surface()`. 빈 값은 화면에 "확인 대기", 스키마에서는 필드 제거.
|
||
- 검증: 28페이지의 표시 텍스트와 구조 지문이 리팩터 전 빌드와 동일. JSON-LD 차이는 빈 `sameAs: []` 제거뿐.
|
||
- `scripts/export_template.mjs` → `templates/supporters-astro/`. 글·데이터·이미지·home_text·구조 기준선을 빼고 `scripts/template/data/`의 빈 세트를 넣는다. 병원 문자열이 남으면 실패. 빈 데이터로 10페이지 0오류 빌드, 게이트 통과.
|
||
- 템플릿 사용: `templates/supporters-astro`를 복사 → 데이터 6개 + posts + public/img + home_text 채움 → `__CLINIC_ID__` 치환 → `npm ci && npm run build`.
|
||
|
||
### 11-3. 남은 단계와 의존 관계
|
||
| 단계 | 상태 | 막는 것 |
|
||
|---|---|---|
|
||
| 3 근거 수집기 (`evidence/<clinic>/`) | **완료** (커밋 c92ecc8, §11-4) | 없음 |
|
||
| 4 글 생성기 | **완료** (§11-5) | 편당 약 $0.09 실측. 단가 상한은 --max-cost-usd 로 걸 수 있고 값은 미정 |
|
||
| 5 승인 UI (§6 입력 폼) | **완료·프로덕션 배포** (§11-6, §11-8) | 상단 고지 문구(site.sponsorNotice)는 병원 입력 후 켜진다 |
|
||
| 6 워커·배포·랜딩 연결 | **완료** (§11-7, §11-8 미리보기 배포됨) | 워커 실행 위치(§12-3)·자동 트리거는 미결. 지금은 로컬에서 수동 실행 |
|
||
| 7 두 번째 병원 회귀 | **완료** (§11-9, 원진성형외과 6/6편, 게이트 0오류) | 없음 |
|
||
| 「채널 인기 전체」 탭 | **제거됨** (§11-9) | 없음 |
|
||
|
||
### 11-4. 근거 수집기 (§7-3) · 커밋 c92ecc8
|
||
- `supporters/scripts/collect_evidence.mjs --clinic <id> --url <홈> [--posts src/content/posts]`. Node 22 + node-html-parser, Firecrawl·요약 도구 없이 curl+파서만(§3-10).
|
||
- 발견: 홈 전체 앵커(메뉴 제거 전) + `page` 사이트맵만(글·영상 post 사이트맵 제외). robots.txt Disallow 존중, 요청 간 400ms.
|
||
- 분류: 경로 세그먼트 우선, 단어 경계(`relocation`이 `location`에, `contour`가 `tour`에 걸리던 오분류 수정). 후보는 `수술 시간|마취|회복|실밥…` 힌트로 procedure/other.
|
||
- 본문: 컨테이너 후보(`main`, `#ajax-content-wrap`, `#content`…) 중 200자 넘는 첫 것 → 페이지 30% 이상에 반복되는 줄(메뉴·푸터) 제거 → 헤딩·문단·목록·표·이미지·링크.
|
||
- 산출: `index.json`(유형·글자·표·이미지·플래그), `pages/<slug>.json`, `doctors.json`, `facts.draft.json`(전화·주소·사업자번호·대표·진료시간 후보 + 출처 URL), `home_text.txt`(전 페이지 본문 공백 제거).
|
||
- 뷰성형외과 결과: 222 링크 → 223 페이지(정보형 유형 18 + 의료진 상세 27 + 시술 108 + 기타 70). 글에 인용된 병원 URL 16/16 커버(`/face/main/`은 301 → `/facial-contour/main/`). 의료진 27명 이름·직함 확인, **약력은 27명 전원 이미지 글자라 "확인 대기"** (authors.json의 약력은 사람이 이미지를 읽어 넣은 값이다. 자동화는 이 값을 만들 수 없다 → §6 입력 항목).
|
||
- 게이트 연결: `node scripts/check.mjs --home-text=../evidence/viewclinic/home_text.txt` → 18편이 전체 사이트 29만 자 기준 40자 연속 일치 0건.
|
||
- 한계: 홈 본문은 이미지·슬라이더라 0자(사실 후보는 전체 body에서 뽑아 정상). 주의사항 페이지는 탭 구조라 표가 0개이고 부위별 문장은 문단으로만 들어온다. 표 형태로 재구성하는 것은 글 생성기의 일.
|
||
|
||
### 11-5. 글 생성기 (§7-4) · 2026-09-07 세션 3
|
||
- `supporters/scripts/generate_posts.mjs` + `scripts/gen/evidence.mjs`(§4 순서 컨텍스트) · `gen/prompt.mjs`(규칙·스키마·근거 대조 프롬프트) · `gen/serialize.mjs`(js-yaml 직렬화 + 빌드 없는 소스 게이트). 입력 형식은 `supporters/briefs/README.md`.
|
||
- 흐름: brief → 컨텍스트(병원 페이지 → 쇼츠 정리 답/자막 → 기사 제목 → 규제 원문 → 팩트 시트 → 의료진 목록) → GPT-4.1 구조화 출력(요약 3·본문·FAQ·태그·pending·usedRefs) → 후처리(근거 태그·본문 FAQ 제거) → 검사 3종 → 수정 최대 2회 → md + report.
|
||
- 검사 3종: (1) 소스 게이트 = rules.mjs 전부 + 금칙어 + 홈페이지 40자 중복 + **COMPARISON_CLAIM 신설**(타 병원·업계 평균 비교 수치. 안전 페이지의 "병원급 평균 23.1% vs 43%"를 모델이 실제로 옮겨 써서 추가) (2) 수치 대조 = 글의 숫자+단위 토큰이 근거 텍스트에 그대로 있어야 함(NUMBER_NOT_IN_EVIDENCE, 1차 출력에서 18편 중 19건 검출) (3) 모델 근거 대조 = unsupported/distorted 목록, 항목별 supported 판정으로 오탐("근거에 명시되어 있음"이라며 올리는 것) 제거.
|
||
- sources·videos·검토자 후보는 brief에서 결정론적으로 조립한다. 모델은 사실의 출처를 고르지 않는다. reviewStatus 는 항상 pending, reviewedAt 은 쓰지 않는다(§3-7).
|
||
- 정답지 18편 회귀(같은 문항·같은 근거 URL): **18/18 게이트 오류 0**(1차 실행 12편 통과 + 검사 오탐 수정 후 6편 재실행 통과). 편당 약 $0.09(호출 2~6회, 목록가 기준), 22초. 리포트 `docs/reports/viewclinic/04_supporters/Viewclinic_Supporters_Generator_Regression_2026-09-07_run1.md` · `…_run2_retry6.md`, 샘플 3편 `generated_samples/`.
|
||
- 새 문항 검증: `briefs/viewclinic/eye-double-eyelid-methods.json`(쌍꺼풀 자연유착·절개·콤비매몰 비교, D2-02/03/06) → 수정 호출 없이 통과, $0.10.
|
||
- 정답지와의 판단 차이(사람 확인 항목): 모델은 애프터케어의 "5~7일 후 일상생활 가능"을 출근 시점으로 읽고, 사람 편집자는 "출근 기준은 공개 자료에 없음"으로 썼다. 근거에는 있으므로 게이트는 통과한다. 이런 해석 차이는 검토 원장 게이트에서 잡는다.
|
||
- 한계: 본문이 이미지 글자인 페이지(코 메인·가슴재수술·진료분야)는 근거 0자로 들어가 pending 에 쌓인다. 자막 없는 롱폼은 인용하지 않으므로 그 글은 정답지보다 얇다(보형물 표면 글 650~900자). 자막 파이프라인(v1 §6)이 붙으면 `evidence.transcripts` 로 넣는다.
|
||
- 미결: 단가 상한값(§9-5). 실측 편당 $0.05~0.19, 첫 배치 10편이면 약 $1.
|
||
|
||
### 11-6. 승인 UI · 입력 반영 (§7-5, §12-2 코드 반영) · 2026-09-07 세션 3
|
||
- 테이블: `supabase/migrations/20260907_supporter_builds.sql` — `supporter_builds`(빌드 실행 기록·단계·글 목록·미리보기 URL, 워커가 service_role 로 갱신) · `supporter_inputs`(§6 9항목 + 글별 post_review/post_approval, 익명 insert/select). **미적용** (discovery_leads 와 함께 `supabase db push`).
|
||
- 폼: `src/components/discovery/ClinicInputsPanel.tsx` → `/discovery/:id` 5절과 6절 사이. 빌드 상태·미리보기 링크, 9항목 입력(입력자 기록), 의료진 ID 표, 글별 검토(검토자 ID·검토일)와 게시 승인(개설자 이름·직함·승인일). 검토 전 승인 버튼은 비활성. tsc 통과.
|
||
- 반영: `supporters/scripts/apply_inputs.mjs --inputs file | --from-supabase`. 같은 (key, post_id) 최신 행만. author/editor → authors·corrections, sponsorship → site.sponsorNotice, specialty_doctors → physicians.specialty, domain → site, 자유 답변 4종 → `src/data/clinicAnswers.json`(생성기 근거 [A], `--site` 옵션으로 워커 작업 폴더에서도 동작), post_review → reviewer·reviewStatus=reviewed·reviewedAt·history, post_approval → approvedBy·approvedAt(검토 전이면 보류). 샘플 `supporters/briefs/viewclinic/inputs.sample.json` dry-run 9건 반영 확인.
|
||
- §12-2 코드 반영: (1) `DisclosureTop.astro` + 게이트 `DISCLOSURE_TOP_MISSING`(site.sponsorNotice 비면 warn, 채우면 error). 지금은 비어 있어 룩앤필 변화 없음. (2) frontmatter `approvedBy/approvedAt`, `lib.isPublishable`: PUBLIC_INDEXABLE=true 빌드는 승인 글만 낸다(글·목록·사이트맵·작성자 페이지). 검증: 색인 허용 빌드 → 승인 0편이라 글 0개, 게이트 오류 0. 게이트 `APPROVED_WITHOUT_BY/DATE`·`APPROVED_BEFORE_REVIEW`·`UNAPPROVED_IN_INDEXABLE_BUILD`. (3) `PRESS_VOICE` 경고를 rules.mjs 로. 규제 주장 검사에서 「게시 승인」은 제외.
|
||
- 랜딩 카피: SampleReport 의 "SAMPLE REPORT · 뷰성형외과 실측" → "SAMPLE REPORT · 실제 사례"(haewon 지시). 두 워크트리(이 브랜치, feature/discovery-url-cta)에 적용, 프로덕션 배포 완료(§11-8).
|
||
|
||
### 11-7. 워커 (§7-6) · 2026-09-07 세션 3
|
||
- `workers/supporters-build/run.mjs --clinic <id> --url <홈> [--inputs|--from-supabase] [--brief] [--max-posts] [--max-cost-usd] [--deploy] [--build-id]`. 실행 환경 독립(로컬·GitHub Actions·Trigger.dev 태스크 어디서든 같은 명령). 단계 evidence → data → inputs → briefs → generate → build → deploy → done, 단계마다 `<work>/status.json` + (build-id 있으면) supporter_builds PATCH.
|
||
- data 단계: 템플릿 복제 + `__CLINIC_ID__` 치환 + facts.draft 첫 후보로 팩트 시트(상호·전화·주소·사업자번호·대표, checkedAt/nextCheck) + doctors.json 으로 physicians(이름·직함·URL, 약력은 빈 배열) + 작성자 "확인 대기".
|
||
- briefs 단계: `supporters/scripts/default_briefs.mjs` 가 근거 유형(about·direction·safety·precautions·aftercare·checkup)이 실제로 있는 문항만 골라 첫 배치 최대 6편(A 병원 소개, B 방문, E 안전, D 주의사항, C 상담 질문, D 애프터케어). 비교 수치·가격·전후·경험담은 avoid 에 고정.
|
||
- **뷰성형외과 E2E 실측**: URL 하나 → 223페이지 수집 → 의료진 27명 → brief 5편(병원 소개는 about 페이지 본문 0자라 제외) → 5/5편 게이트 통과(수정 호출 0, $0.29, 편당 15초) → npm ci·astro build·check.mjs 오류 0(경고 2) → dist 생성. 사람 개입 0. 배포는 `--deploy` 를 주지 않아 건너뜀. 리포트 `docs/reports/viewclinic/04_supporters/Viewclinic_Supporters_Worker_E2E_2026-09-07.md`, brief `generated_samples/default_briefs_viewclinic.json`.
|
||
- deploy 단계(미실행): `vercel link --yes --project supporters-<id>` + `vercel deploy --prod --yes`. 첫 실행은 Vercel 프로젝트를 새로 만드는 외부 행위라 haewon 확인 후. 트리거(discovery_leads insert → Database Webhook → 워커)와 Trigger.dev 래핑은 §12-3 확인 후.
|
||
- 남은 것: discover-channels(유튜브·인스타 핸들)·유튜브 집계·뉴스룸(build_news.py)·감사 재실행(Phase 9)은 워커에 아직 안 붙었다. 이 세 개는 뷰성형외과 샘플에서 사람이 돌린 스크립트가 있으므로 다음 세션에 단계로 추가한다.
|
||
|
||
### 11-8. 실행 (haewon "다 실행해줘") · 2026-09-07 세션 3
|
||
- Supabase: `supporter_builds`·`supporter_inputs` 마이그레이션 적용(Management API `/database/query`, CLI 키체인 토큰 사용. `discovery_leads` 는 이미 적용돼 있었음). 테이블 3개 확인.
|
||
- 서포터즈 미리보기: 워커 deploy 단계 실행 → Vercel 프로젝트 `supporters-viewclinic` 생성, **https://supporters-viewclinic.vercel.app** (X-Robots-Tag noindex, robots Disallow 확인). supporter_builds 행 05ae08e3… status=preview, preview_url 기록.
|
||
- 랜딩 앱: 브랜치 `feature/supporters-autobuild` 를 origin 에 푸시하고 `vercel --prod` 로 infinith-demo 프로덕션 배포. 번들에 "SAMPLE REPORT · 실제 사례", "병원 확인 항목" 확인. /discovery/viewclinic 하단에 병원 확인 항목 패널이 미리보기 링크와 함께 뜬다.
|
||
- 아직 자동이 아닌 것: discovery_leads insert → 워커 실행 트리거. 지금은 `node workers/supporters-build/run.mjs --clinic <id> --url <홈> --deploy --build-id <id>` 를 사람이 돌린다. 병원 입력 후 재빌드도 `--from data --from-supabase` 로 수동.
|
||
|
||
### 11-9. haewon 결정 반영과 두 번째 병원 완주 (§7-7) · 2026-09-07 세션 4
|
||
- 결정(§9): 9-1 「채널 인기 전체」 탭 **제거**(videos.astro, check.mjs 경고 삭제). 9-4 두 번째 병원 **원진성형외과**(https://www.k-wonjin.co.kr). 9-5 단가 상한 **실행당 $10**(generate_posts·run.mjs 기본값). 9-6 워커 위치는 Claude 추천 → `workers/supporters-build/README.md`: 파일럿은 haewon Mac 의 launchd 폴러(`launchd/com.infinith.supporters-poll.plist`, 미설치), 정착은 Trigger.dev(가입·API 키만 haewon).
|
||
- 큐 연결: DiscoveryLeadModal 이 `discovery_leads` 와 함께 `supporter_builds`(queued, clinic_id 는 호스트 첫 세그먼트) 행을 만든다. 마이그레이션 `20260907_supporter_builds_queue.sql`(clinic_name 열, anon queued insert 정책) 적용됨. `workers/supporters-build/poll.mjs` 가 queued 행을 조건부 갱신으로 집어 `run.mjs` 실행. 리포트 없는 병원용 `/supporters/:id` 페이지(ClinicInputsPanel 단독). 랜딩 프로덕션 재배포 완료.
|
||
- **원진성형외과 E2E**: 3번 실패하고 4번째에 완주. 실패 원인과 수정 (1) 비브라우저 UA 403 → 브라우저 UA + 식별 문자열 (2) 경로 끝 슬래시 강제 → 404. 슬래시 미강제 + 404 시 반대 형태 재시도(뷰성형외과 회귀 223페이지 동일) (3) 기획 목록이 뷰 전용 페이지 유형에만 의존 → `default_briefs.mjs` 2층 구조(전용 페이지 문항 + 시술 영역·소개·예약 기반 문항, 조사 은/는 처리) (4) 인터넷 끊김(fetch failed) → `--from generate` 재개.
|
||
- 결과: 216페이지 · 의료진 17명 · 브리프 6편(병원 소개, 방문, 윤곽, 눈성형, 레이저안티에이징, 상담 질문) → **6/6편 게이트 통과**(수정 호출 3, 근거 플래그 2건은 사람 확인용) · $0.58(편당 $0.10) · 빌드·게이트 오류 0 · **https://supporters-wonjin.vercel.app**(noindex). 사람 개입 0. v1 §8 "두 번째 병원에서도 게이트 0오류로 완주" 충족.
|
||
- 원진 글의 특징: 시술 페이지에 없는 칸은 표에 "확인"으로 남고(눈성형 표의 쌍꺼풀·눈매교정 행 전부 확인), 근거가 있는 행(CFS 2시간·7일·3일, 오픈아이 40분·5~7일)만 값이 있다. 이것이 의도한 동작이다. 리포트 `docs/reports/viewclinic/04_supporters/Wonjin_Supporters_Worker_E2E_2026-09-07.md`.
|
||
- 남은 것: 유튜브 핸들 발견·조회수 집계·뉴스룸·감사 재실행을 워커 단계로 추가. 원진은 유튜브 채널 3개가 registry 에 있으므로 첫 후보. launchd 폴러 설치는 haewon 확인 후.
|
||
|
||
### 11-10. 유튜브·로고 단계 (v1 §3 Phase 2 일부) · 2026-09-08
|
||
- haewon 지적: 원진 글 카드에 검은 도형(Astro 기본 파비콘)이 보임. 원인은 워커가 이미지·영상 자산을 아직 안 붙이고 카드가 파비콘으로 대체하던 것.
|
||
- `supporters/scripts/collect_youtube.mjs --channel <UC…|@handle|URL>`: YouTube Data API 로 uploads 전량 → videos.list 배치 → 쇼츠 판별(/shorts/{id} HEAD 200, 상위 120편, 제목 #shorts 포함 시 쇼츠) → viewclinic 과 같은 videos.json(channel·top·topLong·topShorts·shortsInfo·all). 정보형 판정 = NOT_INFO(후기·전후·토크·브이로그·브랜드 필름·연예인·트렌드·변화 등) + 게이트 BANNED_VIDEO_TITLE + checkBannedBody(제목). 설명형 롱폼은 90초 이상. `all[].info` 로 판정을 남긴다. shortsInfo.answer 는 비워 둔다(사람이 채움).
|
||
- 워커 `youtube` 단계(data 다음): `--logo <svg|png>` → public/img/logo.*, site.logo/logoFoot, 파비콘(SVG 는 64×64 흰 배경에 중앙 배치한 favicon.svg). `--youtube <채널>` 없으면 근거 링크에서 자동 발견. site.homeVideos(topLong 3편), factSheet.surfaces.youtube 채움. 오늘 집계본이 있으면 재사용.
|
||
- 글↔영상: `default_briefs.mjs` 가 정보형 롱폼 중 제목이 글 주제 키워드(시술 영역 라벨·안전·상담 등)와 겹치는 것 최대 3편을 brief.videos 로. 병원 소개·방문 안내는 영상을 붙이지 않는다. 워커 generate 단계는 기존 글이 있으면 재생성하지 않고 brief 의 영상만 frontmatter 에 덮어쓴다(`--regenerate` 로 재생성). data 단계 재실행 시 글·videos.json 보존.
|
||
- 카드 대체: PostCard 는 썸네일 → 히어로 → 첫 영상 → 건물 사진 → 병원 로고(`.thumb-logo`, contain) 순. 프레임워크 파비콘은 쓰지 않는다.
|
||
- 게이트가 잡은 것: 설명 영상 제목 "부작용은 없을까?" 가 BANNED_PHRASE 로 홈·영상 페이지에서 차단 → 수집 단계에서 같은 규칙으로 거르게 수정.
|
||
- 원진 결과: 채널 736편 · 설명형 롱폼 10 · 쇼츠 10 · 글 2편에 영상 3편씩(눈성형, 상담 질문), 나머지 4편은 로고 카드 · 헤더 로고·파비콘 = 원진 로고(`supporters/briefs/wonjin/logo-horizontal.svg`). https://supporters-wonjin.vercel.app 재배포. 뷰성형외과 회귀: 게이트 16/16, 빌드 오류 0.
|
||
- 남은 것: 홈페이지 이미지(전후 제외) 히어로·갤러리, 뉴스룸, 감사 재실행. 쇼츠 정리 답은 사람 입력.
|
||
|
||
### 11-11. 홈페이지 이미지 단계 (법 기준) · 2026-09-08
|
||
- haewon 지시: 전후 사진을 거르는 규칙은 의료법 등 관련 법규를 기준으로, 병원은 파트너·고객이므로 법에 걸리지 않는 범위에서 진행.
|
||
- 규칙 문서 `docs/INFINITH_Supporters_Image_Rules.md`: 의료법 56조 2항(2호 치료경험담, 4호 비교, 6호 수술 장면 노출, 7호 부작용 누락, 8호 과장, 14호 인증·보증), 의료광고 심의 기준의 전후 사진 조건(동일 조건·무보정·부작용 병기·환자 동의), 개인정보보호법·초상권을 이미지 유형별 규칙으로 대응. 자동 수집으로 조건을 확인할 수 없는 것(전후·사례·후기·모델·환자·비교·수상·인증·수술 장면·신체 실사)은 제외, 병원 서면 확인 후 사람이 넣는다. 법률 자문 아님, 변호사 확인 권고.
|
||
- `supporters/scripts/collect_images.mjs` + `img_process.py`(PIL): 근거 페이지 이미지 → 규칙 분류(의료진·시설·시술 도해·장비) → 다운로드 → 폭·비율·애니메이션·**글자 이미지 검사(흰 배경 평탄화 후 흰 픽셀 80% 이상 제외)** → 1600px JPEG → `public/img/{doctors,clinic,procedure,equipment}` + `src/data/images.json`(alt·캡션 "출처: 홈페이지 {페이지} ({캡처일})"·원본 URL). 신체 부위(가슴·힙·바디·지방) 페이지 실사는 파일명에 illu·step·diagram·circle 이 있을 때만.
|
||
- 워커 `images` 단계(youtube 다음): site.heroImage(가로 시설 사진)·buildingImage·insideGallery·clinicGallery·imageCredit, physicians[].image. `default_briefs.mjs` 가 글별 히어로 1 + 갤러리 최대 3(근거 페이지에서 나온 도해·장비, 병원 소개는 시설 사진). generate 단계의 기존 글 갱신이 hero·gallery·thumbnail 도 brief 기준으로 덮어쓴다.
|
||
- 원진 결과: 후보 427 → 저장 66장(의료진 17, 시설 9, 시술 40). 6편 전부 히어로 있음, 눈성형·상담 질문 글 영상 3편, 원장 17명 사진. 눈으로 확인한 것: 상담 장면·수술실 모니터링·코 수술 도해는 적합, 흰 배경 마케팅 문구 이미지(힙업 카피)는 1차에서 통과했다가 평탄화 순서 수정 후 제외. https://supporters-wonjin.vercel.app 재배포.
|
||
- 한계: 이미지 내용을 사람이 전수 확인하지는 않았다(파일명·alt·흰 배경 휴리스틱). 얼굴·신체 검출은 없으므로 병원 송부 전 사람이 갤러리를 한 번 훑는다. 뉴스룸·감사 재실행은 아직.
|
||
|
||
---
|
||
|
||
## 12. haewon 결정 반영과 제안 (2026-09-07 세션 2)
|
||
|
||
### 12-1. 결정된 것
|
||
| §9 항목 | 결정 |
|
||
|---|---|
|
||
| 9-2 입력 폼 위치 | **INFINITH 랜딩**. `/discovery/:id` 리포트 안에 "병원 확인 항목" 폼 |
|
||
| 검토 흐름 | **빌드를 다 한 뒤 클라이언트(병원)에 송부**. 자동 빌드는 승인 없이 끝까지 돌고, 미리보기(noindex)를 보낸 뒤 병원이 검토·승인 입력 |
|
||
| 9-5 생성 모델 | **GPT-4 계열** (`OPENAI_API_KEY` 있음). 단가 상한은 첫 배치 실측 후 정함 |
|
||
| 9-3 법적 주체 | 리서치 후 제안 → §12-2 |
|
||
| 9-6 워커·배포 | 추천 → §12-3 |
|
||
| 9-1 탭 제거 · 9-4 원진성형외과 · 9-5 $10 · 9-6 워커 위치(README 추천) | **결정됨 2026-09-07** (§11-9) |
|
||
|
||
### 12-2. 검토 승인의 법적 책임 주체 · 제안
|
||
근거 조문을 원문으로 확인한 결과다(법률 자문이 아니며, 계약 전 변호사 확인을 권한다).
|
||
|
||
**사실 1. 의료광고는 의료인등만 할 수 있다.** 의료법 제56조 제1항: "의료기관 개설자, 의료기관의 장 또는 의료인(의료인등)이 아닌 자는 의료에 관한 광고를 하지 못한다." 서포터즈 사이트는 병원의 지원(경제적 이해관계)을 받아 의료행위·의료기관 정보를 알리므로 의료광고로 볼 가능성이 높다. 따라서 **광고의 주체(법적 책임 주체)는 의료기관 개설자(뷰성형외과 대표원장)이고, AI오투오는 제작·운영 대행**이다. AI오투오가 자기 명의로 의료광고 주체가 되는 구조는 성립하지 않는다.
|
||
|
||
**사실 2. 금지 유형이 사이트 규칙과 일치한다.** 제56조 제2항: 2호 치료경험담, 4호 다른 의료인과의 비교, 7호 심각한 부작용 등 중요 정보 누락, 8호 객관적 사실 과장, 14호 인증·추천 표현. 이미 §3-8 규칙과 게이트가 막고 있다. 새로 볼 것은 **10호 "기사 또는 전문가의 의견 형태로 표현되는 광고"**다. 서포터즈 글이 기사형·전문가 의견형으로 읽히면 이 호에 걸릴 수 있으므로, 광고(병원 지원)임을 숨기지 않는 표시가 방어선이다.
|
||
|
||
**사실 3. 사전심의는 매체 기준이다.** 제57조 제1항: 신문·인터넷신문, 옥외광고물, 전광판, 대통령령이 정하는 인터넷 매체(앱 포함), 그 밖의 광고매체. 시행령 기준은 전년도 말 직전 3개월 일일 평균 이용자 10만 명 이상인 인터넷 매체·SNS. **자체 도메인의 신규 서포터즈 사이트는 이 기준에 들지 않아 법정 사전심의 의무는 없다.** 그러나 2트랙의 **네이버 블로그 재작성본은 10만 명 이상 매체라 게시물별 사전심의 대상**이다. 심의 신청은 의료기관 명의로 한다.
|
||
|
||
**사실 4. 경제적 이해관계 표시.** 추천·보증 심사지침(2024-12-01 시행 개정): 금전 지원·할인·협찬을 소비자가 쉽게 알아볼 수 있게, 게시물 제목 또는 첫 부분에, 같은 언어로, 조건부 표현 없이 표시. 뷰성형외과는 2026-07-12 공정위로부터 수술비 할인 대가를 숨긴 후기 광고로 시정명령·공표명령을 받았다. 같은 유형의 위반이 재발하면 가중된다.
|
||
|
||
**제안: 3층 책임 구조**
|
||
| 층 | 책임 주체 | 화면·기록 |
|
||
|---|---|---|
|
||
| 의료 내용 | 의료기관 개설자(대표원장). 글별 의학 검토는 담당 원장 | 글 하단 "의학 검토 {원장} ({일}) · 게시 승인 {개설자} ({일})". 승인 기록(승인자·직함·일시·글 버전 해시)을 DB에 남긴다. **자필 서명은 불필요**하고 승인 기록이 근거가 된다. 계약서에 "의료광고 주체는 의료기관 개설자, AI오투오는 제작·운영 대행, 법령·심의 준수 확인은 병원" 조항 |
|
||
| 편집·사실 확인·정정 | AI오투오 편집 책임자(안성민) | 현행 ReviewBox·/corrections 유지 |
|
||
| 경제적 이해관계 표시 | 병원(광고주)과 AI오투오(매체 운영) 공동 | **글 첫 부분에 고지 추가**(현행은 하단만). 문구 예: "이 글은 뷰성형외과의 지원(광고비)을 받아 뷰 서포터즈가 작성했습니다." 홈·소개에도 같은 문장 |
|
||
|
||
**검토 흐름(haewon 결정 반영)**: 자동 빌드 완주 → noindex 미리보기 링크 송부 → 병원이 §6 입력 + 글별 검토자·검토일 + 개설자 게시 승인 → 승인된 글만 색인 허용 빌드(`PUBLIC_INDEXABLE=true`). 승인 전 글은 미리보기에서 "검토 대기"로만 보인다. 네이버 트랙은 여기에 의료광고심의위원회 심의를 한 단계 더 둔다.
|
||
|
||
**코드로 옮길 것**: (1) 고지 상단 배치를 §3-8 규칙에 추가하고 게이트에 "글 첫 화면에 지원 고지 문장 존재" 검사 추가. (2) frontmatter에 `approvedBy`·`approvedAt`(개설자 승인) 필드 추가, 승인 없으면 색인 허용 빌드에서 제외. (3) 56조 2항 10호 대응으로 "기자·전문가 화법" 금칙(「본지」「기자」「전문가에 따르면」) 추가.
|
||
|
||
### 12-3. 워커 위치·배포 방식 · 추천
|
||
**부하**: 근거 수집 3분(220페이지) + 유튜브 집계 2분 + 뉴스 1분 + GPT-4 글 10~20편 5~20분 + astro build·게이트 30초 + Vercel 배포 1분 = **10~30분/병원**. Supabase Edge Function(150초)은 불가. Vercel Functions는 Hobby 300초 상한, Pro 800초(1,800초 베타).
|
||
|
||
| 안 | 장점 | 단점 |
|
||
|---|---|---|
|
||
| A. Vercel Functions(Pro) + 단계 분할 + Vercel Cron 폴링 | 인프라 추가 없음 | 단계마다 800초 안에 끝내야 하고 상태 머신·재시도를 직접 만든다. 함수 안에서 `astro build`·의존성 설치가 부적합 |
|
||
| B. Inngest (무료 5만 run/월, 스텝 기반) | 재시도·관측 내장, Vercel 연동 | 각 스텝이 Vercel 함수로 실행되므로 A와 같은 시간·환경 제약 |
|
||
| **C. Trigger.dev v3 (추천)** | 전용 컴퓨트라 타임아웃 없음, Node 22에서 `npm ci`·`astro build`·Vercel API 호출을 한 태스크에서 순차 실행, 로컬 개발 도구 좋음, 오픈소스 셀프호스트 가능. 무료 1,500 run/월(월 빌드 수십 건이면 충분), 유료 $10/월~ | 서비스 하나 추가. 태스크 안에서 템플릿 의존성 설치가 되는지 첫 구현에서 확인 |
|
||
| D. 자체 Node 워커(VPS) + Supabase 큐 폴링 | 완전 통제 | 서버 운영·모니터링 부담. 빌드 수가 적은 지금 단계엔 과함 |
|
||
|
||
**추천 구조**: Trigger.dev 태스크 `build-supporters(clinicId, url)` 하나가 9단계를 순서대로 실행하고, 단계마다 Supabase `supporter_builds`(id·단계·상태·로그·산출 경로·미리보기 URL)를 갱신한다. INFINITH 랜딩은 이 테이블을 폴링(또는 Supabase Realtime)해 진행 상태를 보여준다. 트리거는 `discovery_leads` insert → Supabase Database Webhook → Trigger.dev 이벤트.
|
||
|
||
**배포**: 병원당 Vercel 프로젝트 `supporters-<clinicId>` (Vercel Multi-Project Platforms 패턴). 워커가 `astro build` + 게이트를 통과한 `dist/`를 Vercel Deployments API로 **prebuilt 업로드**한다(Vercel 쪽 빌드 없음, 빠르고 실패 지점이 적다). 환경변수 `SITE_URL`·`PUBLIC_INDEXABLE=false`, `X-Robots-Tag: noindex`는 vercel.json에 이미 있다. 도메인 확정 시 alias만 추가. 단일 프로젝트에 `/<id>/` 경로로 묶는 방식은 canonical·robots·sitemap이 병원별로 분리되지 않아 비추천.
|
||
|
||
**입력 폼(INFINITH 랜딩)**: `/discovery/:id` 안 "병원 확인 항목" 탭 = §6 9항목 + 글별 검토자·검토일·개설자 승인. 저장 테이블 `supporter_inputs`(clinicId·항목·값·입력자·일시). 저장 시 데이터 파일(factSheet·authors·site·글 frontmatter)을 재생성하고 같은 태스크로 재빌드·재배포한다. 코드 수정 없이 데이터만으로 검토 완료·스키마가 켜지는 §10 완료 기준과 맞는다.
|
||
|
||
**GPT-4 단가**: 글 1편 = 근거 컨텍스트 입력 약 6~10K 토큰 + 출력 약 3K 토큰. 모델은 `gpt-4.1` 또는 `gpt-4o` 중 고르며, 첫 배치 10편을 돌려 편당 비용을 실측한 뒤 상한(예: 병원당 첫 배치 총액)을 정한다. 회귀 기준은 뷰성형외과 18편(같은 문항·같은 근거로 생성 → 게이트 통과 + 세 줄 요약·표·FAQ 규격).
|