Text content does not match server-rendered HTML (hydrating 오류)

Yunseok Choi·2024년 3월 30일

Palette 프로젝트

목록 보기
4/10

1️⃣ 문제상황

Next.js 사용 중 렌더링 과정에서 제목과 같은 오류가 뜬다. 조금 더 자세히는 <section> 안에 <button>이 문제를 일으킨다는 내용이었다. 처음에는 어디에서 왜 문제가 나타나는지도 모르고, 그 페이지의 하위 컴포넌트를 하나하나 주석처리 해가면서 헤더의 논리연산자를 사용하는 버튼이 문제를 일으킨 다는 것을 찾았다.

<section css={[sectionStyle, `justify-content: end;`]}>
  {cookies.accessToken && <WorkspaceBtn />}
</section>

2️⃣ 대체 왜??

'연산자로 렌더링을 결정하는 다른 컴포넌트들도 많은데, 다른 것들은 오류를 안 만들고 왜 이 버튼만 문제를 내뱉는거지?' 라고 생각했다. 그리고 왜 그럴까 계속 생각하고 Next.js공식 문서를 보다가 이유를 깨달았다.

Next.js는 기본적으로 SSR, 즉 서버 사이드 렌더링을 한다. 그리고 렌더링된 HTML을 클라이언트로 보내준다. 그런데 여기서 문제가 발생한다. 애플리케이션을 렌더링하는 동안 서버에서 미리 렌더링된 React 트리와 브라우저에서 첫 번째 렌더링(수화) 중에 렌더링된 React 트리 간에 차이 생기는 것이다.

그리고 이 차이의 원인은 쿠키였다. 쿠키는 클라이언트에서 관리된다. 근데 나는 쿠키를 삼항연산자의 조건으로 내걸었으니, 당연히 Next.js는 서버에 없는 쿠키를 보고 false로 반환해서 컴포넌트를 렌더링(hydrating)하지 않았고, DOM에서는 쿠키가 있어 true로 반환해 렌더링이 된 것이다. 그리고 이 차이를 보고 오류가 생긴 것이다.

관련 공식문서 : https://nextjs.org/docs/messages/react-hydration-error

3️⃣ 해결

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>
);

해결! 끝!

profile
이용자와 서비스를 하나로 만드는 개발자, Hermann입니다.

0개의 댓글