공개 블로그(former-force) 클라이언트 사이드 검색 계약. 장문 없음.
1. 왜 CSR 검색인가
| 전제 |
결론 |
| Astro 정적 prerender 배포 |
서버 검색 API 없음이 기본 |
| 글 SSOT = Notion · 빌드타임 fetch |
검색 인덱스도 빌드 산출물 |
URL q만 바꿔 결과 갱신 |
새로고침 없이 브라우저 필터 |
서버에 Notion 토큰을 둔 런타임 검색은 1순위 아님(리미트·지연). 인덱스는 빌드 때 만들고, 클라이언트에서 필터한다.
2. 권장 스택 후보
| 후보 |
요지 |
선택 기준 |
| Pagefind |
Astro/정적 HTML 인덱싱 · 번들·UI 옵션 |
본문 전문 검색·설치 단순 · HTML 산출물 기준 |
| MiniSearch + JSON index |
빌드 시 title/tags/slug/excerpt/body JSON → 브라우저 로드 |
필드 제어·태그칩 병행·페이로드 최소화에 유리 |
기본 권장: 필드·태그 계약을 Posts 메타와 맞추기 쉬우면 MiniSearch+JSON. 본문 전문·유지보수 최소면 Pagefind. 둘 중 하나만 채택(중복 인덱스 금지).
3. 빌드 산출물 · 인덱스 필드
| 항목 |
계약 |
| 생성 시점 |
astro build (Published Posts만) |
| 산출 경로 (제안) |
public/search/ 또는 dist/.../search/ — 구현 시 레포에 확정 |
| 필수 필드 |
title · tags · slug · excerpt |
| 선택 필드 |
body(또는 본문 일부) · date · series |
| 결과 URL |
/posts/[slug] |
| 소스 |
Notion Posts Published (캐시 경로는 ‣) |
4. UI 계약
| 항목 |
값 |
| 진입 |
Posts SearchField → /search |
| 쿼리 |
/search?q= (클라이언트에서 q 반영) |
| 단축키 |
⌘K (Windows: Ctrl+K) → /search 포커스 |
| Figma Desktop |
197:332 |
| Figma Mobile |
197:387 |
| 빈 상태 |
q 없음 · 안내 카피 |
| 로딩 |
인덱스 최초 로드만 · 아래 게이트 |
| 결과 0건 |
empty 카피 · 태그/전체 글 유도 |
| 태그칩 |
/tags/[tag]와 병행 (검색과 필터 충돌 없이) |
| 테마 |
dark-only · shell/Ink Teal 토큰 |
5. 스켈레톤 게이트
인덱스/결과 전환이 <300ms면 스켈레톤 생략. 그 이상만 quiet 스켈레톤(VT 계약과 동일 톤).