본문 바로가기
IT/nextjs 기초 내 공부

쉬운 NextJs 05 : 서버 컴포넌트의 렌더링 프로세스 심층 분석

by higold 2024. 11. 12.
728x90
SMALL

Next.js 서버 컴포넌트의 렌더링 프로세스 심층 분석

목차

  1. 서론
  2. 컴포넌트의 기본 개념
  3. 서버 컴포넌트 렌더링 프로세스
  4. 실제 예제로 보는 렌더링 과정
  5. 결론

서론

Next.js의 서버 컴포넌트는 React 18에서 도입된 혁신적인 기능으로, 서버 사이드 렌더링의 장점을 최대한 활용하면서도 클라이언트의 인터랙티브한 특성을 유지할 수 있게 해줍니다. 이 글에서는 서버 컴포넌트의 렌더링 과정을 상세히 살펴보고, 실제 작동 방식을 코드 예제와 함께 이해해보도록 하겠습니다.

컴포넌트의 기본 개념

React 컴포넌트는 기본적으로 다음과 같은 특성을 가집니다:

// 기본적인 React 컴포넌트의 구조
function Component(props) {
  // 데이터를 인자로 받음 (props)
  // 내부 상태 관리 (state)
  return (
    // JSX를 반환
    <div>컴포넌트 내용</div>
  );
}

이러한 컴포넌트가 렌더링될 때는 다음과 같은 과정을 거칩니다:

  1. JSX → React.createElement (Babel 변환)
  2. React Element (JavaScript 객체) 생성
  3. Fiber 노드로 확장
  4. Virtual DOM 구성

서버 컴포넌트 렌더링 프로세스

서버 컴포넌트의 렌더링은 크게 두 부분으로 나뉩니다:

1. 서버 사이드 프로세스

// 서버 컴포넌트
function ServerComponent() {
  return (
    <div>
      <h1>서버에서 렌더링된 내용</h1>
      <ClientComponent /> {/* 클라이언트 컴포넌트를 위한 플레이스홀더 */}
    </div>
  );
}

서버에서 일어나는 일:

  1. React가 서버 컴포넌트를 RSC(React Server Component) Payload로 변환
  2. Next.js가 이 RSC Payload와 클라이언트 컴포넌트 JavaScript 인스트럭션을 사용하여 초기 HTML 생성

2. 클라이언트 사이드 프로세스

'use client';

// 클라이언트 컴포넌트
function ClientComponent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>증가</button>
    </div>
  );
}

클라이언트에서 일어나는 일:

  1. 초기 HTML을 즉시 표시 (Preview)
  2. RSC Payload를 사용하여 클라이언트/서버 컴포넌트 트리 재구성 (Reconciliation)
  3. JavaScript 인스트럭션을 사용한 하이드레이션 (Hydration)

실제 예제로 보는 렌더링 과정

아래는 실제 Next.js 애플리케이션에서의 예제입니다:

// app/page.js
import ClientComponent from './ClientComponent';

export default function HomePage() {
  return (
    <div className="container">
      <h1>Next.js 서버 컴포넌트 예제</h1>
      <ClientComponent />
    </div>
  );
}

// app/ClientComponent.js
'use client';

import { useState } from 'react';

export default function ClientComponent() {
  const [value, setValue] = useState(0);

  return (
    <div>
      <p>현재 값: {value}</p>
      <button onClick={() => setValue(v => v + 1)}>
        증가
      </button>
    </div>
  );
}

이 코드가 실행될 때의 프로세스를 단계별로 살펴보겠습니다:

  1. 서버 렌더링 단계
  2. <!-- 서버에서 생성된 초기 HTML --> <div class="container"> <h1>Next.js 서버 컴포넌트 예제</h1> <div> <p>현재 값: 0</p> <button>증가</button> </div> </div>
  3. RSC Payload 생성
    • 서버 컴포넌트 렌더링 결과
    • 클라이언트 컴포넌트 플레이스홀더
    • 자바스크립트 파일 참조
  4. 하이드레이션
  5. // 클라이언트 측 JavaScript 번들에 포함되는 코드 __webpack_require__.r(__webpack_exports__); // ... (번들링된 코드)

빌드 결과물 구조

Next.js 빌드 후 생성되는 주요 파일들:

.next/
  ├── static/
  │   ├── chunks/
  │   │   ├── app/
  │   │   │   └── page-[hash].js  // 페이지별 청크
  │   │   └── [hash].js           // 공통 청크
  │   └── [buildId]/
  └── server/
      └── app/
          └── page.js             // 서버 컴포넌트

결론

Next.js의 서버 컴포넌트 렌더링 프로세스는 서버와 클라이언트의 장점을 최대한 활용하는 혁신적인 방식을 제공합니다. 서버에서의 초기 렌더링과 클라이언트에서의 하이드레이션을 통해 빠른 초기 로딩과 풍부한 인터랙션을 모두 달성할 수 있습니다.

참고 문헌

  1. Next.js 공식 문서 - Server Components
  2. React 공식 문서 - Server Components
  3. Dan Abramov의 Server Components 설명
  4. Vercel Engineering Blog
728x90
LIST