SSR과 Server Component(RSC) 이해하기

2025. 11. 3. 18:29·Frontend/Next.js

Next.js와 React 18+ 환경에서 SSR(Server-Side Rendering) 과 Server Component(RSC) 의 차이를 정확히 이해하는 것은 성능 최적화와 클라이언트 번들 최소화 측면에서 매우 중요하다. 많은 개발자가 혼동하는 영역이므로, 핵심 개념과 예제 코드를 중심으로 깔끔하게 정리한다.

 

1. SSR (Server-Side Rendering)

1. 정의

SSR은 클라이언트의 요청 시점마다 서버에서 HTML을 생성해 전달하는 방식이다. Next.js의 App Router 환경에서는 getServerSideProps 대신 fetch의 cache: 'no-store' 옵션을 사용하여 SSR을 구현한다. 

2. 작동 방식

  1. 클라이언트가 페이지(URL)를 요청한다.
  2. Next.js 서버는 해당 요청 시점에 React 컴포넌트를 실행하고, HTML을 서버에서 생성한다.
  3. 생성된 HTML이 클라이언트로 전송되어 초기 화면이 즉시 표시된다.
  4. 이어서 JS 번들이 로드되고, React가 서버에서 렌더된 HTML과 클라이언트 렌더 트리를 비교하여 Hydration(하이드레이션) 을 수행한다 — 즉, 이벤트 핸들러와 상태를 연결해 인터랙션을 활성화한다.

3. 특징

  • 페이지 단위로 서버 렌더링을 수행한다.
  • 서버에서 데이터를 호출하여 HTML에 반영할 수 있다.
  • HTML과 JS 번들이 모두 클라이언트로 전달된다.
  • SEO 최적화와 초기 로딩 속도 개선에 유리하다.

4. 예제 코드 (App Router 방식)

cache: 'no-store'를 사용하면 Next.js는 이 fetch를 요청마다 새로 실행하여, 기존 getServerSideProps와 동일한 SSR 효과를 낸다.

