정적 블로그에 Next.js 대신 Astro를 고른 이유
Jekyll과 jekyll-theme-chirpy로 운영하던 블로그를 마침표를 찍고 다시 만들기로 했습니다.
글을 쓰는 데는 문제가 따로 없었고 다만 Ruby 툴체인을 다시 손볼 때마다 조금씩 막혔고, 테마에서 벗어나는 화면을 만들려고 하면 Liquid 템플릿과 오래 씨름해야 했습니다.
처음 떠올린 것은 당연히 Next.js였습니다.
업무에서 매일 쓰는 프레임워크이고 output: "export"만 설정하면 정적 파일도 만들 수 있고 다 좋죠, 익숙한 도구로 항상 하던데로 익숙하게 만들면 되는 일이었죠.
그런데 요구사항을 적어보니 이상했습니다.
Next.js가 잘하는 SSR, 서버 액션, 클라이언트 라우팅 같은 기능을 이 블로그는 거의 쓸 일이 없었습니다.
Astro는 원래 랜딩페이지처럼 한 번 만들어두면 방문자가 읽기만 하는 사이트에 잘 맞는다고 생각하고 있었습니다. 서버에서 할 일도, 브라우저에서 React가 할 일도 거의 없는 페이지들이죠.
블로그도 결국 글이 많은 랜딩페이지에 가깝다고 보고 Astro로 만들었습니다. 그리고 같은 글을 Next.js로도 한 번 빌드해보면서 두 결과를 비교해봤습니다.
블로그에 정말 필요한 것부터 정리해봤습니다.
| 필요한 것 | 필요 없는 것 |
|---|---|
| 마크다운 글, 코드 하이라이팅 | 로그인, 세션 |
| 목록, 카테고리, 태그, 검색 | 데이터베이스 |
| RSS, 사이트맵, OG 이미지 | 관리자 화면 |
| 기존 URL 그대로 유지 | 요청마다 바뀌는 화면 |
왼쪽은 전부 빌드할 때 내용이 정해집니다. 방문자가 들어온 뒤에 서버가 새로 계산할 게 하나도 없습니다.
같은 글 37편으로 두 번 빌드해봤습니다
느낌만으로 정하고 싶지는 않아서 Next.js 15 App Router에 output: "export"로 최소한의 블로그를 만들고, 지금 운영 중인 Astro 블로그와 비교했습니다.
빌드 시간은 상관없었습니다
| 빌드 시간 | 만든 페이지 | |
|---|---|---|
| Next.js | 약 6초 | 40 |
| Astro | 약 10초 | 122 |
Next.js가 더 빨랐지만, Astro는 OG 이미지와 검색 인덱스까지 같이 만들고 있었습니다.
어느 쪽이든 10초 안쪽입니다. 글 몇십 편짜리 블로그라면 빌드 시간은 기준이 되지 않습니다.
차이는 결과물에서
같은 글 페이지 하나를 비교했습니다.
| Next.js | Astro | |
|---|---|---|
| JS 파일 | 5개 | 0개 |
| JS 크기(gzip) | 103KB | 0B |
| 인라인 JS | 8개 | 2,166B |
제가 쓴 페이지 코드는 125B인데, Next.js는 첫 로드에 103KB의 자바스크립트를 붙였습니다. 클라이언트 컴포넌트를 하나도 넣지 않았는데도요.
HTML 안도 열어봤습니다. 10KB짜리 HTML 중 약 70%가 RSC 데이터(React가 화면을 이어받는 데 쓰는 데이터)였습니다.
Next.js가 잘못 만든 건 아닙니다. 페이지 전환을 부드럽게 하고 React 상태를 이어가려면 필요한 비용입니다.
다만 이 블로그에서 사용자가 하는 일은 읽고 링크를 누르는 것뿐입니다. 쓰지도 않을 기능의 비용을 내고 있었던 셈입니다.
Astro는 자바스크립트 0에서 시작합니다
Astro는 기본적으로 HTML만 보내고, 자바스크립트가 필요한 곳에만 따로 붙입니다.
이 블로그에서 자바스크립트가 필요한 곳은 세 군데뿐이었습니다.
206B 다크모드 토글
1,731B 검색창
229B 첫 화면 깜빡임 방지
Next.js는 React가 다 있는 상태에서 시작하고, Astro는 아무것도 없는 상태에서 필요한 만큼만 더합니다. 숫자보다 이 기본값의 차이가 더 컸습니다.
블로그는 한 번 만들고 오래 방치하는 프로젝트입니다. 1년 뒤에 번들이 얼마나 커졌는지 신경 쓰지 않아도 되는 쪽이 편했습니다.
SEO도 따로 신경 쓸 게 없었습니다. 모든 글이 처음부터 완성된 HTML이라 검색엔진과 링크 미리보기 봇이 그대로 읽습니다. OG 이미지, RSS, 사이트맵도 빌드할 때 파일로 만들어집니다.
기존 URL은 하나도 깨지지 않게
옮기면서 가장 신경 쓴 건 번들 크기보다 이미 공유되고 검색에 잡힌 주소였습니다.
기존 주소는 /posts/<slug>/ 형식이었고, 설정 두 줄로 그대로 살렸습니다.
export default defineConfig({
trailingSlash: "always",
build: { format: "directory" },
});
없어진 카테고리는 redirects로 새 목록에 연결했습니다.
아쉬웠던 점
한글 강조가 깨졌습니다. **'대리'**라는처럼 한글에 바로 붙은 굵게 표시가 Astro 7에서는 적용되지 않았습니다. 37편을 다 옮긴 뒤에야 알았고, remark-cjk-friendly 플러그인으로 해결했습니다. 한글 블로그를 옮긴다면 빌드 성공만 보지 말고 글 몇 편을 직접 열어보세요.
node_modules가 가볍진 않습니다. 185MB, 패키지 417개입니다. 다만 이 무게는 빌드할 때만 쓰이고 방문자는 받지 않습니다.
자료가 적습니다. 공식 문서는 좋지만, 검색으로 나오는 사례는 Next.js보다 훨씬 적습니다.
애드센스 한 줄이 아낀 용량보다 큽니다. 103KB를 아꼈는데 광고 스크립트가 들어갑니다. “자바스크립트 0바이트”라고 자랑하기엔 조금 민망합니다.
그렇다면 Next.js는 언제 선택할까
Astro가 항상 낫다는 이야기는 아닙니다. 아래 같은 기능이 필요했다면 Next.js를 골랐을 겁니다.
- 로그인에 따라 달라지는 화면
- 가격, 재고, 대시보드처럼 실시간 데이터
- 서버 액션, 미들웨어, 결제 처리
- 상호작용이 많은 React 화면
둘 다 정적 사이트도, 서버 렌더링도 할 수 있습니다. 중요한 건 내 프로젝트가 대부분 어느 쪽이냐입니다.
정리
- 프레임워크를 고르기 전에 방문 시점에 서버가 할 일이 있는지 먼저 적어보세요.
- 작은 블로그에서 빌드 시간은 기준이 안 됩니다.
- 콘텐츠가 기본이고 상호작용이 예외라면 Astro가 잘 맞습니다.
- 블로그를 옮길 때는 프레임워크보다 URL과 마크다운 호환성이 더 큰 문제였습니다.
이 블로그에서는 React를 빼는 게 최적화가 아니었습니다. 처음부터 필요 없는 걸 고르지 않은 것뿐이었습니다.