티스토리 뷰

Hydration이란 React가 서버에서 렌더링된 정적 HTML을 받아서 인터랙티브한 React 앱으로 변환하는 과정이다.

 

그런데 서버에서 렌더링된 HTML과 클라이언트에서 렌더링된 HTML이 일치하지 않을 때

Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used 

라는 오류가 발생한다.

 

나의 경우는

useIsMobile 이라는 커스텀 훅을 만들어서 이걸 통해 모바일 디바이스나 모바일 뷰포트인지를 체크한 다음레이아웃이나 조건부 렌더링 등의 작업을 해주었는데,이 커스텀 훅이 사용되는 곳에 'use client' 지시문을 선언해주지 않은 경우 hydration 에러가 발생했고또 커스텀 훅 자체에도 초기값을 설정하는 부분에서 문제가 있었다. 서버 사이드에서는 false를 반환하고, 클라이언트 사이드에서는 실제 디바이스 체크를 하기 때문에 hydration 에러가 발생했다.

 

해결 방법으로는 초기 상태를 false로 고정하고

mounted 상태를 추가해서 클라이언트 사이드 렌더링 여부를 추적,

그리고 클라이언트 사이드에서만 실제 디바이스 체크가 되도록 했다.

이렇게 하면 서버 사이드에서는 항상 false를 반환하여 초기 HTML은 일관되게 생성되고

클라이언트 사이드에서 마운트된 이후에만 실제 디바이스 체크가 되었다.

export const useIsMobile = (): boolean => {
  const [isMobile, setIsMobile] = useState<boolean>(false);
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
    const checkMobile = () => {
      const isMobileDevice = isMobile || window.innerWidth < 769;
      setIsMobile(isMobileDevice);
    };

    // 처음 마운트 시 1회 체크
    checkMobile();
    
    ......
    
    // 서버 사이드에서는 항상 false를 반환
  if (!mounted) {
    return false;
  }

  return isMobileView;
};

 

 

이렇게 하면 서버 사이드 렌더링과 클라이언트 사이드 렌더링이 일치하게 돼서

hydration 에러가 해결되었다.

 

728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
250x250