NextJS의 동작 원리와 Hydrate
NextJS를 사용하다가 헷갈리는 개념이 있어서 정리해보려고 한다.
Hydrate는 간단하게 말하자면 서버단에서 렌더링 된 정적 페이지와 번들링 된 JS파일을 클라이언트에게 보낸 뒤, 클라이언트단에서 HTML 코드와 React인 JS코드를 서로 매칭시키는 과정을 말한다.
React의 웹페이지 구성 원리
React는 JS파일만을 이용하여 웹화면을 구성하는 원리를 가지고 있다. 그래서 실제 HTML 코드는 안에 내용이 하나도 없는 상태이다. (Client Side Rendering이 SEO에 적합하지 않은 이유이기도 하다.)
단순 뼈대만 있는 HTML document와 JS 파일들을 클라이언트로 모두 보낸 뒤, 클라이언트단에서 JS코드들을 통해 웹화면을 렌더링하며 페이지를 그리게 된다.
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './src/App';
ReactDOM.render(<App />, document.getElementById('root'));
위 코드처럼 public/index.html
에는 아무 내용 없는 기본 뼈대만 있고, 나머지는 src/index.js
의 자바스크립트 코드로 존재한다.
- 자바스크립트 코드에서 모든 화면을 렌더링한다.
- HTML DOM 요소 중 root 라는 아이디를 가진 엘리먼트를 찾아서 하위로 주입한다.
NextJS의 웹페이지 구성 원리
- 클라이언트에게 웹 페이지를 보내기 전에 서버단에서 미리 웹페이지를 Pre-rendering 한다.
- Pre-rendering으로 인해 생성된 HTML document를 클라이언트에게 전송한다.
- 서버에서 Pre-rendering된 웹페이지를 클라이언트에게 보내고나서, 바로 리액트가 번들링 된 자바스크립트 코드들을 클라이언트에게 전송한다.
- 자바스크립트 코드들을 받은 클라이언트에서 이전에 받은 HTML DOM 요소와 자바스크립트 코드를 매칭시킨다.
2번의 과정에서 클라이언트가 받은 웹페이지는 단순히 웹화면만 보여주는 HTML이고, 자바스크립트 요소들은 하나도 없는 상태이다. 이는 웹화면을 보여주고 있지만, 특정 JS모듈 뿐만 아니라 단순 클릭과 같은 이벤트 리스너들이 각 웹페이지의 DOM 요소에 하나도 적용되어 있지 않은 상태이다.
네트워크 탭을 보면, 맨 처음 응답받는 요소가 document Type의 파일이고, 이후에 JS파일들이 받아지는 것을 확인할 수 있다.
그리고 이 자바스크립트 코드들이 이전에 보내진 HTML DOM 요소 위에서 한번 더 렌더링 하면서, 각자 자기 자리를 찾아가며 매칭된다. 이 과정을 Hydration 이라고 부른다.
마치 자바스크립트 코드들이 DOM 요소 위에 물을 채우듯 요소들을 채운다하여 Hydration(수화)라는 용어를 쓴다고 한다.
효율성
서버단에서 한 번 렌더링(pre-rendering)하고 클라이언트에서 한 번 더 렌더링하면 비효율적인 렌더링 방식이 아닌가 할 수 있다.
그러나 서버단에서 빠르게 pre-rendering하고 유저에게 빠른 웹페이지로 응답할 수 있다는 것에 큰 이점이 있다. 게다가 이 pre-rendering한 document는 모든 자바스크립트 요소들이 빠진 굉장히 가벼운 상태이므로 클라이언트에게 빠른 로딩이 가능하다.
이는 같은 화면에 대해 두 번 렌더링이 일어난다는 단점을 보완하고도 남는다.
더 나아가서 클라이언트 단에서 자바스크립트를 렌더링을 할 때, 각 DOM 요소에 자바스크립트 속성을 매칭시키기 위한 목적이기 때문에 실제 웹페이지를 다시 그리지 않는다. (Paint 함수 호출X)
출처