React Dom이란? (+ hydrate를 써야 하는 이유!)

글은 React 공식 문서를 해석하고, hydrate를 써야하는 이유를 살펴봅니다.

TL;DR ► render는 리렌더링을 일으키고 hydrate는 일으키지 않습니다. 따라서 SSR을 위해서 hydrate를 쓰라고 공식문서에서 말해줍니다.

1. ReactDOM 이란?

If you load React from a script tag, these top-level APIs are available on the ReactDOM global. If you use ES6 with npm, you can write import ReactDOM from 'react-dom'. If you use ES5 with npm, you can write var ReactDOM = require('react-dom').

► script tag 으로부터 리액트를 로드하면 최상위 API를 ReactDOM 전역에서 사용할 수 있습니다.

► 그냥 ReactDOM을 전역에서 사용할 수 있다고 하는 것 같습니다. react-dom 을 임포트한다면 말이지요.

🤸‍♀️ 개요

The react-dom package provides DOM-specific methods that can be used at the top level of your app and as an escape hatch to get outside of the React model if you need to. Most of your components should not need to use this module.

► 이 react-dom 패키지는 앱의 최상위 수준에서 사용할 수 있는 DOM 관련 메서드를 제공한다고 합니다. 필요하다면 React 모델 외부로도 나갈 수 있는 탈출구를 제공한다고 하네요!

🤸‍♀️ 브라우저 지원

React supports all popular browsers, including Internet Explorer 9 and above,

► IE9 및 IE 10 이전 버전은 폴리필을 해야하는데, 엥간하면 이런 방식을 쓰지 말고 최신 브라우저를 쓰라는 말투입니다.


2. render() 함수

ReactDOM.render(element, container[, callback])

Render a React element into the DOM in the supplied container and return a reference to the component (or returns null for stateless components).

► element는 우리가 짠 React 코드이며 이를 container라는 곳의 DOM에 렌더링해준다고 합니다. 그리고 무려 해당 컴포넌트의 참조를 반환한다고 합니다. 참조를 반환한다는 것은 해당 컴포넌트를 가리키는 정보를 제공하는 듯합니다.

If the React element was previously rendered into container, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React element.

► React 요소가 이전에 렌더링이 되었다면, 그 것은 업데이트를 수행하고 최신 React 요소를 반영하는 데에 "필요한 만큼만" DOM을 변경한다고 합니다.

If the optional callback is provided, it will be executed after the component is rendered or updated.

► 콜백이 제공되는 경우 이는 구성 요소가 렌더링되거나 업데이트가 되면 실행된다고 합니다.

🔆 Note!
ReactDOM.render() controls the contents of the container node you pass in. Any existing DOM elements inside are replaced when first called. Later calls use React’s DOM diffing algorithm for efficient updates.

► 전달되는 컨테이너 "노드"의 내용을 제어합니다. 내부에 있던 기존 DOM은 처음 호출될 때 교체됩니다. 이후의 호출들은 효과적인 업데이트를 위해서 "diffing 알고리즘"을 사용합니다.

ReactDOM.render() does not modify the container node (only modifies the children of the container). It may be possible to insert a component to an existing DOM node without overwriting the existing children.

► 컨테이터 노드를 수정하지 않고 컨테이너의 자식만 수정합니다. 기존 자식을 덮어쓰지 않고도 기존 DOM 노드에 구성요소를 삽입할 수 있습니다.

ReactDOM.render() currently returns a reference to the root ReactComponent instance. However, using this return value is legacy and should be avoided because future versions of React may render components asynchronously in some cases. If you need a reference to the root ReactComponent instance, the preferred solution is to attach a callback ref to the root element.

► 현재 루트 컴포넌트의 인스턴스에 대한 참조를 반환합니다. 그런데 이 반환 값을 사용하는 것은 레거시(예전에 구현된 것이며 현재는 안 사용된다는 뜻인듯 합니다)이며, 향후 버전에서는 구성 요소를 비동기식으로 렌더링 할 예정이 있으므로 더욱 피해야 합니다.

