[Next.js] hydration
💡 시작하기
현재 다니고 있는 회사에서 Next.js를 사용하여 본격적으로 Next.js를 사용하고 공부하게 되었는데요!
그 중에 가장 자주 부딪힌 문제가 바로 Hydration Error였어요. 그래서 이번에는 Hydration Error가 무엇인지, 왜 발생하는지, 어떻게 해결할 수 있는지 대해 정리해보려고 해요
⚙️ Hydration
Hydration ? 서버로부터 정적 렌더링으로 받은 파일을 클라이언트가 다양한 기능들을 첨부하여 동적 웹 페이지로 변환하는 기술
- 다양한 기능?
- 이벤트 처리
- 상태 처리
- 인터랙션 및 애니메이션
Hydration의 뜻은 “수화” 라는 뜻으로, 메마른 정적 HTML 파일에 동적 요소 라는 물을 주기 때문에 다음과 같은 단어를 사용했다고 해요
⚙️ Hydration Error
Hydration Error ? 클라이언트가 서버에서 렌더된 HTML을 재사용할 때, 서버와 클라이언트의 렌더링 결과가 다를 경우 발생하는 에러
Next.js에서의 SSR 과정
- 서버에서 정적인 페이지인 HTML 파일 만듦
- 클라이언트에서 HTML 파일을 초기 렌더링시킴 ← 이때의 파일과 서버에서의 파일 비교
- 클라이언트에서 hydration 진행
hydration의 전제 : 서버가 만든 HTML === 클라이언트가 초기 렌더한 HTML
이 전제가 맞지 않을 때 hydration error가 발생해요.
ex) hydration error
const width = window.innerWidth;
return <div>{width}</div>;
- 서버 :
<div>undefined</div>or window is not defined - 클라이언트 :
<div>1920</div>
⇒ 같지 않으므로 hydration이 깨져버림
🖥️ hydration error가 발생하는 경우
가장 많이 hydration error를 겪는 경우는
- LocalStorage, 브라우저 API(window, document) 등 클라이언트에서만 접근할 수 있는 요소
Date.now(),Math.random()과 같은 실행 시마다 달라지는 값
에 접근했을 때 발생해요
이들의 경우, 렌더링 시점에 바로 실행하기 때문이에요
🖥️ Solution : useEffect 사용하기
hydration error를 해결하려면 위에서 언급한 값들을 반드시 useEffect 안에서 처리하면 돼요
useEffect를 왜 써야 할까요?
useEffect는 브라우저 렌더링이 끝난 뒤(hydration 이후) 실행되는 훅이에요.
useEffect는 서버에서 실행되지 않기 때문에, 서버는 useEffect 안에 있는 코드는 건너뛰고 HTML을 만들게 되어요
클라이언트는 서버가 만들어준 HTML을 그대로 받아 hydration을 통해 초기 렌더링을 맞춘 뒤, 그 이후에 useEffect가 실행되므로 에러를 해결할 수 있어요
기존 코드 vs 해결한 코드
기존 코드
"use client";
export function ExampleComponent() {
// 클라이언트 API를 렌더링 중에 바로 호출 → 서버에서는 window가 없음
const hostname = window.location.hostname;
return <div>현재 호스트: {hostname}</div>;
}
"use client";
import { useEffect, useState } from "react";
export function ExampleComponent() {
// 클라이언트에서만 실행되므로 서버에서는 에러 없음
useEffect(() => {
setHostname(window.location.hostname);
}, []);
if (!hostname) {
return <div>호스트 이름 로딩 중...</div>;
}
return <div>현재 호스트: {hostname}</div>;
}
