목차
이전 포스팅에서 CSR,SSR,SSG,ISG 개념을 공부했다.
이들의 정확한 개념을 파악하여 적절히 섞어 사용하면 성능을 최적화 시킬 수 있다.
🧩 Hydrate
Hydrate 는 리액트에 종속된 개념으로 Next.js에만 국한된것이 아니다.
Next.js 는 첫 페이지 로드 시 Hydrate 과정을 거치는데 위의 Next.js는 React.DOM.hydrate 를 내부적으로 사용하는 것이다.
여기서 Hydrate 이란, 서버에서 렌더링된 HTML을 클라이언트에서 재사용하는 것을 말한다.
과정은 이러하다
처음 클라이언트는 자바스크립트가 적용되지 않은 즉, DOM에 이벤트가 적용되지 않아 어떠한 이벤트가 일어나지 않는 UI 만 담고 있는 상태이다.
그 후에 리액트가 번들링 된 JS 요소들을 클라이언트에 보내주고 DOM 과 맞추게 된다.
예를들어 첫 화면 로딩 시, 가끔 이미지나 폰트가 제대로 적용되어 보이지 않다가 제대로 보이는 경험을 했을 것이다. 이는 웹폰트나 이미지 JS 가 pre-rendering 된 화면에 찾아가고 있는 “하이드레이트” 과정을 지나고 있기 때문이다.
이렇게 되면 서버에서 렌더링, 클라이언트에서 렌더링. 두번의 렌더링을 거쳐 성능이 걱정될수 있지만,
클라이언트에서 렌더링 할때는 웹페이지를 다시 리페인팅 하는것이 아니라, 자바스크립트를 각 돔 요소에 찾아가는 역할이기 때문에 (===하이드레이팅) 크게 방해가 될 요소는 아니다.
또한 pre-rendering 된 화면은 자바스크립트가 다 빠진 화면이기 때문에 상당히 가볍고
그만큼 초기 로딩속도가 줄어들게 된다. 이렇게 되면 유저에게 보다 빠른 화면을 보여줄 수 있다는 큰 장점이 있다.
⚠️ 그러나 제대로 사용하지 않을 경우 생기는 문제가 있다.
하이드레이트는 HTML 비교 시 렌더링 된 트리와 비교하는것이 아니라 Virtual DOM 과 비교한다.
즉, useEffect 가 실행되기 전 상태와 비교하는 것이다.
또한 하이드레이트는 텍스트, 속성값을 비교하지 않고 엘리먼트의 순서만 비교한다.
만약 문제가 생길 시 꼼수로 return null 값 대신 <div/> 과 같은 빈 엘리먼트를 적용시키는 방법도 있다고 한다.
더 자세한 에러 및 해결 사항은 아래의 블로그 참조
🧩 Dynamic Import
Next.js 에서는 hydrate 라는 개념을 기반으로 렌더링 한다고 앞서 설명하였다.
하지만 이렇게 될 경우 pre-rendering 시 모든 DOM 요소를 가져와야 하는 단점이 있다.
예를들어, 첫 화면 렌더링 시 document 에 걸려있는 script를 가져오다보니, 뷰포트에서 벗어난 푸터나 그 외 컴포넌트까지 전부 가져오게 되는데, 눈에 보이지 않는 컴포넌트들 때문에 불필요한 hydrate 작업을 해야할까?
이럴때 다이나믹 임포트를 사용한다.
필요한 컴포넌트만 불러와 성능을 높이자
Dynamic Import 용어 자체는 자바스크립트 모듈을 런타임 시 동적으로 가져올 수 있는것을 말한다.
Next.js에서는 code-spliting 하여 다음과 같이 import 한다.
이렇게 작성하면 서버에서 불필요한 코드를 가져오지 않고, 유저가 필요로 하는 모듈만 가져올 수 있기 때문에 초기 로딩속도도 높아지고 자원낭비도 막을 수 있다.
추가옵션도 필요에 의해 사용 할 수 있다.
ex) ssr : 클라이언트에서 동적 렌더링하여 ssr 이 필요없는 경우, 불리언값으로 서버 렌더링을 비활성화 할 수 있다.
무조건 좋은걸까?
성능면에서 좋을 수 있지만 서버에서 pre-rendering 시 dynamic import 시킨 항목 또한 보이지 않는 단점이 있다.
그렇기 때문에 dynamic import가 적용된 부분은 초기 로딩시 보이지 않으며,
웹 크롤러도 페이지에 접속하여 크롤링 할 정보가 없기 때문에 해당 부분은 SEO 에서 제외된다.
그렇기때문에 pre-rendering 은 그대로 보존하면서 해당 컴포넌트의 js가 필요한 순간에 lazy 요청하여 가져올 수 있는 방안을 생각해야 한다
Next-lazy-hydration 이라는 방식이 있다고 하는데 이는
- 웹팩모듈설정
- Next.js 내부설정
- react-lazy-hydration 라이브러리 사용
세가지 방식을 사용하여 해결 할 수 있는것 같다. 하지만 난이도가 매우 높으니 고려해보도록 하자!