24 lines
3.4 KiB
Markdown
24 lines
3.4 KiB
Markdown
# [[Hydration Mismatch]]
|
|
|
|
## 📌 Brief Summary
|
|
Hydration Mismatch는 서버에서 렌더링된 HTML 콘텐츠와 클라이언트 측에서 기대하거나 생성하는 콘텐츠가 서로 다를 때 발생하는 오류 현상입니다 [1, 2]. 특히 React 서버 컴포넌트(RSC) 환경이나 CSS-in-JS(예: styled-components)를 사용할 때, 서버와 클라이언트 간에 다른 동적 데이터나 CSS 클래스 이름이 생성될 경우 흔하게 발생합니다 [2, 3]. 이를 방지하기 위해서는 서버와 클라이언트 경계에서 일관된 렌더링 결과물과 안정적인 해시 값을 생성하도록 구성해야 합니다 [3, 4].
|
|
|
|
## 📖 Core Content
|
|
- **Hydration의 원리 및 Mismatch 발생 조건**
|
|
React에서 Hydration은 서버에서 렌더링되어 전달된 정적 HTML에 이벤트 리스너와 상태(State)를 연결하여 상호작용 가능한 UI로 만드는 과정입니다 [1]. Next.js 15의 App Router와 같은 구조에서는 이 과정이 주로 클라이언트 컴포넌트(Client Components)에서만 발생합니다 [1]. Hydration Mismatch는 서버가 생성한 콘텐츠와 클라이언트가 렌더링 시 기대하는 콘텐츠가 다를 때 나타나며, 타임스탬프와 같이 서버와 클라이언트에서 각기 다르게 계산되는 동적 데이터가 대표적인 원인입니다 [2].
|
|
|
|
- **CSS-in-JS(Styled Components) 환경에서의 위험성**
|
|
Next.js App Router에서 Styled Components가 작동하도록 Style Registry 패턴을 사용할 경우, 서버와 클라이언트가 서로 다른 CSS 클래스 이름을 생성하면 Hydration Mismatch가 발생할 위험이 있습니다 [3]. 또한, 다크 모드와 라이트 모드 간에 테마를 전환할 때 안정적인 클래스 이름 해시(hash)가 유지되지 않으면 동일한 문제가 발생할 수 있습니다 [4].
|
|
|
|
- **해결 및 완화 전략**
|
|
- **동적 데이터 렌더링 처리:** 클라이언트와 서버에서 값이 달라질 수 있는 동적 요소는, 클라이언트에서 컴포넌트가 마운트된 이후에 렌더링되도록 처리하여 불일치를 피해야 합니다 [2].
|
|
- **컴파일러 옵션 활용:** Styled Components를 사용할 경우 `next.config.js`에서 `styledComponents` 컴파일러 옵션을 활성화해야 합니다. 이는 서버와 클라이언트 경계에서 일관된 CSS 클래스 이름 생성을 보장하여 Hydration Mismatch를 완화합니다 [3].
|
|
- **안정적인 테마 객체 전달:** 테마 전환 시 Hydration Mismatch를 방지하려면, `createTheme` 등을 활용하여 생성된 테마 객체를 `ThemeProvider`에 제대로 전달함으로써 테마 간 전환에도 클래스 이름 해시가 안정적으로 유지되도록 해야 합니다 [4, 5].
|
|
|
|
## 🔗 Knowledge Connections
|
|
- **Related Topics:** [[React Server Components (RSC)]], [[Styled Components]], [[Next.js App Router]], [[CSS-in-JS]]
|
|
- **Projects/Contexts:** [[Next.js 15 기반 애플리케이션의 클라이언트 및 서버 렌더링 구성]], [[Styled Components의 글로벌 스타일 및 테마 구현]]
|
|
- **Contradictions/Notes:** 소스 간의 모순점은 없으며, 동적 렌더링이나 런타임 CSS 생성 시 발생하는 서버-클라이언트 불일치를 해결하기 위해 컴파일러 단의 설정(예: `styledComponents` 활성화)이나 정적이고 안정적인 클래스 네임 사용이 공통적인 해결책으로 제시됩니다 [2, 3].
|
|
|
|
---
|
|
*Last updated: 2026-04-26* |