사례 연구 4: 손 갈 필요 없는 콘텐츠 사이트
아이디어
한 취미가가 마크다운 노트 폴더 — 수년간 여행하며 쓴 식당 리뷰 — 를 검색 가능한 공개 사이트로 바꾸고 싶어 했다. 로그인할 CMS도 없고 월 청구서도 없이. 노트를 추가하고, 푸시하고, 끝.
스펙
마크다운 파일 폴더에서 생성되는 정적 사이트, 리뷰당 파일 하나
(프론트매터에 title, city, rating, body). 리뷰를 최신순으로
나열하는 홈페이지, 리뷰당 페이지 하나, 그리고 도시나 이름으로
하는 클라이언트 사이드 검색을 만들어라. 데이터베이스 없음,
로그인 없음, 내가 손으로 돌려야 하는 빌드 단계 없음. 새 .md
파일을 푸시하면 그게 게시되어야 한다.
숨은 요구사항은 마지막 문장에 있다. "내가 손으로 돌려야 하는 빌드 단계 없음"은 스펙이 사실 출력만이 아니라 워크플로에 관한 것임을 뜻한다 — 그리고 워크플로 요구사항은 명명하지 않으면 AI가 건너뛰는 부류인데, 돌아가는 앱에서는 드러나지 않기 때문이다.
스택
빌드 타임에 마크다운을 읽는 정적 사이트 생성기를, Git 트리거 빌드를 갖춘 CDN 호스트에 배포했다. 저장소에 푸시하면 호스트가 다시 빌드하고, CDN이 서빙한다. 검색은 빌드 시 생성된 작은 JSON 인덱스 위에서 클라이언트 사이드로 하므로, 서버도 없고 쿼리 비용도 없다 — 리뷰 수백 개에서는 괜찮은 트레이드오프이자, 발견한 게 아니라 우리가 명명한 의도적 선택이다.
핵심 프롬프트
우리는 어떤 UI보다 먼저 AI를 데이터 형태에 닻 내렸다:
/reviews 안의 모든 .md 파일을 읽는 정적 사이트를 세팅하라. 각
파일의 프론트매터에 title, city, rating(1-5), date가 있다. 빌드
타임에 그것들을 전부 파싱해 정렬된 목록(최신순)으로 만들고
생성하라: 그것들을 나열하는 홈페이지, 그리고 /reviews/<slug>에
리뷰당 페이지 하나. 어떤 스타일링보다 먼저 데이터 로딩 코드를
보여달라.
"어떤 스타일링보다 먼저"는 의도적인 레버다. 한꺼번에 다 요청하면 신뢰할 수 없는 데이터에 연결된 아름다운 페이지를 얻는다; 데이터 레이어를 먼저 요청하면 단 한 픽셀이 주의를 흩뜨리기 전에 토대를 검증할 수 있다. 그런 다음 싸게 유지하도록 범위를 좁힌 검색:
빌드 타임에 모든 리뷰에 대한 {title, city, slug}로 search.json을
생성하라. 홈페이지에서 검색 박스를 추가해 보이는 목록을
클라이언트 사이드로 city나 title 매칭으로 필터하라 — 네트워크
호출 없이, 이미 로드된 인덱스를 그냥 필터하라. JS 50줄 아래로
유지하라.
장애물
빌드는 로컬에서 통과했지만 배포된 사이트는 개별 리뷰 페이지마다 404를 냈다. 홈페이지는 동작했고; 리뷰별 페이지는 아니었다. 우리는 이론화하기보다 증상과 설정을 붙여 넣었다:
홈페이지는 라이브에서 동작하는데, /reviews/<slug> 페이지들은
로컬 dev에서는 동작하면서 프로덕션에서는 전부 404가 난다. 여기
내 빌드 출력 디렉터리 목록과 호스트의 배포 설정이다: [붙여넣음].
왜 로컬 dev는 이 페이지들을 서빙하는데 프로덕션은 안 하나?
AI는 그것을 dev 서버 라우팅(경로를 동적으로 해석)과 정적
호스팅(물리적으로 존재하는 파일만 서빙)의 차이로 추적했다.
빌드가 리뷰 페이지들을 잘못된 출력 폴더로 생성하고 있어서,
그것들은 절대 업로드되지 않았다 — dev가 프로덕션이 못 하는
라우트를 라우터가 가짜로 만들어줘서 버그를 숨겼던 것이다.
우리는 출력 디렉터리를 호스트가 실제로 배포하는 것에 맞췄고, 페이지들이 나타났으며, 출시 체크리스트에 한 줄을 추가했다: 홈페이지뿐 아니라 라이브 사이트에서 딥 링크를 클릭하라. 더 넓은 교훈은 "dev에서 동작함"과 "배포되어 동작함"은 다른 주장이고, 정적 익스포트가 바로 그 둘이 갈리는 지점이라는 것이다 — dev 서버는 실제 파일 기반 호스팅이 결코 그렇지 않은 방식으로 라우트에 너그럽다.
출시
우리는 진짜 리뷰를 하나 푸시하고, 호스트가 다시 빌드하는 것을 지켜보고, 그 특정 리뷰로 가는 딥 링크를 라이브 도메인에서 로드했다 — dev가 거짓말했던 바로 그 경우. 그런 다음 인덱스가 그것을 집어 들었는지 확인하려 그 도시를 검색했다. 다음 리뷰를 추가하는 것은 한 줄짜리 커밋이었는데, 그게 핵심 전부였다: 출시는 한 순간이 아니라, 우리 없이도 계속 동작하는 워크플로였다.