728x90
먼저 에러가 발생한 문제는 다음과 같습니다.
- App Router 기반에서 MUI 사용 시 발생하는 Hydration failed 에러
- 발생 시점: AppBar, Typography, Button 등 MUI 컴포넌트 사용 시
- 에러 메시지: "Hydration failed because the server rendered HTML didn't match the client..."
왜 문제가 발생했냐면,
- Next.js App Router는 SSR을 기본으로 하기 때문에 서버/클라이언트 렌더가 다르면 mismatch 발생했습니다.
- MUI는 @emotion/react를 사용해 동적 스타일 삽입하고있습니다.
- 서버에서 렌더된 CSS와 클라이언트에서 렌더된 CSS가 일치하지 않으므로 → 오류가 발생한 상황입니다.
MUI 공식 문서에 나와있는 설정방식은 다음과 같습니다. emotion cache를 구성해야하는데요.
Next.js integration - Material UI
Next.js integration - Material UI
Learn how to use Material UI with Next.js.
mui.com
// src/app/emotion.tsx
'use client';
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
const emotionCache = createCache({ key: 'css', prepend: true });
export default function EmotionRegistry({ children }: { children: React.ReactNode }) {
return <CacheProvider value={emotionCache}>{children}</CacheProvider>;
}
Next.js App Router 환경에서는 클라이언트에서 이 캐시를 명시적으로 감싸주지 않으면,
SSR 시점과 CSR 시점의 스타일이 일치하지 않아서 hydration 오류가 발생하게 됩니다.
그래서 이 컴포넌트를 만들고 CacheProvider로 전체 앱을 감싸주는 게 필수입니다.
// layout.tsx
import EmotionRegistry from './emotion';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
<EmotionRegistry> {/* ✅ 여기서 감싸주는 게 핵심 */}
<div className="w-[360px] mx-auto min-h-screen bg-white">
{children}
</div>
</EmotionRegistry>
</body>
</html>
);
}
여기서는 만든 EmotionRegistry를 <body> 내부에서 감싸주고 있어요.
이렇게 하면 MUI의 모든 컴포넌트가 사용하는 Emotion 스타일이 서버와 클라이언트 모두에서 일관되게 적용됩니다.
결과적으로 Hydration failed... 같은 에러 없이 안정적인 SSR/CSR 환경을 만들 수 있습니다.
아 'use client'와는 별도로 추가로 설정해야하는 겁니다.
728x90
'웹개발 > Next.js' 카테고리의 다른 글
Error 상태코드 종류 모음 (0) | 2025.04.09 |
---|---|
Next.js에서 Axios로 JWT 토큰 인증 API 호출하기 (0) | 2025.03.28 |
Next.js의 App Router와 Page Router 차이점, 무엇을 쓰는게 좋을까요? (1) | 2025.01.27 |
React(리액트) vs Next.js(넥스트) 무엇을 써야하나요? (0) | 2024.07.31 |
Next.js로 웹사이트 라우팅 완벽 가이드 (0) | 2024.07.29 |