Next.js - Hydration failed … (ft. MUI)

Next.js - Hydration failed … (ft. MUI)

🧢 Problem


Next.jsλ₯Ό μ‚¬μš©ν•˜μ—¬ 포트폴리였 μž‘μ—…μ„ ν•˜κ³  μžˆμ—ˆλŠ”λ° λ‹€μŒμ˜ μ—λŸ¬κ°€ λ°œμƒν•˜μ˜€λ‹€.

Error: Hydration failed because the initial UI does not match what was rendered on the server.

Warning: Expected server HTML to contain a matching <h6> in <h6>.

See more info here: https://nextjs.org/docs/messages/react-hydration-error


error1


error1


Next.js ν™ˆνŽ˜μ΄μ§€λ‘œ λ“€μ–΄κ°€λ³΄λ‹ˆ 이 였λ₯˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ Œλ”λ§ν•˜λŠ” λ™μ•ˆ 미리 λ Œλ”λ§λœ React 트리(SSR/SSG)와 λΈŒλΌμš°μ €μ—μ„œ 첫 번째 λ Œλ”λ§ 쀑에 λ Œλ”λ§λœ React 트리 간에 차이가 μžˆμ–΄μ„œ λ°œμƒν•˜λŠ” κ²ƒμ΄λΌλŠ” μ„€λͺ…이 λ˜μ–΄ μžˆμ—ˆλ‹€. 그리고 ν•΄λ‹Ή 방법에 λŒ€ν•œ μ˜ˆμ‹œκ°€ λ‚˜μ™€ μžˆμ–΄μ„œ ν•΄λ‹Ή μ˜ˆμ‹œμ— 맞좰 λ³€κ²½ν•΄ λ³΄μ•˜λ‹€.


πŸͺ„ Solution 1


export default function App({ Component, pageProps }: AppProps) {
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  return (
    <>
      <Head>...</Head>
      {mounted && (
        <ThemeProvider theme={theme}>
          <CssBaseline />
          <Component {...pageProps} />
        </ThemeProvider>
      )}
    </>
  );
}

μ—λŸ¬κ°€ μ–΄λŠ 정도 ν•΄κ²°λœ κ²ƒμ²˜λŸΌ λ³΄μ˜€μœΌλ‚˜ 기본적으둜 MUI ν…Œλ§ˆκ°€ μ œλŒ€λ‘œ μ μš©λ˜μ§€ μ•Šμ•˜κ³  λ‹€μŒμ˜ μ—λŸ¬ ν•˜λ‚˜κ°€ λ‚¨μ•˜λ‹€.


client.js:1 Warning: validateDOMNesting(...): <h6> cannot appear as a child of <h6>.
    at h6


ν•΄λ‹Ή μ—λŸ¬λŠ” 처음 λ°œμƒν•œ μˆ˜λ§Žμ€ μ—λŸ¬ 쀑 ν•˜λ‚˜μ˜€λŠ”λ° μ œλŒ€λ‘œ 보지 μ•Šμ•˜μ—ˆλ‹€. ν•΄λ‹Ή μ—λŸ¬λ₯Ό λ‹€μ‹œ κ΅¬κΈ€λ§ν•΄μ„œ μ°Ύμ•„λ³΄λ‹ˆ ν•΄λ‹Ή μ—λŸ¬λŠ” MUI에 κ΄€λ ¨λœ μ—λŸ¬μ˜€λ‹€.

λ‹€μŒμ˜ νŽ˜μ΄μ§€μ—μ„œ ν•΄λ‹Ή μ—λŸ¬μ²˜λ¦¬μ˜ 힌트λ₯Ό μ–»μ—ˆλ‹€.

https://github.com/mbrn/material-table/issues/653


MUI의 Typography νƒœκ·Έλ₯Ό 잘λͺ» μ€‘μ²©ν•΄μ„œ μ‚¬μš©ν•˜λ©΄ λ°œμƒν•˜λŠ” λ¬Έμ œμ˜€λ‹€.

