Astro 5.5 server islands로 정적 부분 + 동적 부분 분리 중인데 일부 페이지에서 hydration mismatch가 나옵니다.
---
// src/pages/index.astro
import LoginStatus from '../components/LoginStatus.astro'
---
<Layout>
<Hero />
<LoginStatus server:defer fallback={LoginSkeleton} />
<FeatureList />
</Layout>
3개 페이지 중 1개만 console에 "Hydration completed but contains mismatches" 경고. 같은 LoginStatus 컴포넌트인데...
경고 발생 페이지
- 홈 (/) — A/B 테스트 분기가 있음
- 제품 페이지 — 정상
- 블로그 — 정상
A/B 테스트 분기는 cookies()로 그룹 결정하는데, 이게 문제일까요?
댓글 4
네, A/B 테스트 분기가 원인이 맞습니다. Astro의 server islands는 "전체 페이지가 정적, 일부만 동적"이라는 가정인데, A/B 테스트로 페이지 전체가 분기되면 그 가정이 깨집니다.
패턴 1 — Edge Function으로 A/B 분기
Astro 페이지에 들어오기 전 edge에서 분기 결정 후 응답 헤더에 그룹 명시. 페이지는 그룹별로 별도 캐시.
패턴 2 — A/B 분기 자체를 client island로
페이지는 모두 정적, A/B 결정은 client 측에서. 깜빡임 발생할 수 있지만 hydration은 안전.
패턴 3 — A/B를 server island 안으로 격리
A/B 분기를 server:defer 컴포넌트 안에서만. 페이지 외부는 정적 유지.
왜 다른 페이지는 OK?
제품 페이지/블로그는 cookies() 호출이 server island 안에서만 발생. 홈은 페이지 컴포넌트 자체에서 호출. Astro는 페이지 컴포넌트에서 cookies() 호출하면 전체 페이지를 동적으로 전환합니다.
3번 패턴이 가장 깔끔하고 성능 좋습니다. 페이지 셸은 CDN 캐시, A/B만 동적.
저는 A/B 도구로 GrowthBook 쓰는데, edge SDK가 있어서 middleware에서 분기 → header inject → server island가 header 읽어서 처리하는 패턴이 깔끔합니다. cookies() 직접 안 만지고요.