// app/page.tsx
export default async function Page() {
  // ✅ SSR: 요청 시마다 서버에서 새로 실행
  const res = await fetch('https://api.example.com/posts', {
    cache: 'no-store', // SSR 방식
  });

  const posts = await res.json();

  return (
    <main>
      <h1>서버 사이드 렌더링 (SSR)</h1>
      <ul>
        {posts.map((post: any) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </main>
  );
}

5. ISR(Incremental Static Regeneration) 버전

ISR은 “매 요청마다”가 아니라 “일정 시간마다” 서버에서 새로 렌더링한다.

export default async function Page() {
  // ✅ ISR: 일정 주기마다 서버에서 페이지를 재생성
  const res = await fetch('https://api.example.com/posts', {
    next: { revalidate: 60 }, // 60초마다 새로 생성
  });

  const posts = await res.json();

  return (
    <main>
      <h1>ISR (부분적 SSR)</h1>
      <ul>
        {posts.map((post: any) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </main>
  );
}

 

2. Server Component (RSC, ‘use server’)

1. 정의

Server Component는 React 18+에서 도입된 서버 전용 컴포넌트로, 클라이언트로 JS 번들을 거의 보내지 않고 서버에서만 렌더링되는 구조를 가진다. 인터랙션 없는 컴포넌트에 최적화되어 있다.

2. 작동 방식

  1. 서버에서 React Server Component를 실행한다.
  2. HTML과 직렬화된 Props만 클라이언트로 전달한다.
  3. 클라이언트는 이 HTML을 그대로 렌더링하며, 필요한 경우 'use client' 컴포넌트와 결합해 인터랙션을 추가한다. — 즉, 인터랙션이 필요하면 Server Component 안에 'use client' 컴포넌트를 섞어서 사용하면 된다.

3. 특징

  • 컴포넌트 단위로 서버 렌더링을 수행한다.
  • 서버에서 DB나 API를 직접 호출할 수 있다.
  • 클라이언트 JS 번들을 최소화해 성능을 극대화한다.
  • 클라이언트와 서버 간 경계가 명확하여 데이터 접근이 안전하다.

4. 예제 코드 (Next.js App Router)

Server Component는 클라이언트에서 조작이 필요 없는 컴포넌트를 서버에서만 렌더링하여 클라이언트 번들을 최소화한다.

// app/components/ServerMessage.tsx
'use server';

async function getServerData() {
  const res = await fetch('https://api.example.com/data', { cache: 'no-store' });
  return res.json();
}

export default async function ServerMessage() {
  const data = await getServerData();

  return (
    <div>
      <h2>Server Component 예제</h2>
      <p>서버에서 받아온 데이터: {data.message}</p>
    </div>
  );
}
// app/page.tsx
import ServerMessage from './components/ServerMessage';

export default function Page() {
  return (
    <main>
      <h1>Next.js Server Component</h1>
      <ServerMessage /> {/* 클라이언트 JS 최소화 */}
    </main>
  );
}

 

3. SSR vs Server Component 비교 정리

구분 SSR Server Component (RSC)
렌더링 단위 페이지 단위 컴포넌트 단위
렌더링 시점 요청마다 (cache: ‘no-store’) 빌드 또는 요청 시 서버 실행
데이터 호출 서버 가능 서버 가능
클라이언트 JS HTML + JS 번들 전달 HTML + Props만 전달 (JS 최소)
목적 SEO, 초기 로딩 속도 개선 성능 최적화, JS 번들 최소화
상호작용 Hydration으로 추가 가능 'use client' 컴포넌트와 조합
대표 코드 fetch(..., { cache: 'no-store' }) 'use server' 함수 또는 기본 Server Component

 

4. 핵심 요약

  • SSR은 요청마다 서버에서 HTML을 새로 생성하며, 클라이언트로 JS 번들을 함께 전달한다. → SEO와 초기 로딩 속도를 개선하는 데 적합하다.
  • Server Component는 컴포넌트 단위로 서버에서 렌더링하며, 클라이언트로 HTML과 Props만 전달해 번들 크기를 극적으로 줄인다. → 서버 데이터 접근이 많은 대규모 애플리케이션의 성능을 최적화한다.
  • App Router 환경에서 SSR을 구현하려면 fetch(..., { cache: 'no-store' }) 또는 next: { revalidate: 0 } 옵션을 사용한다.

'Frontend > Next.js' 카테고리의 다른 글

Next.js 14 & React - The Complete Guide  (0) 2024.12.14
'Frontend/Next.js' 카테고리의 다른 글
  • Next.js 14 & React - The Complete Guide
JTB
JTB
웹/앱 개발 정보를 공유하고 있습니다.
  • JTB
    JTechBlog
    JTB
  • 전체
    오늘
    어제
    • All About Programming;)
      • Computer Science
        • Terminology and Concepts
        • Network
        • Operating System
        • Database
        • Data Structure
        • Web Development
      • Frontend
        • Javascript Essentials
        • Perfomance Optimization
        • JS Patterns
        • React
        • Next.js
        • Flutter
        • Testing
      • Backend
        • Node.js
      • DevOps
        • Docker & Kubernetes
      • Coding Test
        • LeetCode
        • Programmers
      • Tech Books & Lectures
        • Javascript_Modern JS Deep d..
        • Network_IT 엔지니어를 위한 네트워크 입문
      • Projects
        • PolyLingo_2025
        • Build Your Body_2024
        • JStargram_2021
        • Covid19 Tracker_2021
        • JPortfolio_2021
      • BootCamp_Codestates
        • TIL
        • TILookCloser
        • Pre Tech Blog
        • IM Tech Blog
        • Daily Issues and DeBugging
        • First Project
        • Final Project
        • Sprint Review
        • Good to Know
        • Socrative Review
        • HTML &amp; CSS
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 글쓰기
    • 관리
  • 공지사항

  • 인기 글

  • 태그

    need a database
    testing
    딥다이브
    structure of os
    Shared resources
    TCP/IP
    Data Structure
    Threads and Multithreading
    CPU scheduling algorithm
    VoiceJournal
    프론트엔드 성능 최적화 가이드
    leetcode
    How memory manage data
    Time complexity and Space complexity
    커리어
    자바스크립트
    DOM
    Operating System
    Javascript Essentials
    polylingo
    js pattern
    Binary Tree BFS
    indie hacker
    mobile app
    자바스크립트 딥다이브
    모던 자바스크립트 Deep Dive
    database
    Network
    스코프
    이벤트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
JTB
SSR과 Server Component(RSC) 이해하기
상단으로

티스토리툴바