SSR, CSR 그리고 SSG 렌더링

이종경·2025년 6월 28일
0

Rendering

CSR (Client-Side Rendering)

CSR 방식은 서버가 최소한의 HTML 문서를 제공하고, 실제 콘텐츠 렌더링은 클라이언트에서 JavaScript로 수행하는 방식입니다. 주로 SPA(Single Page Application) 형태의 웹사이트에 널리 사용됩니다.

작동 원리 및 프로세스

  1. 초기 접속 시 서버는 빈 HTML과 JavaScript 파일을 클라이언트로 전송합니다.
  2. 클라이언트는 JavaScript를 실행하여 DOM을 동적으로 구성합니다.
  3. 추가적인 데이터 요청은 비동기 API 호출로 이루어지고, UI가 동적으로 업데이트됩니다.

CSR 장점

  • 동적 인터랙션과 뛰어난 사용자 경험 제공
  • 서버 자원 소모가 적고, 확장성이 뛰어남
  • 클라이언트 측 라우팅 및 상태 관리가 용이함

CSR 단점

  • 초기 로딩이 상대적으로 느림(JavaScript 로딩 및 실행)
  • SEO 성능 저하 가능성 (크롤러의 콘텐츠 수집 제한)
  • 자바스크립트 의존성이 큼
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>My React App</title>
    <script src="/static/js/bundle.js"></script>  <!-- 번들된 JS -->
  </head>
  <body>
    <div id="root"></div>  <!-- React가 렌더링될 컨테이너 -->
    <noscript>이 사이트는 JavaScript를 필요로 합니다.</noscript>
  </body>
</html>
import { createRoot } from 'react-dom/client';
import App from './App';

createRoot(document.getElementById('root')).render(<App />);

SSR (Server-Side Rendering)

SSR은 요청을 받을 때마다 서버가 HTML 콘텐츠를 동적으로 생성하여 클라이언트에 전달하는 방식으로, 초기 콘텐츠 표시가 매우 빠르고 SEO에 유리합니다.

작동 원리 및 프로세스

  1. 서버는 클라이언트 요청을 받은 후 HTML을 즉시 렌더링합니다.
  2. 생성된 HTML은 클라이언트로 전송되어 즉시 렌더링됩니다.
  3. 클라이언트에서는 JavaScript가 로딩된 후 hydration 과정을 통해 상호작용 가능한 상태로 만듭니다.

SSR 장점

  • 초기 로딩 속도가 뛰어나며 사용자 경험이 우수함
  • SEO 성능이 뛰어나 검색 엔진 크롤러가 즉시 콘텐츠를 수집 가능
  • 사용자 맞춤형 콘텐츠를 실시간으로 제공 가능

SSR 단점

  • 서버 부하가 증가하여 확장성 문제가 발생할 수 있음
  • 페이지 전환 시 전체 페이지가 재로딩되어 부드럽지 않은 UX 가능성
  • 프론트엔드와 백엔드 환경 설정과 관리 복잡성이 증가
import express from 'express';
import { renderToString } from 'react-dom/server';
import App from './App';

const app = express();
app.get('*', (req, res) => {
  const html = renderToString(<App />);
  res.send(`
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root">${html}</div>
        <script src="/bundle.js"></script>
      </body>
    </html>
  `);
});

app.listen(3000);

SSG (Static Site Generation)

SSG 방식은 빌드 과정에서 미리 모든 콘텐츠를 정적 HTML 파일로 생성하여 제공하는 방법입니다. 문서, 블로그, 마케팅 페이지 등 정적 콘텐츠 위주로 구성된 사이트에서 주로 사용됩니다.

작동 원리 및 프로세스

  1. 빌드 시 모든 콘텐츠를 HTML 파일 형태로 사전 생성합니다.
  2. 생성된 파일은 CDN 또는 정적 호스팅 서비스에 배포됩니다.
  3. 클라이언트 요청 시 사전 생성된 정적 HTML이 즉시 제공됩니다.

SSG 장점

  • 매우 빠른 초기 로딩 속도와 우수한 성능
  • 높은 SEO 최적화 성능
  • 트래픽 폭증에도 안정적 운영 가능

SSG 단점

  • 동적 데이터 반영이 어렵고 변경 시마다 재배포가 필요
  • 개인화된 콘텐츠 제공이 제한적
  • 대규모 사이트의 경우 빌드 시간이 오래 걸릴 수 있음
