⚙️ React Hydration: 내부 단계별 작동 메커니즘

김진서·2025년 10월 29일

우아한테크코스 7기

목록 보기
56/56
post-thumbnail

🎯 기본 개념 정리

🧱 Fiber란?

React 16 이후, React는 “Fiber”라는 내부 구조를 도입했습니다.
이는 컴포넌트 트리를 표현하는 메모리 구조체(virtual tree)이며, 하이드레이션은 바로 이 Fiber 트리를 “서버에서 미리 만들어진 DOM 노드”와 동기화하는 과정입니다.

SSR에서 HTML은 이미 렌더링되어 있으므로, 클라이언트는 새로 만드는 대신 기존 노드에 Fiber를 연결(hydrate)해야 함.


🪄 Hydration 전체 단계 개요

하이드레이션은 ReactDOM.hydrateRoot()(React 18 이후 기준)로 시작합니다.

ReactDOM.hydrateRoot(container, element)

이 호출은 대략 다음 6단계를 거칩니다.

단계이름핵심 동작관련 코드 경로 (react-dom 내부)
1️⃣Container 초기화서버에서 받은 HTML 루트 찾기ReactDOMRoot.createRootImpl()
2️⃣Fiber Tree 생성Virtual Fiber Tree 구성createFiberFromTypeAndProps()
3️⃣Hydration Queue 생성미리 존재하는 DOM과 매칭 준비prepareToHydrateHostInstance()
4️⃣ReconciliationFiber와 기존 DOM을 비교(diff 없이 attach)hydrateInstance(), hydrateTextInstance()
5️⃣Commit Phase이벤트 핸들러, ref, effect 복원commitRoot()
6️⃣Post-hydration UpdateuseEffect, useLayoutEffect 실행flushPassiveEffects()


1️⃣ Container 초기화

목표: SSR에서 생성된 루트 DOM 노드를 찾고, 하이드레이션 모드로 렌더링 준비.

const root = ReactDOM.hydrateRoot(document.getElementById('root'), <App />);

이 시점에서 React는

  • document.getElementById('root') 아래의 모든 노드가 “SSR로 렌더링된 HTML”임을 가정합니다.
  • 새로운 <App />을 렌더링하기 위한 Fiber Root 객체를 만듭니다.
  • hydrate 플래그를 true로 설정합니다.

이 플래그는 React 내부에서 “새로 DOM을 만들지 말고, 기존 것을 재활용하라”는 신호로 작동합니다.


2️⃣ Fiber Tree 생성 (Virtual Fiber)

React는 App 컴포넌트를 재귀적으로 순회하며 Fiber Tree를 생성합니다.

  • 각 컴포넌트마다 Fiber 노드가 만들어지고
  • 각 Fiber에는 다음 정보가 포함됩니다:
필드의미
type함수/클래스/HTML 태그
pendingProps렌더링 시점의 props
stateNode실제 DOM 노드 참조
return부모 Fiber
child / sibling트리 구조
flagsupdate / placement / hydration 등 상태

이 Fiber Tree는 아직 실제 DOM과 연결되지 않은 가상 구조에 불과합니다.


3️⃣ Hydration Queue 생성

이제 React는 “hydration queue”라는 내부 구조를 만들어서 SSR에서 이미 존재하는 DOM 노드들을 순차적으로 읽어가기 시작합니다.

  • React는 첫 번째 DOM 노드를 hydrationParentFiber로 설정
  • DOM 트리를 순회하며 다음 노드를 하나씩 “hydrate 대상”으로 push

📦 핵심 함수: prepareToHydrateHostInstance() → DOM 노드를 Fiber와 매칭할 준비를 함.

이 시점에서는 아직 이벤트 핸들러도, ref도, state도 연결되지 않았습니다.
그냥 HTML element의 형태와 순서를 검증 중이에요.


4️⃣ Reconciliation 단계 (실제 하이드레이션)

이제 진짜 하이드레이션이 일어납니다.

서버에서 만들어진 DOM과 클라이언트의 Virtual Fiber를 하나씩 대응시킵니다.

  • React는 각 Fiber의 type과 기존 DOM 노드의 nodeName을 비교
    <div> Fiber는 <div> DOM과 연결
    <span> Fiber는 <span> DOM과 연결
    → 불일치하면 “hydration mismatch warning” 출력

  • TextNode인 경우:
    → SSR HTML의 텍스트와 props.children 문자열을 비교
    → 다르면 hydrateTextInstance()에서 mismatch 처리

