Hydration Error와 mounted 상태 관리에 대한 설명
문제 상황
// 문제가 있는 코드
export const FeatureToggles = () => {
const { user } = useAuth();
const isAdmin = user?.email === 'test@gmail.com';
return (
<div>
{isAdmin && <Link>글쓰기</Link>} // 💥 Hydration Error 발생
</div>
);
};발생 원인
쉽게 얘기하면 순서가 어긋나기 때문에 문제가 발생한다.
서버 사이드 렌더링 (SSR)
Next.js는 첫 렌더링을 서버에서 수행
이때
useAuth()의 초기 상태는null또는 빈 상태따라서
isAdmin은false가 되어 버튼이 렌더링되지 않음클라이언트 사이드 렌더링
브라우저에서 JavaScript가 실행되면서
useAuth()가 실제 유저 정보를 가져옴isAdmin이true가 되어 버튼이 나타남이 차이로 인해 서버와 클라이언트의 렌더링 결과가 불일치
해결 방법
export const FeatureToggles = () => {
const [mounted, setMounted] = useState(false); // 👈 마운트 상태 추가
const { user } = useAuth();
const isAdmin = user?.admin === 'true';
useEffect(() => {
setMounted(true); // 👈 클라이언트에서 마운트 완료 시 상태 변경
}, []);
return (
<div>
{mounted && isAdmin && <Link>글쓰기</Link>} // 👈 마운트 된 후에만 렌더링
</div>
);
};mounted 상태의 역할
초기값
false서버 사이드 렌더링 시에는 항상
false버튼이 렌더링되지 않음
서버와 클라이언트의 초기 렌더링이 일치
클라이언트에서
true로 변경useEffect는 클라이언트에서만 실행컴포넌트가 마운트된 후
mounted가true로 변경이후 조건부 렌더링이 정상적으로 동작
장점
안정적인 hydration
서버와 클라이언트의 초기 렌더링이 일치
hydration 에러 방지
클라이언트 사이드 로직이 준비된 후에만 조건부 렌더링 실행
단점
깜빡임
컴포넌트 마운트 후 버튼 표시 가능
UX에 영향을 줄 수 있음