본문으로 바로가기

 

 

Next.js로 토이프로젝트를 진행하던 도중에 아래와 같은 오류가 발생하였습니다.

warning: Prop `className` did not match. Server: "MuiFormControl-root sc-iKTcqh gwSKiw css-1nrlq1o-MuiFormControl-root" Client: "MuiFormControl-root sc-gJhJTp gehcyX css-1nrlq1o-MuiFormControl-root"

 

 

[발생 원인]

저는 Next.js로 styled-components와 Material-UI를 사용하고 있었습니다. 그런데 왜 이런 경고가 발생했을까요?

이 경고는 서버에서 렌더링된 클래스 이름과 클라이언트에서 렌더링된 클래스 이름이 일치하지 않아서 발생합니다. 주로 SSR환경에서 styled-components와 Material-UI를 함께 사용할 때 발생하는 문제입니다. 

 

Next.js는 기본적으로 모든 페이지를 미리 렌더링(pre-render)합니다. 생성된 각 HTML은 해당 페이지에 필요한 최소한의 자바스크립트 코드와 연결되며, 브라우저가 페이지를 로드하면 자바스크립트 코드가 완전히 인터랙티브 하게 만들어집니다. 이 과정을 hydration이라고 부릅니다. 

 

그런데, styled-components와 Material-UI는 각각 고유의 클래스 이름 생성 방식을 사용합니다. SSR에서는 서버에서 생선 된 HTML을 클라이언트에서 다시 렌더링 합니다. 서버와 클라이언트가 서로 다른 클래스 이름을 생성하면, 클래스 이름 불일치가 발생해 버립니다.

 

[해결 방법]

1. _document.ts 파일에서 서버 사이드 렌더링 시 styled-components와 Material-UI 스타일을 올바르게 처리하도록 합니다.

import Document, {
  Html,
  Head,
  Main,
  NextScript,
  DocumentContext
} from 'next/document';
import { ServerStyleSheet } from 'styled-components';

class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;
    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />)
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        )
      };
    } finally {
      sheet.seal();
    }
  }

  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

 

2. next.config에서 styledComponents를 true로 설정해 줍니다.

/** @type {import('next').NextConfig} */
const nextConfig = {
  compiler: {
    styledComponents: true
  }
};

module.exports = nextConfig;

 

 

이러면 콘솔에 경고가 깔끔하게 지워졌을 겁니다. 이 설정을 통해 서버와 클라이언트 모두에서 일관된 스타일을 적용할 수 있으며, 클래스 이름 불일치 오류를 해결할 수 있습니다. 

 

 

 

 

References

https://blog.hwahae.co.kr/all/tech/13604

https://tesseractjh.tistory.com/164