렌더링 타입 (CSR, SSR, SSG, ISR).
masonfe-hyunsu
🧭 1. 개요.

화면이 붙으려면 컴포넌트와 데이터를 HTML로 바꿔야 하고, 이 과정이 렌더링이다.
같은 화면이라도 HTML을 언제, 어디서 만드느냐에 따라 첫 화면 속도, 검색 노출, 서버 비용이 갈린다.
이 포스팅에서는 그 시점을 CSR, SSR, SSG, ISR 네 타입으로 나눠 정리해 본다.
요약하면, 렌더링은 HTML을 만들어 화면에 붙이는 일이고, 타입은 그 HTML을 언제, 어디서 만드느냐로 나눈다.
시점을 나눠 보면 아래다.
CSR: 브라우저에서 그린다
SSR: 요청 올 때 서버에서 그린다
SSG: 빌드할 때 미리 그린다
ISR: 미리 그리되, 필요할 때 다시 그린다

왼쪽부터 CSR → SSR → SSG → ISR 순서다. 자세한 동작은 아래부터.
🖥️ 2. CSR : 브라우저에서 그리기.
CSR (Client-Side Rendering)은 JS를 받은 뒤, 브라우저에서 HTML을 만드는 방식이다.
Create React App으로 SPA를 만들던 시절이 딱 이 그림이었다.
요청 → 거의 빈 HTML + JS
→ 브라우저가 JS 실행
→ 데이터 fetch
→ 화면 완성로그인 후 대시보드처럼 검색 노출이 크게 중요하지 않은 화면, 들어온 뒤 오래 붙잡고 쓰는 앱에는 잘 맞았다.
대신 첫 화면이 느리게 느껴질 때가 많다. JS를 받고, 돌리고, fetch가 끝나야 본문이 보이기 때문이다.
브라우저에서 보면 대략 이 순서다. 한동안 비어 있다가, JS가 끝난 뒤에야 내용이 채워진다.

링크 미리보기나 크롤러도 빈 HTML만 볼 위험이 있어서, 요즘은 진입만 서버나 정적으로 두고 안쪽은 CSR로 가는 식이 더 흔하다.
🖨️ 3. SSR : 요청마다 서버에서 그리기.
SSR (Server-Side Rendering)은 요청이 올 때마다 서버가 HTML을 만들어 내려준다.
브라우저는 그 HTML을 먼저 보여 주고, 이후 JS로 클릭, 입력을 붙인다. 이 붙이는 과정이 Hydration(서버가 준 HTML에 이벤트를 연결하는 일)이다.
CSR는 JS와 fetch가 끝나야 본문이 보이는데, SSR는 HTML이 먼저 내려온다.
요청 → 서버에서 데이터 조회 + HTML 생성
→ HTML 응답
→ JS 로드 후 hydrate
→ 상호작용 가능검색, OG(Open Graph, 링크 미리보기용 메타) 이미지가 중요한 페이지나, 로그인 사용자마다 내용이 달라져야 하는 화면에서 자주 골랐다.
다만 매 요청마다 서버 일이 생긴다. TTFB(Time To First Byte, 첫 바이트가 오기까지 시간)가 길어질 수 있고, 트래픽이 늘면 서버도 같이 바빠진다.
Next.js에서는
getServerSideProps때부터 익숙했고, App Router의 동적 렌더링도 같은 축으로 보면 편했다.HTML과 클라이언트 렌더 결과가 어긋나면 hydration mismatch가 난다. 서버에서 그린다와 브라우저에서 살아 움직인다를 구분해 두면 이런 이슈도 덜 막막하다.
📦 4. SSG : 빌드할 때 미리 그리기.
SSG (Static Site Generation)은 빌드 시점에 HTML을 만들어 두고, CDN이나 정적 호스팅으로 뿌린다.
예를 들면 이 블로그처럼, 글이 자주 안 바뀌는 콘텐츠랑은 거의 정석이다.
빌드 → 페이지 HTML 생성
→ S3 + CloudFront 같은 곳에 배포
→ 요청 시 캐시된 HTML 응답문서, 랜딩, 마케팅 페이지처럼 배포 시점에 내용이 확정되는 곳에 잘 맞는다.
대신 내용을 바꾸려면 다시 빌드해야 하고, 페이지가 아주 많으면 빌드 자체가 길어진다.
output: "export"로 정적 파일을 뽑는 경우도 이 계열로 보면 된다.
♻️ 5. ISR : 미리 그리되, 가끔 다시 그리기.
ISR (Incremental Static Regeneration)은 SSG처럼 미리 만들되, 시간이 지나면 백그라운드에서 다시 굽는 방식이다.
완전 정적과 매 요청 SSR 사이에서 타협한 느낌이다.
빌드 → 정적 HTML
→ 캐시로 제공
→ revalidate 시간이 지나면
→ 다음 요청 이후 백그라운드 재생성
→ 이후 요청부터 새 HTML루프만 보면 대략 이렇다.

박스: 빌드 (미리 만들기)
구름: 캐시에 올려 두기
회전 화살표: 필요할 때 다시 굽기
상품 목록이나 뉴스처럼, 자주 바뀌진 않는데 배포마다 전부 다시 빌드하기엔 무거운 페이지에서 손이 갔다.
CDN 속도는 유지하면서 내용을 주기적으로 갱신하고 싶을 때 유용하다.
다만 잠깐 옛 내용이 보이는 stale(아직 갱신 전인 캐시) 구간이 생길 수 있고,
revalidate나 on-demand 재생성을 같이 설계해야 한다. 여기부터는 캐시 감각이 좀 필요하다.
🎯 6. 고를 때 보는 기준.
페이지 전략을 고를 때는 이런 질문을 먼저 본다.
이 페이지는 검색, 공유가 중요한가?
데이터가 요청마다 달라져야 하나, 빌드 시점이면 되나?
갱신은 분 단위인가, 하루 단위인가, 배포 때만인가?
서버를 그만큼 돌려도 되나?
고를 때마다 이게 제일 고민이었다.

그래서 대략 이렇게 골랐다.
로그인 후 앱 화면 → CSR (또는 혼합)
개인화된 HTML이 당장 필요 → SSR
거의 안 바뀌는 문서, 블로그 → SSG
정적 속도는 유지하고 가끔만 갱신 → ISR
💡 7. 정리.
타입 이름은 결국 HTML을 만드는 시점의 별칭이다.
한 사이트 전체를 한 방식으로 묶기보다, 페이지마다 다르게 고르는 편이 맞았다. "우리 서비스는 SSR이다"보다 "이 페이지는 왜 SSR인가"가 더 쓸모 있었다.
댓글