Search

04-4_SSG

정적 생성 (SSG)

지금까지 구현한 SSR은 요청이 올 때마다 렌더링해요. 하지만 블로그 글처럼 내용이 자주 바뀌지 않는 페이지는 어떨까요?
요청 1: /blog/hello → renderToString() → HTML 요청 2: /blog/hello → renderToString() → HTML ← 같은 결과 요청 3: /blog/hello → renderToString() → HTML ← 계속 반복
Plain Text
복사
매번 똑같은 결과를 만드는 건 낭비예요.

아이디어: 미리 렌더링해두기

정적 생성(Static Site Generation, SSG)의 핵심은 간단해요. 빌드 시점에 HTML을 미리 만들어서 파일로 저장해두는 거예요.
// build.ts - 빌드 스크립트 import { renderToString } from "react-dom/server"; import fs from "fs"; import BlogPost from "./pages/BlogPost"; // 빌드할 페이지 목록 const posts = [ { id: "hello", title: "Hello World", content: "첫 번째 글입니다." }, { id: "ssr", title: "SSR 이해하기", content: "SSR은..." }, ]; // 각 페이지를 미리 렌더링 for (const post of posts) { const html = renderToString(<BlogPost post={post} />); const fullHtml = ` <!DOCTYPE html> <html> <body> <div id="root">${html}</div> <script> window.__INITIAL_DATA__ = ${JSON.stringify(post)}; </script> <script type="module" src="/client.tsx"></script> </body> </html> `; // 파일로 저장 fs.writeFileSync(`./dist/blog/${post.id}.html`, fullHtml); } console.log(`${posts.length}개의 페이지가 생성되었습니다.`);
TypeScript
복사
이 스크립트를 빌드 시점에 실행하면:
dist/ blog/ hello.html ← 미리 렌더링된 HTML ssr.html ← 미리 렌더링된 HTML
Plain Text
복사

정적 파일 서빙

이제 서버는 렌더링할 필요 없이 파일만 보내면 돼요.
// server.ts import { Hono } from "hono"; import { serveStatic } from "hono/serve-static"; const app = new Hono(); // 정적 파일 서빙 app.use("/blog/*", serveStatic({ root: "./dist" })); export default app;
TypeScript
복사
요청: /blog/hello 서버: dist/blog/hello.html 파일을 그대로 전송
Plain Text
복사
렌더링 비용이 0이에요. CDN에 올려두면 전 세계 어디서든 빠르게 응답할 수 있죠.

SSG의 한계

하지만 SSG에는 한계가 있어요.
1.
빌드 시점에 모든 페이지를 알아야 한다: 동적으로 생성되는 페이지는 처리하기 어려워요.
2.
내용이 바뀌면 다시 빌드해야 한다: 글 하나 수정해도 전체 빌드가 필요해요.
3.
빌드 시간이 길어질 수 있다: 페이지가 수천 개라면?
이 한계를 해결하는 방법이 ISR이에요.