코드도보통지

7관문. Hydration Warning

관문 7 / 7

서버와 클라이언트의 초기 상태 불일치로 발생하는 Hydration 경고를 올바르게 해결하라.

📖 이론 비급

Hydration Mismatch: 서버-클라이언트 정합성

서버에서 렌더한 HTML과 클라이언트 첫 렌더 결과가 다르면 Hydration 에러가 발생한다. localStorage나 window 기반 초기값은 서버에서 접근 불가하므로 불일치가 생긴다.

해결책: const [mounted, setMounted] = useState(false); useEffect(() => setMounted(true), []); mounted 전엔 서버와 동일한 기본값을 렌더하고 mounted 후에만 클라이언트 전용 값을 표시한다.

⚔️ 수련 코드

'use client';
import { useState, useEffect } from 'react';

// 문제: 서버는 'light'를 렌더하지만 클라이언트는 localStorage의 값을 읽어 불일치 발생
function ThemeDisplay() {
  const [theme, setTheme] = useState(
    typeof window !== 'undefined' ? localStorage.getItem('theme') || 'light' : 'light'
  );

  // TODO: mounted 상태를 추가하여 Hydration 불일치를 해결하라
  // mounted 전엔 기본값('light')을 표시하고
  // mounted 후에만 localStorage 값을 반영하라

  return (
    <div>
      <p>테마: {theme}</p>
      <button onClick={() => {
        const next = theme === 'light' ? 'dark' : 'light';
        setTheme(next);
        localStorage.setItem('theme', next);
      }}>전환</button>
    </div>
  );
}

export default ThemeDisplay;