fix(supporters): v3 룩앤필 복원, 텍스트만 고객용으로 유지

- 홈 구조·영어 세리프 헤딩·아이브로우·통계 블록을 v3 그대로 되돌림 (주제 카드 섹션 제거)
- 통계 3칸은 답한 질문 수 / 원장 설명 영상 / 강남언니 후기로 숫자 유지, 설명만 고객 문장
- about·editorial·posts·clinic 상단 제목을 v3 방식(영어 세리프 h1)으로 복원
- 글 상세 아이브로우 "D · 시술 정보" 복원 (QB 번호만 제외)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Haewon Kam 2026-09-07 09:00:53 +09:00
parent 24b8be0f3d
commit 32e050a501
13 changed files with 23 additions and 46 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 KiB

After

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 KiB

After

Width:  |  Height:  |  Size: 543 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 826 KiB

After

Width:  |  Height:  |  Size: 827 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 KiB

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

After

Width:  |  Height:  |  Size: 194 KiB

View File

@ -6,7 +6,7 @@ const ld = { '@type': 'AboutPage', '@id': `${site}/about#page`, name: '이 사
---
<Base title="이 사이트에 대해" description="뷰 서포터즈는 뷰성형외과를 알아보는 분들의 질문에 원장 영상과 공개 자료를 근거로 답하는 곳입니다. 누가 쓰고 누가 감수하는지, 무엇을 싣지 않는지, 병원과의 관계를 밝힙니다." jsonLd={ld}>
<article class="wrap" style="padding-bottom:4rem">
<header class="article-head"><div class="eyebrow">소개</div><h1>이 사이트에 대해</h1><p style="color:var(--slate-600);margin-top:0.6rem">누가 쓰는지, 무엇을 근거로 하는지, 무엇을 싣지 않는지.</p></header>
<header class="article-head"><div class="eyebrow">About</div><h1 class="serif">About This Site</h1><p style="color:var(--slate-600);margin-top:0.6rem">누가 쓰는지, 무엇을 근거로 하는지, 무엇을 싣지 않는지.</p></header>
<h2>어떤 곳인가요</h2>
<p>뷰 서포터즈는 {fact.shortName}를 알아보는 분들이 실제로 묻는 질문에 답하는 곳입니다. 병원 홈페이지가 병원을 소개한다면, 이곳은 "가기 전에 뭘 알아야 하지?", "이 수술은 어떻게 진행되지?", "후기는 어디서 보지?" 같은 환자 쪽 질문에서 출발합니다.</p>

View File

@ -9,7 +9,7 @@ const ld = [clinicSchema(site), physicianSchema('dr-choi')];
---
<Base title="뷰성형외과 기본 정보" description="뷰성형외과의원의 주소·전화·진료시간·층별 구성·진료과·공개 이력을 한 곳에 정리했습니다. 방문 전에 확인하세요." jsonLd={ld}>
<article class="wrap" style="padding-bottom:4rem">
<header class="article-head"><div class="eyebrow">병원 정보</div><h1>뷰성형외과 기본 정보</h1><p style="color:var(--slate-600);margin-top:0.6rem">주소, 전화, 진료시간, 층별 안내, 의료진을 한 곳에 모았습니다. 표기는 공식 홈페이지를 따르고, 홈페이지에 없는 항목은 출처를 따로 적습니다.</p></header>
<header class="article-head"><div class="eyebrow">Fact Sheet</div><h1 class="serif">Fact Sheet</h1><p style="color:var(--slate-600);margin-top:0.6rem"><strong style="color:var(--primary-900)">뷰성형외과 기본 정보.</strong> 주소, 전화, 진료시간, 층별 안내, 의료진을 한 곳에 모았습니다. 표기는 공식 홈페이지를 따르고, 홈페이지에 없는 항목은 출처를 따로 적습니다.</p></header>
<FactBlock />
<h2>진료시간</h2>
<div class="table-wrap"><table><thead><tr><th>요일</th><th>진료</th></tr></thead><tbody>{fact.hours.rows.map((r) => <tr><td>{r.days}</td><td>{r.open ? `${r.open} ~ ${r.close}` : r.note}</td></tr>)}</tbody></table></div>

View File

@ -7,7 +7,7 @@ const ld = { '@type': 'WebPage', '@id': `${site}/editorial#page`, name: '편집
---
<Base title="편집 기준 (운영자용)" description="뷰 서포터즈 운영자용 편집 기준. 질문 뱅크, 글 구조, 원천 변환 규칙, 중복 콘텐츠 회피, 구조화 데이터, 발행 전 검사." jsonLd={ld} noindex>
<article class="wrap" style="padding-bottom:4rem">
<header class="article-head"><div class="eyebrow">운영자용</div><h1>편집 기준</h1><p style="color:var(--slate-600);margin-top:0.6rem">이 페이지는 병원 담당자, 서포터즈, INFINITH 운영진이 보는 문서입니다. 방문자에게 보이는 소개는 <a href="/about">이 사이트에 대해</a>에 따로 있습니다.</p></header>
<header class="article-head"><div class="eyebrow">Editorial Policy</div><h1 class="serif">Editorial Policy</h1><p style="color:var(--slate-600);margin-top:0.6rem">이 페이지는 병원 담당자, 서포터즈, INFINITH 운영진이 보는 문서입니다. 방문자에게 보이는 소개는 <a href="/about">이 사이트에 대해</a>에 따로 있습니다.</p></header>
<div class="notice">고객 화면에는 "AI가 인용하는 방식"이나 제작 원칙을 쓰지 않습니다. 방문자는 답을 보러 오지 제작 과정을 보러 오지 않습니다. 이 페이지의 내용은 이 페이지 밖으로 내보내지 않습니다.</div>
<h2>1. 왜 이 사이트인가</h2>

View File

@ -5,39 +5,28 @@ import PostCard from '../components/PostCard.astro';
import FactBlock from '../components/FactBlock.astro';
import VideoLite from '../components/VideoLite.astro';
import Gallery from '../components/Gallery.astro';
import { SITE_NAME, CATEGORY_LABELS, fact, clinicSchema } from '../lib';
import { SITE_NAME, fact, clinicSchema } from '../lib';
const posts = (await getCollection('posts')).sort((a, b) => b.data.dateModified.localeCompare(a.data.dateModified));
const site = Astro.site!.toString().replace(/\/$/, '');
const ld = [
{ '@type': 'WebSite', '@id': `${site}/#website`, name: SITE_NAME, url: site, inLanguage: 'ko', about: { '@id': `${fact.url}/#clinic` }, publisher: { '@type': 'Organization', name: SITE_NAME, url: site } },
clinicSchema(site),
];
// 고객이 고르는 주제. 글이 있는 카테고리만 보여 준다. 설명문은 환자 관점의 질문 예시다.
const TOPIC_HINT: Record<string, string> = {
A: '어떤 병원인지, 어떤 원장이 있는지',
B: '가는 길, 예약, 상담 당일 준비',
C: '병원과 원장을 고를 때 볼 것',
D: '수술 방법, 보형물, 회복 과정',
E: '마취, 수술 실명제, 응급 대비',
F: '가격 안내를 어디서 확인하는지',
G: '후기를 어디서 어떻게 읽을지',
};
const topics = Object.keys(CATEGORY_LABELS).map((c) => ({ key: c, label: CATEGORY_LABELS[c], hint: TOPIC_HINT[c], count: posts.filter((p) => p.data.category === c).length })).filter((t) => t.count > 0);
---
<Base title="뷰성형외과, 궁금한 것부터 답합니다" description="뷰성형외과(서울 강남 신논현역)를 알아보는 분들이 실제로 묻는 질문을 골라, 원장 설명 영상과 병원 공개 자료를 근거로 답합니다. 글마다 작성자와 원장 감수 여부를 밝힙니다." jsonLd={ld}>
<Base title="뷰성형외과를 알아보는 사람들의 질문에 먼저 답합니다" description="뷰성형외과(서울 강남 신논현역)를 알아보는 분들이 실제로 묻는 질문을 골라, 원장 설명 영상과 병원 공개 자료를 근거로 답합니다. 글마다 작성자와 원장 감수 여부를 밝힙니다." jsonLd={ld}>
<section class="hero-light">
<div class="blob a"></div><div class="blob b"></div>
<div class="wrap-wide inner">
<div>
<div class="eyebrow">뷰 서포터즈</div>
<h1>뷰성형외과,<br /><span class="accent">궁금한 것부터 답합니다.</span></h1>
<div class="eyebrow">View Supporters · Sample</div>
<h1>뷰성형외과를 알아보는 사람들의<br /><span class="accent">질문에 먼저 답합니다.</span></h1>
<p class="lede">{fact.shortName}는 {fact.founded}년 개원한 서울 강남 신논현역 인근 성형외과입니다. 이곳은 병원을 알아보는 분들이 실제로 묻는 질문을 골라, 원장 설명 영상과 병원이 공개한 자료를 근거로 답하는 곳입니다. 글마다 누가 썼고 원장 감수를 거쳤는지 밝힙니다.</p>
<div class="chips">
<span class="chip"><span class="dot"></span>{fact.founded}년 개원 · 신논현역 3번 출구 50m</span>
<span class="chip"><span class="dot"></span>원장 설명 영상 {fact.surfaces.youtube.videos}편을 근거로</span>
</div>
<div class="hero .actions" style="display:flex;gap:0.8rem;flex-wrap:wrap;margin-top:1.6rem">
<a class="btn primary" href="/posts">질문별 답 보기</a>
<a class="btn primary" href="/posts">전체 글 보기</a>
<a class="btn secondary" href="/clinic">병원 정보</a>
</div>
</div>
@ -47,41 +36,35 @@ const topics = Object.keys(CATEGORY_LABELS).map((c) => ({ key: c, label: CATEGOR
<section class="section dark">
<div class="wrap-wide">
<div class="sec-head"><div class="eyebrow" style="color:var(--purple-300)">주제별로 찾기</div><h2>무엇이 궁금하세요?</h2><p class="sub">병원에 가기 전에 알고 싶은 것을 주제별로 정리했습니다.</p></div>
<div class="grid">
{topics.map((t) => (
<a class="card topic" href={`/posts#cat-${t.key}`}>
<div class="cat">{t.count}편</div>
<h3>{t.label}</h3>
<p>{t.hint}</p>
</a>
))}
<div class="sec-head"><div class="eyebrow" style="color:var(--purple-300)">Why This Site</div><h2>Questions First</h2><p class="sub">병원에 가기 전에 알고 싶은 것부터 답합니다. 답은 원장이 직접 설명한 영상과 병원 공개 자료를 근거로 합니다.</p></div>
<div class="stats">
<div class="stat"><b>{posts.length}</b><span class="label">답한 질문</span><span class="desc">질문 하나에 글 하나. 첫 단락 "세 줄 요약"에 답을 먼저 쓰고, 그다음에 근거를 풉니다.</span></div>
<div class="stat"><b>{fact.surfaces.youtube.videos}</b><span class="label">원장 설명 영상</span><span class="desc">글에서 원장이 한 말은 영상을 함께 붙여 두어 직접 확인할 수 있습니다.</span></div>
<div class="stat"><b>{fact.surfaces.gangnamunni.reviews}</b><span class="label">강남언니 후기</span><span class="desc">후기는 어디서 몇 건을 볼 수 있는지만 안내합니다. 다른 환자의 경험담은 옮기지 않습니다.</span></div>
</div>
</div>
</section>
<section class="section light">
<div class="wrap-wide">
<div class="sec-head"><div class="row"><div><div class="eyebrow">최근 글</div><h2>최근에 답한 질문</h2><p class="sub">첫 단락 "세 줄 요약"에 답을 먼저 쓰고, 그다음에 근거를 풉니다.</p></div><a href="/posts">전체 보기</a></div></div>
<div class="sec-head"><div class="row"><div><div class="eyebrow">Latest</div><h2>Recent Answers</h2><p class="sub">최근에 답한 질문. 첫 단락 "세 줄 요약"만 읽어도 답을 알 수 있습니다.</p></div><a href="/posts">전체 보기</a></div></div>
<div class="grid">{posts.slice(0, 6).map((p) => <PostCard post={p} />)}</div>
</div>
</section>
<section class="section tint">
<div class="wrap-wide">
<div class="sec-head"><div class="eyebrow">원장 영상</div><h2>원장이 직접 설명합니다</h2><p class="sub">이 사이트의 글은 아래와 같은 원장 설명 영상을 근거로 씁니다. 원본을 그대로 재생할 수 있습니다.</p></div>
<div class="sec-head"><div class="eyebrow">From The Doctors</div><h2>Doctors Explain</h2><p class="sub">원장이 직접 설명하는 영상. 이 사이트의 글은 이런 영상을 근거로 씁니다.</p></div>
<div class="video-grid" style="grid-template-columns:repeat(auto-fill,minmax(300px,1fr))">
<VideoLite id="Nbemu6mL_uY" title="가장 VIEW다운 가치 : 안전과 신뢰의 약속" published="2026-05-19" compact />
<VideoLite id="_OZRSJIDWgs" title="스포르자가 또 방문한 이유, 모티바 프리저베 교육 현장" published="2026-08-20" compact />
<VideoLite id="xohC5C6aY70" title="모티바 프리저베는 수술 직후 만세가 가능하다?" published="2026-08-31" compact />
</div>
<p style="margin-top:1.2rem"><a href="/videos">가장 많이 본 영상 보기</a></p>
</div>
</section>
<section class="section light">
<div class="wrap-wide">
<div class="sec-head"><div class="eyebrow">병원 둘러보기</div><h2>건물 안은 이렇게 생겼습니다</h2><p class="sub">19층 자체 사옥. 상담 4~5층, 검진 지하 1층, 수술 11~14층, 입원 8·10층.</p></div>
<div class="sec-head"><div class="eyebrow">Inside</div><h2>Inside The Building</h2><p class="sub">19층 자체 사옥. 상담 4~5층, 검진 지하 1층, 수술 11~14층, 입원 8·10층.</p></div>
<Gallery cols={3} items={[
{ src: '/img/clinic/consult-1.jpg', alt: '뷰성형외과 4~5층 상담센터 대기 공간. 검은 소파와 밝은 조명', caption: '4~5F 상담센터' },
{ src: '/img/clinic/exam-1.jpg', alt: '뷰성형외과 지하 1층 검진센터 입구. Examination Center 간판', caption: 'B1F 검진센터' },
@ -93,22 +76,16 @@ const topics = Object.keys(CATEGORY_LABELS).map((c) => ({ key: c, label: CATEGOR
<p style="font-size:0.83rem;color:var(--slate-500);margin-top:-0.6rem">사진 출처: 뷰성형외과 공식 홈페이지 병원둘러보기</p>
</div>
</section>
<section class="section dark">
<div class="wrap-wide">
<div class="sec-head"><div class="eyebrow" style="color:var(--purple-300)">믿고 읽어도 되나요</div><h2>이 글들은 이렇게 만듭니다</h2><p class="sub">읽는 분이 판단할 수 있도록 세 가지를 항상 밝힙니다.</p></div>
<div class="sec-head"><div class="eyebrow" style="color:var(--purple-300)">Principles</div><h2>What We Do, What We Don't</h2><p class="sub">읽는 분이 판단할 수 있도록 세 가지를 지킵니다.</p></div>
<div class="grid">
<div class="card"><h3>원장이 감수합니다</h3><p>의학적인 내용은 뷰성형외과 담당 원장이 확인합니다. 감수가 끝난 글에는 감수 완료와 날짜를, 아직인 글에는 감수 예정을 표시합니다.</p></div>
<div class="card"><h3>근거를 보여 드립니다</h3><p>글마다 참고한 원장 영상과 병원 자료의 링크를 붙입니다. 원장이 한 말은 영상으로 직접 확인할 수 있습니다.</p></div>
<div class="card"><h3>과장하지 않습니다</h3><p>전후 사진, 다른 환자의 경험담, 효과를 보장하는 표현은 쓰지 않습니다. 이 사이트는 뷰성형외과의 지원을 받아 운영하며, 그 사실을 모든 글에 적습니다. <a href="/about">이 사이트에 대해</a></p></div>
<div class="card"><h3>합니다</h3><p>질문 하나에 글 하나. 첫 단락에 답을 먼저 씁니다. 의학적인 내용은 담당 원장이 감수하고, 감수가 끝난 글에는 날짜를, 아직인 글에는 감수 예정을 표시합니다.</p></div>
<div class="card"><h3>하지 않습니다</h3><p>전후 사진, 다른 환자의 경험담, 다른 병원과의 비교, 효과를 보장하는 표현. 후기는 강남언니·구글에서 몇 건을 볼 수 있는지와 링크만 안내합니다.</p></div>
<div class="card"><h3>밝힙니다</h3><p>누가 썼는지, 원장 감수를 거쳤는지, 무엇을 참고했는지, 그리고 이 사이트가 뷰성형외과의 지원을 받는다는 사실. <a href="/about">이 사이트에 대해</a></p></div>
</div>
</div>
</section>
<section class="section tint"><div class="wrap-wide"><div class="sec-head"><div class="eyebrow">병원 정보</div><h2>주소·전화·진료시간</h2><p class="sub">방문 전에 확인하세요. 진료시간은 바뀔 수 있으니 전화로 한 번 더 확인을 권합니다.</p></div><FactBlock /></div></section>
<section class="section tint"><div class="wrap-wide"><div class="sec-head"><div class="eyebrow">Fact Sheet</div><h2>Clinic Facts</h2><p class="sub">주소·전화·진료시간. 방문 전에 전화로 한 번 더 확인을 권합니다.</p></div><FactBlock /></div></section>
</Base>
<style>
.card.topic { text-decoration: none; color: inherit; }
.card.topic:hover { text-decoration: none; }
.card.topic h3 { color: var(--primary-900); }
</style>

View File

@ -52,7 +52,7 @@ if (d.faq.length) graph.push({ '@type': 'FAQPage', '@id': `${url}#faq`, mainEnti
<Base title={d.title} description={d.description} jsonLd={graph} type="article" ogImage={d.hero?.src}>
<article class="wrap" style="padding-bottom:4rem" data-qb={d.qbIds.join(',')}>
<header class="article-head">
<div class="eyebrow">{CATEGORY_LABELS[d.category]}</div>
<div class="eyebrow">{d.category} · {CATEGORY_LABELS[d.category]}</div>
<h1>{d.title}</h1>
<div class="meta">
<span>작성 {supporter(d.author).name}</span>

View File

@ -10,7 +10,7 @@ const ld = { '@type': 'CollectionPage', '@id': `${site}/posts#page`, name: '전
---
<Base title="전체 글" description="뷰성형외과에 대해 사람들이 묻는 질문에 서포터즈가 먼저 답한 글 목록. 카테고리별로 정리했습니다." jsonLd={ld}>
<div class="wrap-wide" style="padding-bottom:4rem">
<header class="article-head"><div class="eyebrow">전체 글</div><h1>질문별로 답한 글</h1><p style="color:var(--slate-600);margin-top:0.6rem">궁금한 주제를 골라 보세요. 글 하나가 질문 하나에 답합니다.</p></header>
<header class="article-head"><div class="eyebrow">Archive</div><h1 class="serif">All Answers</h1><p style="color:var(--slate-600);margin-top:0.6rem">궁금한 주제를 골라 보세요. 글 하나가 질문 하나에 답합니다.</p></header>
{cats.map((c) => {
const list = posts.filter((p) => p.data.category === c);
if (!list.length) return null;