// pages/posts/[id].jsx (Next js)
export default function Post({ post }) {
  return <div>{post.title}</div>;
}

export async function getStaticPaths() {
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();
  const paths = posts.map(post => ({ params: { id: post.id } }));
  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`);
  const post = await res.json();
  return { props: { post } };
}

SSR에서 Hydration이 필요한 이유

Server-Side Rendering(SSR)은 초기 로딩 속도를 높이고 SEO(Search Engine Optimization)에 유리한 환경을 제공합니다. 그러나 서버에서 생성된 HTML은 기본적으로 정적이어서, 사용자와의 동적인 상호작용을 처리할 수 없습니다. 이를 보완하기 위해 등장한 것이 바로 Hydration입니다.

Hydration은 서버가 렌더링하여 클라이언트로 전달한 정적 HTML을 클라이언트 측 JavaScript와 연결하여 동적으로 만드는 과정입니다. 이 과정이 없으면 사용자는 화면을 보기는 하지만 버튼 클릭같은 기본적인 인터렉션을 수행할 수 없습니다.

React에서의 Hydration 작동 방식

React의 Hydration 과정은 크게 세 단계로 이루어집니다.

1. 가상 DOM과 실제 DOM 비교 (Reconciliation)

서버에서 받은 HTML과 클라이언트에서 생성한 가상 DOM(vDOM)을 비교하여, 서로 일치하는 부분은 재사용하고 일치하지 않는 부분은 재렌더링합니다.

2. 이벤트 리스너 연결 및 상태 관리

서버에서 내려온 HTML 요소에 React가 관리하는 이벤트 핸들러와 상태를 연결하여 상호작용 가능한 상태로 만듭니다.

3. 인터랙티브한 UI 활성화

Hydration이 완료되면, 사용자는 정적인 페이지가 아닌 완전히 동작 가능한 인터랙티브한 애플리케이션을 이용할 수 있게 됩니다.

React 18 이후 새롭게 도입된 Hydration 전략

Streaming SSR

페이지 전체가 준비될 때까지 기다리지 않고 HTML 콘텐츠를 조각(chunk) 단위로 나누어 스트리밍 형태로 클라이언트에 전달할 수 있습니다. 이를 통해 사용자는 더 빨리 콘텐츠를 확인할 수 있고, 일부 콘텐츠가 늦게 도착하더라도 사용자 경험에 큰 영향을 미치지 않습니다.

Selective Hydration

모든 콘텐츠를 한 번에 Hydration하지 않고 중요한 요소부터 우선적으로 Hydration합니다. 이를 통해 사용자가 실제로 보는 콘텐츠부터 빠르게 활성화되고, 나머지 요소는 필요에 따라 점진적으로 활성화됩니다.

Lazy Hydration

일부 콘텐츠의 Hydration을 사용자의 특정 행동(예: 스크롤, 클릭)까지 연기하는 전략입니다. 초기 로딩 속도를 높이고 전체 애플리케이션 성능을 효과적으로 향상시킬 수 있습니다.

Hydration 성능 최적화 기법

Partial Hydration

페이지 전체를 Hydration할 필요 없이, 인터랙티브한 부분만 Hydration하고 정적인 부분은 그대로 둠으로써 성능 부담을 최소화합니다.

Progressive Hydration

페이지를 한 번에 Hydration하지 않고 중요도에 따라 순차적으로 처리합니다. 주요 콘텐츠는 즉시 Hydration하고, 덜 중요한 콘텐츠는 사용자의 브라우저가 유휴 상태일 때 처리하여 성능 효율성을 극대화합니다.

Islands Architecture

페이지를 독립적인 UI 모듈(섬)로 나누어 각 섬이 독자적으로 Hydration을 수행하도록 합니다. 이를 통해 각 컴포넌트가 서로 독립적으로 동작하며, 전체 페이지 성능이 개선됩니다.

참고
Server-side Rendering (SSR)
SPA와 SSG, 그리고 SSR
웹에서 렌더링
Next.js의 Hydrate란?
React의 hydration mismatch 알아보기
Understanding React Hydration
react hydration test case

profile
작은 성취들이 모여 큰 결과를 만든다고 믿으며, 꾸준함을 바탕으로 개발 역량을 키워가고 있습니다

0개의 댓글