λ‚˜λŠ” μ—λŸ¬κ°€ λ‚˜κΈ΄ μ „ μž‘μ—…μ„ ν™•μΈν•˜κ³  문제λ₯Ό μ°Ύμ•„λƒˆλ‹€.


πŸͺ„ Solution 2


<Typography variant="subtitle1" m={5}>
  μ£Όμš” κΈ°λŠ₯ : ν•™μŠ΅ν•˜κ³ μž ν•˜λŠ” μ˜μ–΄λ¬Έμž₯을 등둝, λ¬Έμž₯집(κ·Έλ£Ή)λ³„λ‘œ κ΅¬λΆ„ν•˜μ—¬ ν•™μŠ΅ν• 
  수 있으며, ν•™μŠ΅ν•œ λ¬Έμž₯은 λ”°λ‘œ 체크 κ°€λŠ₯, 각각의 λ¬Έμž₯ λ”°λ‘œ μƒμ„Ένžˆ μ‘°νšŒν•˜μ—¬
  ν•™μŠ΅ν•  수 μžˆλ‹€
  <br></br>
  <br></br>
  FrontEnd : React, NextJS, TypeScript, TailwindCSS, React Query, Recoil
  <br></br>
  BackEnd : MongoDB
  <br></br>
  Deployment : Vercel
  <br></br>
  GitHub : &nbsp;
  <Typography
    variant="subtitle1" // 쀑볡!!!
    ...
  >
    <a href="https://github.com/Gryffindor0ne/me-moonjang">
      https://github.com/Gryffindor0ne/me-moonjang
    </a>
  </Typography>
</Typography>


ν•΄λ‹Ή μ—λŸ¬λŠ” MUI 라이브러리λ₯Ό μ‚¬μš©ν•˜λ˜ 쀑 Typegraphy νƒœκ·Έλ₯Ό μ€‘μ²©μœΌλ‘œ μ‚¬μš©ν•˜λ‹€κ°€ 같은 μ˜΅μ…˜μ„ μ€‘λ³΅μœΌλ‘œ μ‚¬μš©ν•˜μ—¬ λ°œμƒν•œ μ—λŸ¬λΌλŠ” 것을 μ•Œκ²Œ λ˜μ—ˆλ‹€. ν•΄λ‹Ή μ˜΅μ…˜μ„ μ‚­μ œν•˜κ³  μœ„μ—μ„œ μ„€μ •ν•œ 뢀뢄도 λ‹€ μ‚­μ œν•œ ν›„ 앱을 λ‹€μ‹œ μ‹€ν–‰ν•΄λ³΄λ‹ˆ μ—λŸ¬μ—†μ΄ 잘 μž‘λ™ν•˜μ˜€λ‹€.

κ²°κ΅­ ν•΄λ‹Ή μ—λŸ¬λŠ” λ‚΄κ°€ SSR으둜 μž‘λ™ν•˜λŠ” NextJSμ—μ„œ MUI 라이브러리λ₯Ό 잘λͺ» μ‚¬μš©ν•˜μ—¬ λ Œλ”νŠΈλ¦¬ 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚¨ 것이 μ›μΈμ΄μ—ˆλ‹€. μ–΄μ°Œλ³΄λ©΄ μ•„μ£Ό λ‹¨μˆœν•œ μ‹€μˆ˜μΈλ° μ—λŸ¬κ°€ λ¬΄μˆ˜ν•˜κ²Œ 많이 λœ¨λ‹ˆ 내심 λ‹Ήν™©ν•˜μ˜€λ‹€. λ‹€ν–‰νžˆ 원인은 금방 μ°Ύμ•„λ‚΄μ–΄ ν•΄κ²°ν•˜μ˜€κ³  그둜 인해 또 ν•œ 가지 λ°°μš°λŠ” μž‘μ—…μ΄ λ˜μ—ˆλ‹€.