ReactHard#435
React에서 hydration mismatch가 발생하는 원인과 해결 방법을 설명해주세요.
#React#Hydration#SSR#Next.js
답변 포인트
서버가 만든 HTML과 클라이언트 첫 렌더 결과가 달라지는 경우를 생각해보세요.
정답 및 해설
빠른 요약
Hydration mismatch는 서버에서 생성한 HTML과 클라이언트가 처음 렌더링한 결과가 다를 때 발생합니다. SSR 환경에서 React는 기존 HTML에 이벤트를 붙이며 hydration을 수행하는데, 이때 마크업이 다르면 경고나 UI 깨짐이 생길 수 있습니다.
Hydration mismatch는 서버에서 생성한 HTML과 클라이언트가 처음 렌더링한 결과가 다를 때 발생합니다. SSR 환경에서 React는 기존 HTML에 이벤트를 붙이며 hydration을 수행하는데, 이때 마크업이 다르면 경고나 UI 깨짐이 생길 수 있습니다.
흔한 원인은 다음과 같습니다.
- 렌더 중
Date.now(),Math.random()사용 - 서버와 클라이언트의 locale/timezone 차이
- 브라우저에서만 가능한
window,localStorage값을 첫 렌더에 사용 - 조건부 렌더링 결과가 서버/클라이언트에서 다름
- 잘못된 HTML nesting
해결의 기본은 첫 렌더 결과를 서버와 클라이언트에서 동일하게 만드는 것입니다. 브라우저 전용 값은 useEffect 이후에 읽거나, 초기 placeholder를 두고 클라이언트 마운트 후 교체합니다.
TSX
function ClientTime() {
const [time, setTime] = useState<string | null>(null);
useEffect(() => {
setTime(new Date().toLocaleTimeString());
}, []);
return <span>{time ?? '시간 불러오는 중'}</span>;
}정말 의도적으로 다를 수밖에 없는 텍스트에는 suppressHydrationWarning을 제한적으로 사용할 수 있지만, 구조 불일치를 덮는 용도로 남용하면 안 됩니다.