Next.js와 MUI의 병용이 더 쉬워졌다!

Next.js와 MUI의 병용이 더 쉬워졌다!

Next.js 및 MUI를 함께 사용하자 (feat. Tailwind CSS)

바로 저번 주까지만 해도 Next.js와 MUI를 함께 사용하려면 캐시 처리 및 인젝션 오더 설정용 프로바이더를 직접 공식 문서에 따라 만들고 커스텀해 삽입하는 노가다가 필요했다. 하지만 이제 그럴 필요가 없어진 것 같다. 포트폴리오용 사이트를 제작하기 위해 MUI 문서를 들어가보니 새로운 방법이 제시되어 있었기 때문이다.

변경된 사용 방법

우선 각 단계를 진행하기 전에 기본적인 MUI 구성은 완료되어 있어야 한다. 또한 문서에서는 Next.js 13 이상에서 진행하기를 권장하고 있다.

나는 pnpm 패키지 매니저를 사용하므로 다른 패키지 매니저를 사용한다면 적절히 변환해서 사용하면 된다.

App Router에서 사용하기

  • 1. 필요한 패키지 설치: pnpm add @mui/material-nextjs @emotion/cache 명령어로 필요한 의존성을 추가한다.
  • 2. 설정: app/layout.tsx에서 AppRouterCacheProvider를 사용해 <body> 안의 요소를 감싼다.
// app/layout.tsx
+ import { AppRouterCacheProvider } from '@mui/material-nextjs/v13-appRouter'; // or `v14-appRouter` if you are using Next.js v14

export default function RootLayout(props) {
  const { children } = props;
  return (
    <html lang="en">
      <body>
+        <AppRouterCacheProvider>{children}</AppRouterCacheProvider>
      </body>
    </html>
  );
}

다른 스타일 솔루션(Tailwind CSS 등)을 사용한다면

AppRouterCacheProvideroptions 프롭의 enableCssLayertrue로 설정해주면 된다.

- <AppRouterCacheProvider>{children}</AppRouterCacheProvider>
+ <AppRouterCacheProvider options={{ enableCssLayer: true }}>

이렇게 하면 MUI에 의해 만들어진 스타일에 대해 @layer mui 룰을 적용하여 CSS 모듈이나 Tailwind CSS, 혹은 바닐라 CSS의 @layer가 적용되지 않은 스타일이 이를 덮어쓸 수 있게 해준다.

Pages Router에서 사용하기 (또는 SSR, SSG)

  • 1. 필요한 패키지 설치: App Router에서 필요한 패키지에 더하여 @emotion/server도 설치한다.
    pnpm add @mui/material-nextjs @motion/cache @emotion/server
  • 2. 필요한 설정 진행:
    pages/_document.tsx 파일에서 진행한다.
    • Document의 getInitialPropsdocumentGetInitialProps를 import해 사용한다.
    • <Head> 안쪽에 <DocumentHeadTags>를 렌더한다.
+ import { DocumentHeadTags, documentGetInitialProps } from '@mui/material-nextjs/v13-pagesRouter'; // or `v14-pagesRouter` if you are using Next.js v14

 export default function MyDocument(props) {
   return (
     <Html lang="en">
       <Head>
+        <DocumentHeadTags {...props} />
         ...
       </Head>
       <body>
         <Main />
         <NextScript />
       </body>
     </Html>
   );
 }

+ MyDocument.getInitialProps = documentGetInitialProps;
  • pages/_app.tsx에서 <AppCacheProvider>를 최상위 엘리먼트로 렌더한다.
+ import { AppCacheProvider } from '@mui/material-nextjs/v13-pagesRouter'; // or `v14-pages` if you are using Next.js v14

 export default function MyApp(props) {
   return (
+    <AppCacheProvider {...props}>
       <Head>
         ...
       </Head>
       ...
+    </AppCacheProvider>
   );
 }
  • (Typescript 사용 시) DocumentHeadTagsProps을 Document의 프롭 인터페이스에 추가한다.
+ import type { DocumentHeadTagsProps } from '@mui/material-nextjs/v13-pagesRouter'; // or `v14-pagesRouter` if you are using Next.js v14

+ export default function MyDocument(props: DocumentProps & DocumentHeadTagsProps) {
   ...
 }

댓글

이 블로그의 인기 게시물

C# 남아도는 메모리에도 불구하고 OutOfMemoryException이 발생한다면?

USB를 뒤는 괜찮은데 앞에 꽂으면 인식이 힘들다?

MySQL 데이터 타입과 Java 데이터 타입 비교/매칭