[PWA] (26) Hydration 에러

Kimmy·2025년 5월 29일

PWA_PROJECT

목록 보기
38/47

Hydration 이란?

Client에서 렌더링된 React 애플리케이션이 server에서 렌더링된 HTML과 일치하도록 동기화하는 과정이다.
Hydration 오류는 이 두개가 각각 렌더링한 HTML이 불일치할때 발생한다.

Hydration 에러

ngrok으로 생성한 url을 모바일에서 접속하는데,Hydration 에러가 발생했다.
특이점은, chorme 에서는 문제없는데 반해 safari 에서 하면 Hydration 에러가 난다는 점이다.
알게된 경위는, iphone을 사용하는 내 핸드폰에서는 이 에러가 나는데, android폰에서는 이 에러가 나지 않았다. 그래서 처음에는 ios 랑 android의 차이인가 싶었는데, 찾아보니 safari vs chrome 문제때문인 것 같았다.

✅ 핵심 원인 요약: iOS Safari 고유의 DOM 조작이나 렌더링 차이

✅ iPhone Safari vs iPhone Chrome

iOS Chrome도 실제 렌더링 엔진은 Safari와 동일한 WebKit을 사용한다고 한다. (Apple의 정책 때문에).

하지만 UI나 일부 내부 설정 차이로 인해 Chrome은 HTML을 덜 조작하거나, 조금 다르게 초기화할 수 있다.

따라서 문제는 브라우저 차이가 아니라, Safari의 DOM 자동 수정 기능에 가까울 가능성이 높다.

의심 포인트는 크게 3개,

  1. 전화번호 자동 링크 변환 - Safari는 텍스트 중 전화번호를 자동으로 < a href="tel:...">로 바꾸기도 함.
  2. 날짜/시간 포맷 자동 변환 - Safari는 시스템 로케일에 따라 자동으로 날짜 표현 방식이 달라질 수 있음
  3. WebKit 특화 스타일 문제 --webkit-touch-callout: none; 같은 WebKit 전용 스타일이 조건부로만 렌더링되면, SSR과 CSR 결과가 달라짐.

라고 하는데, 사실 엄청 막막하다 파일이 한두개가 아닌데 어디서 부터 어디까지 찾고 수정해야할지..

toLocaleString(), toLocaleDateString(), Math.random().. 등등 이 코드가 여기저기 쓰여서 다 바꾸면 되는지 어디서 부터 시작해야할지 감이 안왔다.
그래서 Next.js + React 환경에서 hydration 오류의 위치를 찾는 가장 빠른 방법을 찾아보았다.

✅ 수정 포인트 요약:

  1. headers() 제거: 동적 분기를 클라이언트 컴포넌트(ClientLayoutWrapper.js)로 옮김

  2. < script> 태그 분리: MapScripts.js로 분리하고 next/script 사용

  3. Safari 전화번호 자동 링크 방지: < meta name="format-detection" content="telephone=no" /> 추가

➡️이렇게 분리하면:

  • SSR 시에는 완전히 고정된 HTML만 렌더됨 (hydration 안정)

  • 클라이언트에서만 동적으로 pathname, 스크립트 등 처리

  • Safari에서도 < a href="tel:..."> 자동 생성 방지

이렇게 수정-ngrok새로고침-접속 하는 테스트를 반복했지만 아직 hydration 에러를 해결하지 못했다


(반복 또 반복 ㅠㅠ)

다른 블로그에서는 < html lang="ko" suppressHydrationWarning>
을 추가하면 된다고 하는데, 역시 무용지물이었다.

일단 크롬에서는 정상작동하니까, safari에서만 발생하는 이 에러를 고쳐나갈 방법을 계속 고민해보아야겠다.

Console Error

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:
- A server/client branch if (typeof window !== 'undefined').
- Variable input such as Date.now() or Math.random() which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.

It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.

See more info here: https://nextjs.org/docs/messages/react-hydration-error
profile
바리바리 개바리 🌼

0개의 댓글