Next.js를 사용할 때 생겼던 Hydration 이슈이다. Hydration이란 Next.js의 SSR 특성 때문에 생기는 오류이다.
Next.js의 SSR 특성은 정적 HTML 파일을 먼저 서버에서 가지고 와서 브라우저에서 js파일로 다시 랜더링해주는 특성이다. 이 특성으로 인하여 사용자는 더 빠르게 화면을 볼 수 있다.
Hydration error는 SSR에서 생기는 부작용인데 SSR또는 SSG에 의하여 pre-render되는 React tree와 브라우저에서 render되는 React tree가 달라서 발생하는 문제이다.
SSR에서 render되는 것을 Hydration이라고 하기 때문에 Hydration Error라고 한다.
해결방안 1
보통 이런 이슈는 특정 라이브러리나 application code에서 pre-render되는 것과 browser에서 render되는것과의 차이에 의해서 생긴다.
예를 들어 ‘window’라는 component가 rendering되는 것을 보자.
function MyComponent() {
// This condition depends on `window`. During the first render of the browser the `color` variable will be different
const color = typeof window !== 'undefined' ? 'red' : 'blue'
// As color is passed as a prop there is a mismatch between what was rendered server-side vs what was rendered in the first render
return <h1 className={`title ${color}`}>Hello World!</h1>
}
이 코드는 React의 Hook중에서 useEffect를 사용하여 아래와 같이 수정할 수 있다.
// In order to prevent the first render from being different you can use `useEffect` which is only executed in the browser and is executed during hydration
import { useEffect, useState } from 'react'
function MyComponent() {
// The default value is 'blue', it will be used during pre-rendering and the first render in the browser (hydration)
const [color, setColor] = useState('blue')
// During hydration `useEffect` is called. `window` is available in `useEffect`. In this case because we know we're in the browser checking for window is not needed. If you need to read something from window that is fine.
// By calling `setColor` in `useEffect` a render is triggered after hydrating, this causes the "browser specific" value to be available. In this case 'red'.
useEffect(() => setColor('red'), [])
// As color is a state passed as a prop there is no mismatch between what was rendered server-side vs what was rendered in the first render. After useEffect runs the color is set to 'red'
return <h1 className={`title ${color}`}>Hello World!</h1>
}
또한 css-in-js 라이브러리를 사용할 경우에의 문제일 수도 있다.
css in js 라이브러리의 종류에는 Styled-Components나 Emotion 같은 것이 있는데, css in js l라이브러리가 pre-render되지 않는다면 hydration mismatch로 이어질 수 있다.
나의 경우
나의 경우 Cookie를 사용하는 Website를 만들고 있었는데 처음에 User의 정보가 Cookie에 있으면 로그인을 유저의 이름으로 바꾸어줄려고 했다.
이 코드를 컴포넌트 내에서 사용할 때 useEffect로 Cookies.get 함수를 넣어서 바꾸어주어 해결하였다.
const [logined, setLogined] = useState(false);
useEffect(() => {
if (
Cookies.get("userInfo") !== "null" ||
Cookies.get("userInfo" !== "undefined")
) {
setLogined(true);
} else {
setLogined(false);
}
});
해결 방안 2
pages/_document가 없거나 Babel plugin이 없다면 추가하여서 사용하도록 하자.
// .babelrc를 만들어서 아래 코드를 추가해주자
{
"presets": [
"next/babel"
],
"plugins": [
"babel-plugin-styled-components"
]
}
그 외의 이슈는 아래 공식문서를 참고하면 될 것 같다.
https://nextjs.org/docs/messages/react-hydration-error
'프론트엔드 > Next.js' 카테고리의 다른 글
Next.js에서 새로고침하면 스타일이 적용안되는 문제 (0) | 2022.08.04 |
---|---|
Next.js로 프로젝트 시작 (0) | 2022.08.04 |
Next.js 설치와 폴더 구조 (0) | 2022.08.04 |
Next.js 를 사용하는 이유 (0) | 2022.08.04 |