Using ReactDOM.render() to hydrate a server-rendered container is deprecated and will be removed in React 17. Use hydrate() instead.

► ⭐️ 이제 이 render() 는 앞으로 사용되지 않을 것이며 React 17에서는 아예 삭제(!) 시켜 버릴 것입니다. 앞으로는 hydrate()을 써야 합니다. ⭐️


3. hydrate() 함수란?

< 이 부분은 심심재님의 글을 다수 발췌했습니다 (링크) >

hydrate는 해석하면 "수화하다"라는 뜻입니다. 수화라는 말은 우리 몸에 수분을 보충하는 행위이지요. react에서 왜 hydrate라는 용어를 사용하게 되었을까요?

위에서 살펴본 render 함수는 react element를 렌더링하는 함수입니다. 이 render함수는 컨테이너의 자식으로 리액트 컴포넌트를 넣어준다고 했습니다. 기존에 이미 렌더링 된 리액트 컴포넌트가 있다면 새로 렌더링 하는 것이 아니라 업데이트만 해주고요.

반면에 hydrate라는 메서드를 살펴봅니다.

함수 살펴보기

ReactDOM.hydrate(element, container[, callback

코드를 확인해봅니다. render와 모양이 똑같습니다. 그렇다면 왜 react에서는 render대신에 hydrate을 사용하라고 할까요? 

hydrate는 렌더링을 하지 않고 이벤트 핸들러만 붙여줍니다. 

서버사이드렌더링을 해서 이미 마크업이 채워져있는 경우에는 굳이 render 메소드를 사용할 필요가 없습니다. SSR을 하는 경우에는 hydrate로 콜백만 붙여야 합니다.

CSR(Client Side Rendering)을 하는 경우에는 타겟 컨테이너에 리액트 컴포넌트가 렌더링 된 적이 없을것이기 때문에 render메소드를 사용해야 합니다. CSR은 자바스크립트 코드가 도착하기 전에 빈화면이었다가, 렌더링을 한 후 우리가 원하는 UI를 보여주기 때문이지요.

하지만 SSR 프레임워크와 함께 리액트를 사용할때는 hydrate 사용을 고려해야 합니다. 여기서 말하는 hydrate는 좁은 의미의 hydrate입니다. 위에서 hydrate를 수분 보충으로 표현 했습니다. 아래 이미지를 보면 hydrate가 뭔지 좀 더 잘 이해가 될 것 입니다.

서버가 완성된 HTML을 내려줍니다. 이때 Dehydrate는 수분을 없앤다는 뜻입니다. 다시 말해서 동적인것을 정적으로 만드는 행위를 Dehydrate라고 표현했습니다. 그리고 나서 JS가 실행되면서 리액트가 정적인 HTML과 store를 동적인 리액트 컴포넌트 트리와 store로 변환하는 과정이 일어나는데, 이걸 (Re)hydrate라고 합니다. 마치 수분기 없는 정적인 상태에서 수분 넘치는 동적인 상태로 변화한것입니다.

문제는 이렇게 rehydrate가 일어나면서 쓸데없이 화면이 한번더 그려지는 현상이 발생한다는것입니다. 왜냐면 리액트는 서버에서 완성된 HTML이 내려와서 이미 화면에 제대로 렌더링이 됬는지 안됬는지 모르고 자신이 할일을 그냥 했을 뿐입니다. 서버에서 내려준 HTML로 렌더링 된 화면은 그냥 단순히 그림일 뿐입니다. 리액트가 관리하지 않는 화면입니다. 그래서 SSR을 하는 경우에는 ReactDom의 render메소드가 아니라 hydrate 메소드를 사용해야 합니다.

결론적으로 hydrate 메서드는 render메서드와 달리 렌더링을 해주는 것이 아닌 이벤트 핸들러를 붙여주는 메서드이기 때문에, SSR에서 필요합니다. react에서 render 대신 hydrate을 채택하겠다고 하는 말은, react 역시 SSR이 react가 나아가야 할 방향이라고 말하는 듯합니다.

좋은 웹페이지 즐겨찾기