React Hydration, hydrateRoot

2023. 5. 19.·🎨 프론트엔드 공부/React & Next

📍React에서 Hydrate란?

✅Hydrate의 사전적 의미: 수화 (예 - 메마른 꽃에 물을 줘서 생기있게 만드는 것)
서버 사이드 렌더링된 HTML을 클라이언트 사이드에서 enhance하여 feature를 가진 App 형태로 완성시키는 것
enhance 내용 : 상태(state), interaction 등을 추가

 

 

📍hydrateRoot API

✅createRoot와 비슷

hydrateRoot 를 호출하여 서버 환경에서 이미 렌더링된 기존 HTML(domNode)에 React(reactNode)를 부착

 

import { hydrateRoot } from 'react-dom/client';

const domNode = document.getElementById('root');
const root = hydrateRoot(domNode, reactNode); // render, unmount가 포함된 객체 반환
// domNode : 서버 사이드 렌더링된 DOM Element
// reactNode : 클라이언트 사이드에서 생성된 JSX

 
- 부착 후 domNode 이하의 DOM을 React가 관리하게 됨
- root 엘리먼트에 대해 hydrateRoot를 1번만 호출 (Next.js 에서는 Next가 대신 호출)
 

📍주의사항

- hydrateRoot() 가 hydrate 시작 전, DOM element가 다르면 버그로 인식 (개발 환경에서 동일하지 않은 부분을 경고)

예) Next.js 에서 Styled-components 라이브러리를 사용할 때, css-in-js 특성 상 프리렌더링과 동시에 style이 적용되지 않으므로 hydration error가 발생

 


- 마크업이 동일하지 않는 경우는 거의 없다
- 모든 마크업을 비교하는 것은 리소스 소모가 큼
- 프리렌더링된 HTML이 없는 경우, hydrateRoot()를 사용할 수 없고, 대신 createRoot()를 사용해야 함

 

⭐Next.js는 root element render 시 createRoot() 대신 hydrateRoot()를 사용

- 코드 내에 createRoot() 없고 대신 hydrateRoot() 호출

 

📍root.render(reactNode)

✅root.render를 호출하여 Hydrate된 내부 컴포넌트를 React 컴포넌트(<App />)로 업데이트

root.render(<App />);

 

hydrate가 끝나기 전에 root.render를 호출하면 React는 서버에서 렌더링된 HTML을 모두 없애고 클라이언트에서 렌더링된 컴포넌트들로 완전히 교체

 

📍root.unmount(reactNode)

✅root.unmount를 호출하여 React root 하위의 렌더링된 트리를 삭제

- 루트 내부의 모든 컴포넌트를 umount하며, 루트 DOM 노드에서 React를 떼어내는 기능

- 모든 이벤트 핸들러와 state를 DOM에서 제거

- React로 이루어진 앱에서는 쓸 일이 거의 없음 (jQuery와 React가 혼용된 앱의 경우 사용할 수 있음)

root.unmount();

 

📍서버에서 렌더링된 HTML을 hydrate

✅pre-render 된 HTML을 React component인 <App /> 으로 교체하여 interactive한 App으로 Hydrate

- 앱 실행할 때 최초 1번만 수행

- 프레임워크를 사용중이라면 프레임워크가 알아서 수행 (Next.js 등)

import { hydrateRoot } from 'react-dom/client';

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

 

이 때, hydrateRoot에 전달한 React 트리(index.html)는 서버에서 만들었던 React Tree 결과물(App.js)과 동일해야 함

- 프리렌더링의 목적이 빠른 화면 로딩을 통해 유저의 경험을 개선하는 것이므로,

index.html(HTML + CSS) 의 화면과 App.js의 화면은 동일해야 함

- HTML + CSS만 먼저 뿌려주고, CSR로 완성된 App.js 에서 state와 interaction을 추가

 

 

 

📍문서 전체를 hydrate

✅앱을 React로만 작성한 경우, <html> 태그를 포함한 JSX로 전체 문서를 렌더링할 수 있음

- 이 때는, 전역 변수인 document를 hydrateRoot() 의 첫 번째 인자로 넘겨줌

(Next.js의 _document 역할)

 

App.js: React로만 작성된 앱

function App() {
  return (
    <html>
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="stylesheet" href="/styles.css"></link>
        <title>My app</title>
      </head>
      <body>
        <Router />
      </body>
    </html>
  );
}

 

index.js: document를 받아 Hydrate 역할을 수행

import { hydrateRoot } from 'react-dom/client';
import App from './App.js';

hydrateRoot(document, <App />);

 

📍불가피한 hydration 에러 억제

현재 시간을 렌더링하는 앱의 경우, 빌드타임에 프리렌더링하는 현재 시간과 hydration 시의 현재 시간의 텍스트 컨텐츠가 다를 수 있음

이 때, suppressHydrationWarning attributes를 추가하여 warning을 방지할 수 있음

- 한 단계 아래까지만 적용되는 임시방편적 방법

- 텍스트 컨텐츠에 대해서만 사용 가능

 

export default function App() {
  return (
    <h1 suppressHydrationWarning={true}>
      Current Date: {new Date().toLocaleDateString()}
    </h1>
  );
}

 

⭐서버와 클라이언트에서 다른 내용을 렌더링하려면, useEffect를 사용하면 됨

 

📍참고

https://react.dev/reference/react-dom/client/hydrateRoot

 

hydrateRoot – React

The library for web and native user interfaces

react.dev

 
https://www.gatsbyjs.com/docs/conceptual/react-hydration/

 

Understanding React Hydration | Gatsby

One of the central ideas of Gatsby is that HTML content is statically generated using React DOM server-side APIs. Another key feature is…

www.gatsbyjs.com

 

'🎨 프론트엔드 공부/React & Next' 카테고리의 다른 글
  • React createPortal
  • React createRoot
  • React(Next.js) 에서 이미지 입력받기
  • [React Docs] React 방식으로 생각하기 (2)
지식물원
지식물원
지식이 자라는 식물원!
  • 지식물원
    지식물원
    지식물원
  • 전체
    오늘
    어제
    • 분류 전체보기 (516)
      • 🎨 프론트엔드 공부 (253)
        • JS & TS (92)
        • HTML & CSS (22)
        • React & Next (49)
        • Vue & Nuxt (22)
        • 기타 (68)
      • 🤓 기술 학습 & 공부 기록 (116)
        • Node.js (0)
        • Python (37)
        • 백엔드 (0)
        • 딥러닝 (1)
        • 컴퓨터 일반 (72)
        • 개발 인프라 (6)
      • 👨‍💻 프로젝트 경험 (6)
        • Work (0)
        • Toy (6)
      • ⚙️ 개발 팁 & 노하우 (21)
        • 프론트엔드 (6)
        • 기타 (15)
      • ☕️ 커리어 & 인터뷰 준비 (88)
        • 코딩 테스트 (88)
      • 📰 기술 트렌드 & 생각 정리 (4)
      • 📚 기타 (25)
        • 마케팅 (15)
        • 비개발서적 (10)
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

    • 모바일 접속 시 코드 하이라이팅 깨질 때
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
지식물원
React Hydration, hydrateRoot
상단으로

티스토리툴바