diff --git a/docs/DEVELOPMENT_DIRECTION.md b/docs/DEVELOPMENT_DIRECTION.md deleted file mode 100644 index 04c1a09..0000000 --- a/docs/DEVELOPMENT_DIRECTION.md +++ /dev/null @@ -1,214 +0,0 @@ -# Web4AI 개발 방향 — v19 설계서와 현재 구현 비교 - -> 기준일: 2026-08-31 -> 비교 대상: `Web4AI_SW설계서_및_개발일정_v19.pdf`(22쪽)와 이 저장소의 현재 코드·문서 -> 목적: 설계서를 그대로 복제하는 것이 아니라, 현재 제품에서 **유지할 결정**, **방향을 다시 정할 결정**, **추가할 개발 항목**을 구분한다. - -설계서 표지는 파일명과 달리 `v18 · 2026.08.30`으로 표기되어 있다. 아래에서는 전달받은 파일을 편의상 “v19 설계서”라고 부르되, 계약·일정 확정 전 문서 버전부터 확인해야 한다. - ---- - -## 1. 결론 - -현재 프로젝트는 설계서 전체의 축소판이 아니라, 설계서의 **Site AEO(A1~A8) 일부를 소상공인용 제품으로 먼저 구현한 별도 MVP**에 가깝다. - -- 현재 강점은 `사업장 확인 → 허용된 소스 수집 → fact 승인 → 근거 기반 문구 생성 → 정적 HTML 발행 → IndexNow`가 실제 코드와 테스트로 연결되어 있다는 점이다. -- 가장 큰 공백은 **Brand AEO 전체(B1~B9)**, **규제 검사(A4)**, **소유권 검증(A1)**, **원본 변경·AI 크롤러 재방문 추적(A9)**이다. -- 가장 큰 방향 충돌은 **타겟 업종**, **Playwright 크롤링**, **배포 도메인**, **마이크로서비스·공통 인프라**다. 이 항목은 “미구현”으로 보고 바로 만들면 안 되고 제품·법무·운영 결정을 먼저 내려야 한다. -- 권장 방향은 현 구조를 버리고 5계층/2엔진으로 즉시 재작성하는 것이 아니다. 현재 시스템을 **Site AEO MVP 기준선**으로 유지하고, Brand AEO를 경계가 분명한 모듈로 붙인 뒤 부하와 조직 규모가 실제 분리를 요구할 때 서비스로 분리한다. - -### 현재 범위의 대략적인 위치 - -| 설계서 영역 | 현재 판단 | -|---|---| -| Site AEO A1~A9 | **부분 구현** — A3·A5·A6·A7 일부와 A8 중심 | -| Brand AEO B1~B9 | **미구현** — 준비도 자체 점수만 있으며 실제 AI 응답 측정은 없음 | -| 운영 콘솔 15개 화면 | **부분 구현** — 사업장·빌더·지역정보·SEO/AEO 준비도 중심 | -| 계약 A~G / BFF | **미구현** — 화면이 FastAPI 를 직접 호출 (BFF 없음) | -| 25테이블 append-only Fact Graph | **다른 모델로 구현** — 승인 후보/노출값 중심의 key-value fact 모델 | -| 8개 스프린트 일정 | **현재 코드에 바로 적용 불가** — 이미 구현된 것과 방향 충돌 항목이 섞여 있어 재산정 필요 | - ---- - -## 2. 방향이 다른 부분 - -아래는 단순히 덜 만든 기능이 아니라, 설계서와 현재 프로젝트가 서로 다른 결정을 내린 항목이다. - -| 항목 | v19 설계서 | 현재 프로젝트 | 권장 판단 | -|---|---|---|---| -| 제품 범위 | Site AEO + Brand AEO 이원 플랫폼 | 상호명 기반 소상공인 정적 홈페이지 생성·발행 | 현재 제품을 Site AEO MVP로 명시하고 Brand AEO 확장 여부를 별도 마일스톤으로 승인 | -| 1차 업종 | 숙박, 법무법인, 성형외과 | 숙박, 카페, 음식점, 관광체험 | **반드시 사업 결정 필요.** 법률·의료를 넣으면 데이터 스키마뿐 아니라 규제·승인·감사 체계가 선행되어야 함 | -| 입력 방식 | 고객 원본 사이트를 depth 3·최대 200페이지 크롤 | 공식 API, 사용자 확정 URL, 정적 HTML; 플랫폼 우회 수집 금지 | 현재의 출처·동의·robots 원칙 유지. 대규모 원본 사이트 수집은 별도 제품 모드로 분리 | -| 동적 크롤링 | 정적 우선, Playwright 폴백 | 봇 탐지 우회로 변질될 수 있어 HeadlessAdapter 미등록·금지 | 포괄적인 Playwright 폴백은 채택하지 않음. 소유권이 검증된 고객 도메인에만 허용할지 법무·보안 결정 후 제한적으로 검토 | -| 발행 도메인 | 고객 도메인 서브패스 권장, 서브도메인 차선 | 기본 `web4ai.o2osolution.ai/s/`, custom domain 경로 미완성 | 설계서 방향이 검색 권위 측면에서 더 적합. 고객 도메인 연결·소유권 검증을 우선 과제로 추가 | -| 백엔드 구조 | Site/Brand 엔진, BFF, 엔진별 DB 분리 | 코드 한 벌 + 진입점 둘(:9800 사장님 / :9801 내부), 단일 PostgreSQL | 청중별 분리는 포트로 끝냈다. 엔진별 물리 분리는 트래픽·팀 소유권 근거가 생긴 뒤 수행 | -| 작업 인프라 | Temporal, Redis, Celery 등 공통 인프라 | PostgreSQL 잡 큐 + lease + dead-letter | 현재 DB 큐 유지. 동일 책임의 인프라를 중복 도입하지 않음. 장기 워크플로 보상·분산 추적 요구가 확인될 때 Temporal 재평가 | -| Fact Graph | 엔티티·predicate·snapshot, append-only | 업종 스키마 기반 key-value fact, 후보/노출/이력 상태 | 현재 모델은 발행 안전성에 적합. Brand 측정 재현성에 필요한 snapshot과 entity 관계만 점진적으로 확장 | -| 점수 | Site AEO Score + 실제 4개 AI 엔진 기반 AVS | 내부 데이터 기반 SEO/AEO **준비도** 점수 | 이름과 의미를 분리 유지. 실제 측정 전 현재 점수를 AVS/가시성 점수라고 부르지 않음 | -| 운영 사용자 | Reviewer/Owner 권한과 15개 통합 화면 | USER/OWNER/DEVELOPER, 사장님 앱(:3000)과 내부 콘솔(:3002)이 갈려 있다 | 규제 기능 도입 전 Reviewer 역할·서버 계산 `allowed_actions` 추가 | -| 이미지 | 원본 사진·영상이 EEAT 근거 | 이미지 호스팅을 현재 non-goal로 두고 외부 URL 사용 | 저작권 결론과 소유자 업로드 저장소가 먼저. 크롤 이미지 재게시를 전제로 개발하지 않음 | - ---- - -## 3. 설계서 항목별 구현 차이 - -### 3-1. Site AEO A1~A9 - -| 단계 | 현재 상태 | 코드 근거 | 추가할 것 | -|---|---|---|---| -| A1 사이트 진단·소유권 검증 | **일부** | 사업장 동일 업소 확인과 `verified_at`, SEO 진단은 있으나 DNS TXT/meta/well-known 검증은 없음 | 도메인 소유권 challenge, 만료·재검증, 발행 차단 정책 | -| A2 크롤·추출 | **일부** | collector registry, `StaticHtmlAdapter`, TourAPI, 네이버 장소 조회, 사용자 확정 링크 | 허용 도메인용 crawl run/document 기록, 원본 hash, 제한·재시도·수집 보고서 | -| A3 Fact Graph | **부분 구현** | `facts`, 업종 스키마, 출처·신뢰도·상태 전이, 승인 후보 모델 | source URL의 selector/snippet, entity 관계, 측정용 불변 snapshot | -| A4 규제·과장 검사 | **기초만 존재** | 생성 문구의 과장·근거 없는 숫자/시설 검사는 있으나 업종별 법규 3단 분류와 승인 감사는 없음 | 외부화된 규칙, SAFE/REVIEW/BLOCK 판정, 규칙 버전, 근거 snippet, Reviewer 승인 로그 | -| A5 AEO 콘텐츠 생성 | **구현** | Gemini Text, 소개문·meta·FAQ, 근거 fact key, ground check | 질문은행과 생성 페이지의 연결, 질문형 콘텐츠 단위의 버저닝 | -| A6 JSON-LD | **구현** | 업종별 JSON-LD, FAQPage, Breadcrumb, WebPage, sameAs | 법률·의료 도입 시 타입·자격·저자 스키마 확장 | -| A7 3-way 일치성 | **부분 구현** | JSON-LD↔표시 텍스트 검증, 생성문↔fact 근거 검사, publish gate | 원본↔발행본 SimHash 중복도, 모든 사실 문장의 fact ID 역참조 보고서 | -| A8 배포 | **대부분 구현** | 프리렌더 정적 HTML, canonical, sitemap, robots, llms.txt, IndexNow, nginx/Azure 경로 | 고객 도메인 서브패스·서브도메인 연결, TLS/DNS 자동화, Search Console 제출 자동화 여부 | -| A9 모니터링·변경 감지 | **미구현** | `AI_CHECK` enum 만 있고 worker handler·보고 모듈 없음. 표(`ai_check_results`)는 한 번도 안 써서 마이그레이션 0006 이 뗐다 — 붙일 때 다시 만든다 | CDN 크롤러 로그 수집, 원본 hash 비교, fact 만료/재검토, 재생성 큐 | - -### 3-2. Brand AEO B1~B9 - -현재 `seo_audit.py`의 점수는 “발행 준비도”다. 설계서의 Brand AEO처럼 ChatGPT·Gemini·Claude·Perplexity 응답을 정기 호출하여 브랜드 언급·인용·순위·사실성을 측정하지 않는다. - -필요한 기능은 다음 순서가 적절하다. - -1. **B1 질문은행**: 업종×지역×의도 질문, 버전, 활성 세트, 고객 편집 이력 -2. **B2 측정 스케줄**: 주기, 엔진, 반복 횟수, 비용 상한, 중지 조건 -3. **B3~B4 엔진 어댑터와 원문 보존**: 모델·버전·프롬프트·응답·citation 정규화 -4. **B5 분석**: 브랜드 alias 언급, 인용 URL, 추천 위치, 감성, fact snapshot 대조 -5. **B8 이원 점수**: 원계열, 반복 평균, 신뢰구간, MA4를 모두 보존하고 준비도 점수와 별도 표시 -6. **B6~B7 개선 루프**: EEAT 결손과 외부 인용원을 제안하되, 자동 발행하지 않고 fact 확인/A4/A7을 재통과 -7. **B9 리포트**: 주간·월간 리포트, 모델 교체 마커, 비용과 데이터 결손 표시 - -100문항×4엔진×3회라는 설계서 기본값은 테넌트당 주 1,200회 호출이다. 현재 제품 원가 상한인 **사이트당 약 $1**과 충돌할 가능성이 높으므로, 구현 전 모델별 실측 단가와 파일럿 질문 수를 다시 계산해야 한다. 초기에는 10~20개 핵심 질문, 1~2개 엔진, 반복 3회로 시작하고 통계적 유효성과 비용을 함께 측정하는 편이 안전하다. - -### 3-3. 콘솔·계약·데이터 - -- 내부 콘솔(`admin/frontend`)에는 사업장 목록/상세, 지역 콘텐츠, SEO 진단이 있고 빌더는 사장님 앱(`solution/frontend`)에 있다. 설계서의 질문 빌더·규제 승인·AI 퍼포먼스·랭킹·인용출처·정기 리포트 화면은 없다. -- 화면이 API 를 직접 호출한다. 설계서의 BFF, 서비스 JWT 교환, 섹션별 부분 실패, 계약 A~G는 없다. -- DB에는 현재 17개 ORM 모델이 있으며 설계서의 `document`, `predicate_def`, `entity`, `fact_snapshot`, `compliance_rule`, `review`, `publication_question`, `index_state`, `regeneration_request`, `event_outbox`, `audit_log` 등에 해당하는 완성 모델은 없다. -- 현재 fact는 수정 잠금과 후보 이력을 보존하지만, 설계서가 요구하는 전체 append-only 불변식·스냅샷 재현성 모델과 같지는 않다. - -계약 A~G를 한 번에 33개 REST/7개 이벤트로 만드는 것보다, 먼저 아래 세 계약만 버전 고정하는 것을 권장한다. - -1. `FactSnapshot`: 측정 당시의 발행 사실을 재현할 수 있는 읽기 전용 계약 -2. `QuestionSet`: 생성 대상과 측정 대상을 같은 question ID로 연결하는 계약 -3. `Publication`: 발행 URL과 question ID를 연결해 인용 성과를 귀속하는 계약 - -이 세 계약이 있어야 Brand AEO 결과가 단순한 “브랜드가 나왔다”를 넘어 “어떤 질문을 겨냥한 어떤 페이지가 인용됐다”까지 설명할 수 있다. - ---- - -## 4. 권장 개발 우선순위 - -### P0 — 개발 전에 확정할 결정 - -- **제품 범위**: Site AEO 소상공인 MVP를 유지할지, 법률·의료와 Brand AEO를 이번 제품 범위에 포함할지 -- **1차 파일럿**: Stay 머뭄 1곳 우선인지, 3업종 동시인지 -- **도메인 전략**: 고객 서브패스 / 고객 서브도메인 / 플랫폼 공용 경로의 지원 우선순위 -- **크롤 정책**: 소유권 검증 고객 도메인의 JS 렌더링 허용 범위. 플랫폼 robots·봇 차단 우회 금지는 유지 -- **이미지 권리**: 소유자 업로드만 허용할지, 기존 플랫폼 사진 재게시를 허용할지 -- **비용 예산**: Brand 측정의 테넌트당 주간 호출·금액 상한 -- **문서 버전**: 전달 파일의 파일명 v19와 표지 v18 불일치 해소 - -### P1 — 현재 Site AEO를 설계서 수준으로 닫기 - -1. 도메인 소유권 검증과 만료 시 발행 차단 -2. crawl run/document와 원본 hash 저장 -3. A7 SimHash 중복도 검사 및 fact 역참조 리포트 -4. A9 원본 변경 감지, fact 만료/검토, AI 크롤러 방문 로그 -5. 고객 도메인 연결, TLS/DNS 운영 절차 -6. 서버 계산 `allowed_actions` (앱 경계 분리는 2026-08-31 완료) - -완료 기준은 “페이지가 만들어진다”가 아니라, **소유권이 확인된 원본에서 출처가 남는 fact를 만들고 두 게이트를 통과해 고객 도메인에 발행되며, 변경과 재방문을 관측할 수 있다**는 것이다. - -### P2 — 규제 업종을 넣는 경우에만 선행 - -1. Reviewer 역할과 승인 워크벤치 -2. 외부화된 업종별 규칙과 버전 관리 -3. SAFE / NEEDS_EVIDENCE / PROHIBITED 3단 판정 -4. 규칙 ID·근거 snippet·판정 모델·승인자·시각을 남기는 감사 로그 -5. 성형외과 사전심의 상태와 자격/면허 fact 모델 -6. 법률·의료 전문가의 규칙 승인 및 변경 절차 - -A4가 완성되기 전에는 법무법인·성형외과 콘텐츠 자동 발행을 열지 않는다. - -### P3 — Brand AEO 최소 측정 루프 - -1. 질문은행과 publication-question 연결 -2. fact snapshot -3. 1~2개 AI 엔진 어댑터와 응답 원문·모델 버전 저장 -4. 언급·인용 URL·추천 위치·사실성 분석 -5. 반복 측정, 신뢰구간, MA4, 비용 집계 -6. 읽기 전용 퍼포먼스·인용출처 화면 - -처음부터 자동 EEAT 재생성까지 닫지 말고, 먼저 **같은 질문을 반복 측정했을 때 지표가 의사결정에 쓸 만큼 안정적인지** 검증한다. - -### P4 — 개선 폐루프와 운영 확장 - -- EEAT 결손 → 고객 확인 요청 / 재생성 요청 분기 -- 재생성 요청의 A4·A7 재통과 -- 정기 리포트와 외부 채널 전략 -- BFF의 섹션별 부분 실패와 서비스 JWT -- 데이터·트래픽·팀 소유권이 임계에 도달하면 Site/Brand 저장소 및 배포 단위 분리 - ---- - -## 5. 재작성하지 않고 유지할 현재 구현 - -설계서와 다르더라도 아래는 현재 제품에 맞고 이미 안전장치가 있으므로 유지하는 편이 낫다. - -- PostgreSQL 기반 잡 큐의 원자적 claim, lease, dedupe, dead-letter -- `VERIFIED`/`CORRECTED`만 발행하고 재수집 후보가 정정값을 덮지 않는 상태 모델 -- 백엔드는 payload만 만들고 프론트 프리렌더러가 정적 HTML을 생성하는 경계 -- JSON-LD와 화면값 불일치 시 발행을 막는 게이트 -- 외부 API 키가 없어도 해당 어댑터만 비활성화하는 구성 -- robots.txt와 약관을 우회하지 않는 수집 원칙 -- 현재 SEO/AEO 점수를 “준비도”로 명시하는 정직한 표현 - ---- - -## 6. 일정 재구성 제안 - -설계서의 S1~S8은 신규 구축 기준이라 현재 저장소에 그대로 적용하면 이미 끝난 기반 작업을 반복하고, 미결 정책을 코드로 먼저 굳히게 된다. 다음과 같이 게이트 중심으로 다시 잡는다. - -| 마일스톤 | 목표 | 종료 조건 | -|---|---|---| -| M0 방향 확정 | 범위·업종·도메인·크롤·비용 결정 | P0 결정 기록과 승인 | -| M1 Site 완결 | A1/A7/A9 공백과 고객 도메인 보완 | 소유권→발행→변경감지 E2E 통과 | -| M2 규제 게이트 | 법률·의료를 할 경우 A4 구축 | 전문가 승인 룰셋과 감사 가능한 차단/승인 | -| M3 Visibility 파일럿 | 질문은행·snapshot·최소 엔진 측정 | 반복 측정의 비용·분산·인용 검출 정확도 보고 | -| M4 개선 루프 | 측정 결과를 안전한 재생성 요청으로 연결 | 고객 확인 또는 A4/A7 재통과 후 발행 | -| M5 플랫폼화 | 콘솔/BFF/서비스 분리 | 실제 트래픽·팀 소유권 기준 충족 시에만 수행 | - -주차 추정치는 P0의 업종 수, AI 엔진 수, 외부 전문가 검토 가능일이 정해진 뒤 산정한다. 특히 3개 업종 동시 개발과 4개 엔진×3회 측정을 전제로 한 기존 8스프린트 일정은 현재 인력·비용 정보 없이 확정 일정으로 취급하면 안 된다. - ---- - -## 7. 바로 만들 백로그 - -| 우선순위 | 에픽 | 대표 산출물 | -|---|---|---| -| 1 | 소유권 검증 | challenge 테이블/API, DNS/meta/well-known 검증기, 만료 정책, 발행 게이트 | -| 2 | 수집 재현성 | crawl run, document hash, source selector/snippet, 변경 비교 | -| 3 | 일치성 강화 | SimHash, fact 역참조 커버리지, 실패 사유 UI | -| 4 | 발행 관측 | crawler visit/index 상태, CDN 로그 적재, 재수집/재생성 조건 | -| 5 | 고객 도메인 | 서브패스/서브도메인 연결, canonical·sitemap 검증, TLS/DNS 운영 | -| 6 | 측정 계약 | question set, fact snapshot, publication-question 연결 | -| 7 | Visibility 파일럿 | 엔진 어댑터, 원문 로그, mention/citation/position/factuality 분석, 비용 상한 | -| 8 | 운영 화면 | 소유권·수집·게이트·발행 상태부터 추가, 이후 질문/성과/인용 화면 | -| 조건부 | 규제 업종 | 규칙 저장소, Reviewer, 승인 워크벤치, 감사 로그, 사전심의 | - ---- - -## 8. 관련 현재 문서 - -이 문서는 비교와 향후 방향만 다룬다. 현재 제품 원칙과 구현 상세는 중복해서 관리하지 않는다. - -- 제품 범위와 non-goal: [PRODUCT.md](PRODUCT.md) -- 현재 수집·생성·발행 흐름: [COLLECTION_SEO_AEO_FLOW.md](COLLECTION_SEO_AEO_FLOW.md) -- 법무·데이터·작업 큐 결정: [DECISIONS.md](DECISIONS.md) -- 데이터 소스 실측: [DATA_SOURCE_RESEARCH.md](DATA_SOURCE_RESEARCH.md) -- 배포와 도메인 운영: [DEPLOY.md](DEPLOY.md) -- 외부 API 비용: [API_USAGE.md](API_USAGE.md) - diff --git a/docs/TEMPLATES.md b/docs/TEMPLATES.md index ed54e74..2bb8f8e 100644 --- a/docs/TEMPLATES.md +++ b/docs/TEMPLATES.md @@ -1,5 +1,7 @@ # 템플릿과 렌더링 +화면 규칙(글자 크기 · 간격 · 접기 · ✓ 표시)은 [TEMPLATE_DESIGN.md](TEMPLATE_DESIGN.md). + 사장님이 고르는 "템플릿"이 어디에 정의돼 있고, 화면에 어떤 순서로 그려지는지 적은 문서다. 2026-09-28에 구조를 한 번 갈아엎었고, 이 문서는 그 뒤의 모습이다. @@ -32,12 +34,12 @@ | 칸 | 뜻 | |---|---| | `name` · `tag` · `description` | 빌더에서 사장님이 보는 이름과 설명 | -| `layout` | 어떤 뼈대로 그릴지. 지금은 `basic`과 `paper` 두 개 | +| `layout` | 어떤 뼈대로 그릴지. `basic` · `paper` · `round` · `cinema` · `bigtype` · `boutique` · `graphic` · `coral` · `minimal` · `pine` | | `colors` | 기본 색. 사장님이 팔레트를 고르면 그 색이 위에 덮인다 | | `look` | 서체, 모서리, 그림자, 섹션 간격. 사장님이 못 바꾼다 | | `addSections` | 이 템플릿을 고르면 새로 켜지는 섹션. 레트로의 일력·영상 같은 것 | -지금 템플릿은 네 개다. +지금 템플릿은 아홉 개다. | id | 이름 | 뼈대 | |---|---|---| @@ -45,12 +47,24 @@ | `magazine` | 매거진 | basic | | `retro` | 레트로 | basic | | `paper` | 고택 | paper | +| `round` | 라운드 | round | +| `cinema` | 시네마 | cinema | +| `bigtype` | 빅타이포 | bigtype | +| `boutique` | 부티크 | boutique | +| `graphic` | 일러스트 | graphic | +| `coral` | 코랄 | coral | +| `minimal` | 미니멀 | minimal | +| `pine` | 솔숲 | pine | 심플·매거진·레트로는 뼈대가 같고 색과 서체만 다르다. 고택은 손으로 만든 시안 `/s/stay2`를 그대로 옮긴 것이라 뼈대부터 다르다. 폭 640px짜리 한 단에, 위쪽 탭 네 개(소개 · 지역 소개 · 이용안내·예약 · 이야기)로 화면을 나눈다. 탭을 눌러도 페이지를 새로 받지 않는다. 내용은 전부 한 HTML 안에 있고 보이는 묶음만 바뀐다. 검색엔진은 네 묶음을 다 읽는다. +라운드·시네마·빅타이포·부티크·일러스트·코랄·미니멀·솔숲은 고택과 같은 섹션과 탭 네 개를 그대로 받고 모양만 다르다. +예약 시트와 예약 폼은 고택 부품을 가져다 쓴다. 모바일 390px에서 먼저 맞췄다. 일러스트는 사진이 +거의 없는 집을 위한 것이라, 첫 화면과 객실 카드를 그림으로 채운다. + 업종마다 쓸 수 있는 템플릿과 기본 템플릿은 같은 파일의 `industries`에 적는다. 숙박은 레트로가 기본이고, 병원은 심플과 매거진만 쓸 수 있다. diff --git a/docs/TEMPLATE_DESIGN.md b/docs/TEMPLATE_DESIGN.md new file mode 100644 index 0000000..b722e69 --- /dev/null +++ b/docs/TEMPLATE_DESIGN.md @@ -0,0 +1,106 @@ +# 템플릿 디자인 규칙 + +새 템플릿을 만들거나 기존 템플릿을 고칠 때 지키는 화면 규칙이다. 기준은 고택(`layouts/paper/`)이다. +고택은 손으로 만든 시안 `/s/stay2`(`solution/site/scripts/mockup/king-stay2/`)를 옮긴 것이라 +스크롤 길이·접기·글자 크기가 이미 검증돼 있다. 수치가 애매하면 `layouts/paper/paper.css` 를 연다. + +템플릿 목록과 등록 방법은 [TEMPLATES.md](TEMPLATES.md), 렌더링 흐름은 [RENDERING.md](RENDERING.md). + +## 1. 폭 + +| 화면 | 규칙 | +|---|---| +| 모바일 390px | 먼저 맞춘다. 가로 넘침 0 | +| 700~1023px | 640px 한 단, 가운데 | +| 1024px 이상 | 템플릿마다 정한다. 넓은 배치면 콘텐츠 최대 1080px, 첫 화면은 가로 전체 | + +부티크처럼 모바일 한 단을 데스크톱에서도 그대로 쓰는 템플릿이 있다. 정한 방식은 [TEMPLATES.md](TEMPLATES.md) 에 적는다. + +## 2. 글자 + +- 본문 16~17px, 줄 간격 1.7 이상. 고택은 17px/1.9. **본문 16px 미만 금지** +- 보조 글씨 14~15px. 기능 글씨(버튼·메뉴) 12px 미만 금지 +- 섹션 제목 22~30px. 고택은 19px 명조 +- 첫 화면 문구: 모바일 28px 안팎, 데스크톱 48px 이하 +- 상호를 크게 쓰는 템플릿(빅타이포)도 64px 이하 +- `vw` 로 커지는 글자 크기 금지. 넓은 화면에서 끝없이 커진다 +- 보조 글씨 대비 4.5:1 이상. `#8b95a1` 같은 연회색은 흰 바탕에서 2.9:1 이라 탈락한다 + +### 템플릿별 한글 글꼴 — 겹치지 않게 배정했다 + +| 템플릿 | 제목 | 본문 | +|---|---|---| +| 고택 | Noto Serif KR | 시스템 고딕 | +| 라운드 | Noto Sans KR | Noto Sans KR | +| 시네마 | 송명 | Noto Sans KR | +| 빅타이포 | 함렛 | 함렛 · IBM Plex Mono | +| 부티크 | Cormorant · 나눔명조 | 나눔명조 | +| 일러스트 | 주아 | 고운돋움 | +| 코랄 | Gothic A1 · Aboreto | Gothic A1 | +| 미니멀 | Diphylleia · Cinzel | Questrial · 나눔고딕 | +| 솔숲 | IBM Plex Sans KR | IBM Plex Sans KR | + +새 템플릿은 이 표에 없는 글꼴을 쓴다. 웹폰트는 `seo/head.ts` `WEB_FONTS` 에 등록해야 받아 온다. + +## 3. 간격 + +- 제목 위 여백 32px 이상. 제목 위가 아래보다 넓다 +- 카드형 목록 사이 10px 이상(선으로 나누는 목록은 예외) +- 같은 목록의 카드는 같은 크기: 사진은 고정 비율 + `object-fit:cover`, 글은 줄 수 말줄임 +- 칸 수는 항목 수에 맞춘다(`repeat(auto-fit, minmax(…))`). 3개인데 4칸을 잡아 빈칸을 남기지 않는다 + +## 4. 섹션 머리 + +- **제목은 위, 내용은 아래.** 참고한 펜션 사이트들이 모두 이 방식이다 +- 제목을 왼쪽, 내용을 오른쪽에 두는 좌우 분할은 쓰지 않는다. 내용이 한두 줄이면 왼쪽이 텅 빈다 + (예외: 소개 글과 사진이 둘 다 충분할 때의 소개 섹션) +- 제목 위에 같은 뜻의 작은 라벨(‘객실’ 위 ‘객실 안내’)을 달지 않는다. + 참고 사이트의 정체성인 영문 제목(코랄 `Room View`, 미니멀 `Stay`)은 예외 + +## 5. 스크롤 줄이기 — 몇 개 보이고 접나 + +`
` 로 접는다. 내용은 HTML 에 남아 크롤러가 읽는다. 빼지 않는다. + +| 목록 | 처음 보이는 수 | 근거 | +|---|---|---| +| 첫 화면 사진 | 5장 | `paper/Hero.tsx` `MAX_SLIDES` | +| 홈 객실 | 4개(2열) | 나머지는 이용안내 탭 | +| 홈 사진 갤러리 | 큰 1 + 4장 | `paper/Gallery.tsx` `FIRST` | +| 홈 주변 안내 | 3~4곳 | 나머지는 지역 탭 | +| 명소 · 맛집 | 8곳 | `paper/Around.tsx` `FIRST_ROWS` (데스크톱 넓은 배치는 8, 모바일 6도 허용) | +| 축제 | 가로 캐러셀 | 세로로 펼치지 않는다 | +| 추천 일정 | 4개 | `paper/Itinerary.tsx` `FIRST` | +| 노래 | 6곡 | `paper/Story.tsx` | +| 인물 | 4명 | `paper/Story.tsx` | +| 지역 읽기 | 3편, 본문 3줄 말줄임 | `paper/Story.tsx` | +| 자주 묻는 질문 | 8개, 질문은 접힌 상태 | `paper/Faq.tsx` `FIRST` | + +## 6. 값 보여주기 + +- **‘가능 · 있음’은 ✓, ‘불가 · 없음’은 ✕ 목록으로 쓴다.** `주차 / 가능` 같은 표로 쓰지 않는다 + - 마크업: `