이 블로그는 어떻게 만들어졌나
주말 동안 만든 블로그다. Astro 6 + Cloudflare Workers + D1, 에디터는 TipTap. 글은 markdown으로 저장하고, 인증은 Cloudflare Access에 위임했다. 모든 결정의 기준은 단 하나, as little code as possible.
Why Astro
선택지는 Next.js, Remix, SvelteKit, Astro 정도였다. 처음엔 Next.js를 생각했다. 익숙하니까.
그런데 블로그는 본질적으로 콘텐츠 사이트다. SSR이 필요한 페이지는 admin과 edit 두 개뿐이고, 나머지는 사실상 정적이다. Next.js의 App Router는 그 정도 규모엔 과하다는 인상을 받았다. Astro는 "기본은 정적, 필요할 때만 server"라는 모델이라 mental overhead가 거의 없다.
결정적이었던 건 Astro의 file-based routing이 이상한 짓을 안 한다는 점이었다. src/pages/posts/[slug].astro 파일이 곧 /posts/<slug> 경로다. middleware는 src/middleware.ts 하나. magic이 적다.
D1 vs Git
처음엔 git-as-database로 시작하려 했다. content를 GitHub에 commit하고, GitHub Actions가 build를 trigger하는 식. Hugo 같은 static site generator의 정석이다.
그런데 글을 쓸 때 매 저장마다 git commit이 일어나는 건 친화적이지 않았다. 자동저장은 안 한다고 정했지만, 명시 저장이라도 commit 한 번에 600ms씩 걸리는 건 견디기 어려웠다.
D1으로 갈아탔다. 같은 명시 저장이 ~10ms로 떨어졌다. 그리고 D1의 Time Travel 기능이 30일 PITR을 무료로 제공한다. "git history가 그리워질까" 하는 걱정은 사실상 사라졌다.
TipTap, again
WYSIWYG 에디터는 두 번째다. 첫 번째는 ProseMirror를 직접 다뤘는데, schema 정의가 짜증나서 6개월 만에 갈아엎었다. TipTap은 그 ProseMirror를 한 단계 추상화한 layer다.
이번엔 @tiptap/starter-kit + tiptap-markdown 조합으로 끝냈다. markdown 직렬화·역직렬화가 한 줄로 된다.
const body_md = (editor.storage.markdown as any).getMarkdown();
나중에 custom node — Callout, Embed, Code Sandbox 같은 것 — 을 붙이고 싶어지면 그때 schema를 만들 거다. 일단은 plain markdown으로 충분하다.
Fonts
Roboto Slab + Noto Serif KR 페어링. Roboto Slab은 self-host한 variable font 한 파일(34KB), Noto Serif KR은 124개 chunk로 쪼갠 subset에서 페이지에 등장한 글자가 속한 chunk만 lazy 다운로드.
외부 도메인(fonts.googleapis.com, fonts.gstatic.com)을 안 거치는 게 큰 차이를 만든다. DNS lookup, TLS handshake가 사라지면서 LCP가 눈에 띄게 빨라졌다.
The fastest font is the one you already have.
시스템 폰트 폴백(Apple Myungjo, Batang)이 Noto Serif KR이 도착하기 전에 즉시 렌더된다. 둘 다 serif라 시각적 점프가 작다.
What's missing
아직 없는 것들:
- 이미지 업로드 (R2 bucket binding 풀고
/api/upload추가하면 끝) - syntax highlighting (Shiki 한 줄)
- RSS / sitemap (template 30줄)
- 검색 (D1 FTS5)
- 다크 모드
- 백업 cron (D1 → GitHub mirror)
전부 "필요해지면 1시간" 정도의 작업이다. 미리 만들지 않는다. YAGNI는 오래 살아남는 원칙이다.
Footnote
이 글 자체가 첫 번째 "진짜 글"이다. 셋업이 끝났다는 신호이자, 셋업에 너무 오래 매달리지 말라는 자기 경고다.