0Pricing
React Academy · 강의

수화 오류: 원인과 해결 방법

서버와 클라이언트 HTML의 불일치를 찾아 suppressHydrationWarning으로 해결합니다.

수화 오류: 원인과 해결 방법은(는) CoddyKit의 무료 React Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 React Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

하이드레이션 오류란 무엇인가요

하이드레이션 오류는 리액트가 서버에서 렌더링한 HTML이 클라이언트에서 리액트가 예상하는 가상 DOM과 일치하지 않을 때 발생합니다. 리액트는 경고를 기록하고 컴포넌트를 처음부터 다시 렌더링하여 화면이 깜박이게 합니다.

일반적인 원인 1: 무작위 값

렌더링 중에 Math.random(), Date.now() 또는 crypto.randomUUID()를 사용하면 서버와 클라이언트에서 서로 다른 값이 생성됩니다.

// Bad — different on server vs client:
<div id={Math.random().toString()}>...</div>

// Fix — use useId() (stable across server/client):
import { useId } from 'react';
function Component() {
  const id = useId();
  return <div id={id}>...</div>;
}

일반적인 원인 2: 브라우저 전용 프로그래밍 인터페이스

렌더링 중에 localStorage, window.innerWidth 또는 navigator를 읽으면 서버에서 충돌하거나 서로 다른 값이 생성됩니다.

// Bad — localStorage doesn't exist on server:
<div>{localStorage.getItem('theme')}</div>

// Fix — read in useEffect (client-only):
const [theme, setTheme] = useState('light');
useEffect(() => {
  setTheme(localStorage.getItem('theme') ?? 'light');
}, []);

일반적인 원인 3: 날짜 및 시간 형식 지정

로캘을 인식하는 날짜 형식 지정은 서버(UTC/Node.js 로캘)와 클라이언트(브라우저 로캘)에서 서로 다른 문자열을 반환합니다.

// Risky — locale may differ:
<time>{new Date().toLocaleDateString()}</time>

// Fix — use a consistent locale:
<time>{new Date().toLocaleDateString('en-US', { timeZone: 'UTC' })}</time>

일반적인 원인 4: 잘못된 HTML 중첩

리액트는 가상 DOM에서 클라이언트 HTML을 생성하지만, 잘못된 HTML 중첩(예: <p> 안의 <p>)으로 인해 브라우저가 DOM을 서로 다르게 재구성하여 불일치가 발생합니다.

// Bad — browser auto-closes the nested <p>:
<p>Outer <p>Inner</p> text</p>

// Fix — use <div> or correct semantic elements:
<div>Outer <p>Inner</p> text</div>

일반적인 원인 5: 상태에 따른 조건부 렌더링

클라이언트 전용 상태(예: 사용자 인증이나 화면 너비)에 따라 다르게 렌더링되는 컴포넌트는 서버가 해당 상태 없이 렌더링하므로 불일치가 발생합니다.

// Bad — server renders 'Guest', client re-renders 'Alice' immediately:
<h1>{user?.name ?? 'Guest'}</h1>

// Fix — use a mounted guard to defer client-only rendering:
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
if (!mounted) return <h1>Guest</h1>; // match server output

suppressHydrationWarning

클라이언트에서 형식을 지정하는 타임스탬프처럼 불일치가 의도된 요소에는 suppressHydrationWarning을 사용하십시오. 해당 요소에 대한 경고만 억제합니다.

<time suppressHydrationWarning dateTime={isoDate}>
  {new Date(isoDate).toLocaleString()}
</time>

ssr: false를 사용한 동적 가져오기

Next.js에서는 dynamic(fn, { ssr: false })를 사용하여 컴포넌트가 서버에서 전혀 렌더링되지 않도록 할 수 있습니다. 이렇게 하면 클라이언트 전용 컴포넌트의 하이드레이션 불일치가 제거됩니다.

import dynamic from 'next/dynamic';

const ClientOnlyChart = dynamic(() => import('./Chart'), { ssr: false });

export default function Dashboard() {
  return <ClientOnlyChart />; // only renders in the browser
}

하이드레이션 오류 디버깅

리액트 18은 개발 환경에서 정확히 어떤 DOM 노드가 불일치하는지 보여 주는 자세한 하이드레이션 오류 메시지를 기록합니다. 브라우저 DevTools를 사용하여 서버 HTML과 리액트 트리를 검사하십시오.

안정적인 ID를 위한 useId

useId()는 서버와 클라이언트 렌더링에서 일관된 안정적이고 고유한 ID를 생성합니다. id/htmlFor 쌍과 ARIA 속성에 사용하십시오.

function FormInput({ label }: { label: string }) {
  const id = useId();
  return (
    <div>
      <label htmlFor={id}>{label}</label>
      <input id={id} />
    </div>
  );
}

하이드레이션 오류 테스트

Next.js 앱을 개발 모드(npm run dev)로 실행하고 브라우저 콘솔을 확인하십시오. 하이드레이션 불일치는 컴포넌트 스택 추적이 포함된 빨간색 경고로 표시됩니다.

빠른 확인

localStorage를 읽기 때문에 서버와 클라이언트에서 다르게 렌더링되는 컴포넌트에 대한 가장 좋은 해결 방법은 무엇인가요?

복습

하이드레이션 불일치는 무작위 값, 브라우저 전용 프로그래밍 인터페이스, 로캘에 민감한 형식 지정, 잘못된 HTML 중첩, 클라이언트 전용 조건부 렌더링 때문에 발생합니다. useId(), 클라이언트 전용 상태를 위한 useEffect, 의도적인 차이를 위한 suppressHydrationWarning, 클라이언트 전용 컴포넌트를 위한 dynamic({ ssr: false })로 해결하십시오.

자주 묻는 질문

“수화 오류: 원인과 해결 방법” 강의는 무료인가요?

네 — “수화 오류: 원인과 해결 방법” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 React Academy 강의 전체를 잠금 해제할 수 있습니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“수화 오류: 원인과 해결 방법”에서 뭘 배우나요?

서버와 클라이언트 HTML의 불일치를 찾아 suppressHydrationWarning으로 해결합니다. 브라우저에서 직접 실행하는 실습 코드로 React Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

React Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 React Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“수화 오류: 원인과 해결 방법” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 React Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 React Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. React SSR 내부 동작 이해하기
  2. 수화 오류: 원인과 해결 방법
  3. 선택적 수화와 스트리밍 HTML
  4. 아일랜드 아키텍처 패턴
← React Academy(으)로 돌아가기