mason
mason-log.

렌더링 타입 (CSR, SSR, SSG, ISR).

mason

masonfe-hyunsu

🧭 1. 개요.

데이터에서 HTML, 화면으로 이어지는 렌더링

화면이 붙으려면 컴포넌트와 데이터를 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가 끝난 뒤에야 내용이 채워진다.

CSR 첫 화면, 로딩 뒤에 내용이 채워짐
  • 링크 미리보기나 크롤러도 빈 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

루프만 보면 대략 이렇다.

ISR 재생성 루프
  • 박스: 빌드 (미리 만들기)

  • 구름: 캐시에 올려 두기

  • 회전 화살표: 필요할 때 다시 굽기

  • 상품 목록이나 뉴스처럼, 자주 바뀌진 않는데 배포마다 전부 다시 빌드하기엔 무거운 페이지에서 손이 갔다.

  • CDN 속도는 유지하면서 내용을 주기적으로 갱신하고 싶을 때 유용하다.

  • 다만 잠깐 옛 내용이 보이는 stale(아직 갱신 전인 캐시) 구간이 생길 수 있고, revalidate나 on-demand 재생성을 같이 설계해야 한다. 여기부터는 캐시 감각이 좀 필요하다.


🎯 6. 고를 때 보는 기준.

페이지 전략을 고를 때는 이런 질문을 먼저 본다.

  • 이 페이지는 검색, 공유가 중요한가?

  • 데이터가 요청마다 달라져야 하나, 빌드 시점이면 되나?

  • 갱신은 분 단위인가, 하루 단위인가, 배포 때만인가?

  • 서버를 그만큼 돌려도 되나?

고를 때마다 이게 제일 고민이었다.

렌더링 타입 선택 기준

그래서 대략 이렇게 골랐다.

  • 로그인 후 앱 화면 → CSR (또는 혼합)

  • 개인화된 HTML이 당장 필요 → SSR

  • 거의 안 바뀌는 문서, 블로그 → SSG

  • 정적 속도는 유지하고 가끔만 갱신 → ISR


💡 7. 정리.

타입 이름은 결국 HTML을 만드는 시점의 별칭이다.

한 사이트 전체를 한 방식으로 묶기보다, 페이지마다 다르게 고르는 편이 맞았다. "우리 서비스는 SSR이다"보다 "이 페이지는 왜 SSR인가"가 더 쓸모 있었다.


🔗 8. 참고 자료.

이전 글
블로그 리리뉴얼.

댓글

불러오는 중...
목록으로