From 9b717dbcfcae8095ed8da061f438163188003a26 Mon Sep 17 00:00:00 2001 From: Haewon Kam Date: Mon, 14 Sep 2026 16:01:44 +0900 Subject: [PATCH] =?UTF-8?q?fix(worker):=20=EB=B9=8C=EB=93=9C=EB=A7=88?= =?UTF-8?q?=EB=8B=A4=20=ED=85=9C=ED=94=8C=EB=A6=BF=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A5=BC=20=EA=B0=B1=EC=8B=A0=20=C2=B7=20?= =?UTF-8?q?=EB=B7=B0=20=EB=84=A4=EC=9D=B4=EB=B2=84=20=EC=86=8C=EC=9C=A0=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=EA=B0=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 템플릿은 data 단계에서만 복사돼, --from build 로 돌리면 그 사이에 고친 화면 코드가 기존 병원 폴더에 닿지 않았다. 오늘 두 건이 이 이유로 배포되지 않았다. - 검색엔진 소유 확인 메타: site.json 에 값이 들어갔는데 화면에 안 나왔다 - 회복 일정 플래너 계측(plan_procedure_select·plan_result·plan_save): 세 사이트 모두 없었다 refreshTemplateCode() 가 build 단계에서 화면 코드만 다시 덮는다. src/layouts·components·pages·styles·lib 과 lib.ts·content.config.ts 가 대상이고, 병원 데이터·글·이미지는 건드리지 않는다. 병원별로 갈리는 astro.config.mjs·vercel.json 의 치환값, 구조 기준선, home_text 도 덮지 않는다. 내용이 같은 파일은 건너뛴다. 뷰 브리프에 네이버 서치어드바이저 소유 확인 값을 넣었다(viewpl.webforai.kr 용). 사이트마다 값이 달라 옮겨 쓰면 확인되지 않는다는 것을 주석에 적었다. 검증: 세 사이트 재배포 후 뷰에 소유 확인 메타가 나오고 다른 두 곳에는 안 나온다. 플래너 계측은 세 곳 모두 번들에 들어갔다. Co-Authored-By: Claude Opus 5 (1M context) --- supporters/briefs/viewclinic/clinic.json | 6 +++-- workers/supporters-build/run.mjs | 33 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/supporters/briefs/viewclinic/clinic.json b/supporters/briefs/viewclinic/clinic.json index 5da95b6..ac50036 100644 --- a/supporters/briefs/viewclinic/clinic.json +++ b/supporters/briefs/viewclinic/clinic.json @@ -23,7 +23,9 @@ "alt": "뷰성형외과 건물 외관", "width": 886, "height": 885 - } + }, + "naverSiteVerification": "e47011473eef74d7b2c4f20e93f97a889cb699cc" }, - "_siteNote": "홈 히어로가 가슴 라인 일러스트로 잡혀 있었고 건물 사진의 alt 도 '가슴확대 시설 사진'으로 잘못 붙어 있었다. 건물 외관으로 고정한다." + "_siteNote": "홈 히어로가 가슴 라인 일러스트로 잡혀 있었고 건물 사진의 alt 도 '가슴확대 시설 사진'으로 잘못 붙어 있었다. 건물 외관으로 고정한다.", + "_verifyNote": "네이버 서치어드바이저 소유 확인 값(2026-09-14 발급, viewpl.webforai.kr 용). 사이트마다 값이 다르므로 다른 병원에 옮겨 쓰면 확인되지 않는다. 구글은 webforai.kr 도메인 속성을 DNS TXT 로 확인해 서브도메인 전부가 함께 확인된다." } diff --git a/workers/supporters-build/run.mjs b/workers/supporters-build/run.mjs index cbccbf0..d125d9e 100644 --- a/workers/supporters-build/run.mjs +++ b/workers/supporters-build/run.mjs @@ -55,6 +55,38 @@ function applySiteUrl() { return liveUrl; } +// 템플릿의 코드 파일을 빌드 폴더에 다시 덮는다. 병원 데이터·글·이미지는 건드리지 않는다. +// 템플릿은 data 단계에서만 복사되므로, --from build 처럼 중간부터 돌리면 그 사이에 고친 화면 코드가 +// 기존 병원 폴더에 닿지 않는다. 2026-09-14 에 소유 확인 메타와 플래너 계측이 이 이유로 배포되지 않았다. +// 병원별로 갈리는 것(astro.config.mjs·vercel.json 의 치환값, 구조 기준선, home_text)은 덮지 않는다. +const CODE_DIRS = ['src/layouts', 'src/components', 'src/pages', 'src/styles', 'src/lib']; +const CODE_FILES = ['src/lib.ts', 'src/content.config.ts']; +function refreshTemplateCode() { + if (!existsSync(TEMPLATE)) return '템플릿 없음'; + let n = 0; + const copyIfDiff = (rel) => { + const from = join(TEMPLATE, rel), to = join(SITE, rel); + if (!existsSync(from)) return; + if (existsSync(to) && readFileSync(from).equals(readFileSync(to))) return; + mkdirSync(dirname(to), { recursive: true }); + cpSync(from, to, { recursive: true }); + n += 1; + }; + for (const d of CODE_DIRS) { + const from = join(TEMPLATE, d); + if (!existsSync(from)) continue; + const walk = (sub) => { + for (const e of readdirSync(join(from, sub), { withFileTypes: true })) { + const rel = join(d, sub, e.name); + if (e.isDirectory()) walk(join(sub, e.name)); else copyIfDiff(rel); + } + }; + walk(''); + } + for (const f of CODE_FILES) copyIfDiff(f); + return n ? `화면 코드 ${n}개 갱신` : '화면 코드 최신'; +} + // ---------- 상태 ---------- const statusPath = join(WORK, 'status.json'); const status = existsSync(statusPath) ? JSON.parse(readFileSync(statusPath, 'utf8')) : { clinic, url, status: 'queued', phases: [], posts: [], createdAt: new Date().toISOString() }; @@ -456,6 +488,7 @@ await phase('heroes', () => { await phase('build', () => { // 주소·색인 설정을 먼저 적용한다. 원격 빌드가 이 값으로 canonical·사이트맵을 만든다. applySiteUrl(); + const refreshed = refreshTemplateCode(); const inst = run('npm', ['ci', '--no-audit', '--no-fund'], { cwd: SITE }); if (!inst.ok) throw new Error(`npm ci 실패\n${tail(inst.out)}`); const b = run('npx', ['astro', 'build'], { cwd: SITE });