358 lines
47 KiB
Markdown
358 lines
47 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.
|
||
- 남은 것: 홈페이지 이미지(전후 제외) 히어로·갤러리, 뉴스룸, 감사 재실행. 쇼츠 정리 답은 사람 입력.
|
||
|
||
---
|
||
|
||
## 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 규격).
|