Next.js 사용 중 렌더링 과정에서 제목과 같은 오류가 뜬다. 조금 더 자세히는 <section> 안에 <button>이 문제를 일으킨다는 내용이었다. 처음에는 어디에서 왜 문제가 나타나는지도 모르고, 그 페이지의 하위 컴포넌트를 하나하나 주석처리 해가면서 헤더의 논리연산자를 사용하는 버튼이 문제를 일으킨 다는 것을 찾았다.
<section css={[sectionStyle, `justify-content: end;`]}>
{cookies.accessToken && <WorkspaceBtn />}
</section>
'연산자로 렌더링을 결정하는 다른 컴포넌트들도 많은데, 다른 것들은 오류를 안 만들고 왜 이 버튼만 문제를 내뱉는거지?' 라고 생각했다. 그리고 왜 그럴까 계속 생각하고 Next.js공식 문서를 보다가 이유를 깨달았다.
Next.js는 기본적으로 SSR, 즉 서버 사이드 렌더링을 한다. 그리고 렌더링된 HTML을 클라이언트로 보내준다. 그런데 여기서 문제가 발생한다. 애플리케이션을 렌더링하는 동안 서버에서 미리 렌더링된 React 트리와 브라우저에서 첫 번째 렌더링(수화) 중에 렌더링된 React 트리 간에 차이 생기는 것이다.
그리고 이 차이의 원인은 쿠키였다. 쿠키는 클라이언트에서 관리된다. 근데 나는 쿠키를 삼항연산자의 조건으로 내걸었으니, 당연히 Next.js는 서버에 없는 쿠키를 보고 false로 반환해서 컴포넌트를 렌더링(hydrating)하지 않았고, DOM에서는 쿠키가 있어 true로 반환해 렌더링이 된 것이다. 그리고 이 차이를 보고 오류가 생긴 것이다.
관련 공식문서 : https://nextjs.org/docs/messages/react-hydration-error
HTML 컴포넌트의 return 쪽에서 직접적으로 cookie를 써서 오류가 난 것임을 깨닫고, useState()와 useEffect()를 써서 cookie의 유무에 따른 boolean을 사용해 논리 연산자의 조건에 넣었고, 이로서 오류가 사라졌다.
const [cookies] = useCookies(["accessToken"]);
const [isCookieThere, setIsCookieThere] = useState(false);
useEffect(() => {
if (cookies.accessToken) {
setIsCookieThere(true);
}
}, []);
return (
<section css={[sectionStyle, `justify-content: end;`]}>
{isCookieThere && <WorkspaceBtn />}
</section>
</header>
);