📦 내부 주요 함수:

hydrateInstance(fiber, domNode);
hydrateTextInstance(fiber, textNode);
  • 성공 시: fiber.stateNode = domNode
  • 실패 시: 경고 출력 후, DOM을 새로 렌더링하는 fallback 모드로 전환

즉, 이 단계에서 React는 기존 DOM을 파괴하지 않고 “붙이기만” 합니다.


5️⃣ Commit Phase (이벤트/Ref 복원)

하이드레이션의 마지막 핵심 단계입니다.

이제 DOM과 Fiber가 매칭되었으니, React는 “활성화”를 시작합니다.

  • 이벤트 리스너 바인딩 (onClick, onChange 등)
  • Ref 객체 연결 (ref.current = domNode)
  • 클래스형 컴포넌트의 lifecycle 메서드 복원
  • Suspense boundary 복구

📦 관련 코드:

commitRoot(root);
commitMount();

이제 이 시점부터, 클라이언트는 기존 HTML을 “React 트리”로 완전히 제어할 수 있게 됩니다.
즉, “hydrated” 상태가 된 거예요.


6️⃣ Post-hydration Updates (Effects 실행)

이제 useEffect()componentDidMount() 같은 비동기 후처리 로직이 실행됩니다.

  • 이 단계는 브라우저 페인트 이후에 이루어짐
  • React는 내부적으로 flushPassiveEffects()를 통해 모든 side-effect를 수행

이제 화면이 완전히 살아나고, 유저 이벤트를 받을 준비가 끝납니다. 🎉


⚠️ Hydration Mismatch가 발생하는 경우

아래와 같은 경우에 mismatch 경고가 발생합니다.

원인예시결과
서버와 클라이언트의 랜덤 값 차이<div>{Math.random()}</div>DOM 리렌더링
날짜, 시간 값 다름<div>{new Date().toLocaleTimeString()}</div>mismatch 경고
조건부 렌더링 불일치서버는 A, 클라이언트는 B 렌더링fallback to client render

React는 mismatch를 발견하면 “soft fallback”으로 전환합니다.
→ 기존 DOM을 버리고 다시 렌더링함.

즉, 다시 복구되지만 다른 버그들과 같이 반드시 고쳐줘야 합니다. 가장 나은 경우는 그저 느려지기만 할 뿐이지만, 최악의 경우엔 이벤트 핸들러가 다른 요소(Element)에 붙어버립니다.


🧠 React 18 이후: Selective Hydration

React 18은 하이드레이션 전체를 병렬 처리할 수 있도록 개선했습니다.

  • Suspense boundaries 단위로 하이드레이션 가능
  • Interaction이 발생한 부분부터 우선 하이드레이션
  • Streaming SSR과 결합하면, HTML이 점진적으로 “활성화”

📦 내부적으로는 ReactDOMServer.stream()hydrateRoot() 간의 “token stream”으로 연결됨.

즉, Hydration이 더 이상 전체 페이지 단위가 아니라, 트리 일부 단위로 분산 수행됩니다.


🧬 요약 및 정리

(SSR) HTML 전달
      ↓
[Step 1] hydrateRoot() 호출
      ↓
[Step 2] Fiber Tree 생성
      ↓
[Step 3] DOM과 Fiber 매칭 (hydrateInstance)
      ↓
[Step 4] 이벤트/Ref 복원
      ↓
[Step 5] useEffect 실행
      ↓
🎉 페이지 완전 활성화
개념설명
HydrationSSR로 만들어진 HTML에 Fiber 트리를 연결해 JS 이벤트/상태를 복원하는 과정
Fiber TreeReact 내부에서 컴포넌트 구조를 메모리로 표현하는 트리 구조
Hydration Queue기존 DOM을 순회하면서 Fiber를 하나씩 attach하는 대기열
Selective HydrationSuspense boundary 단위로 병렬/부분 하이드레이션
Mismatch서버와 클라이언트 렌더 결과가 다를 때 발생 (React가 DOM 재생성으로 대응)

🧩 레퍼런스

profile
PAy IT forwaRD를 실천하는 프론트엔드 개발자.

0개의 댓글