๐Ÿค ์€์ง€log ๐Ÿค

[NextJS] NextJS ์—์„œ Material-Ui ์‚ฌ์šฉํ•˜๊ธฐ ๋ณธ๋ฌธ

๐ŸŒท Next JS

[NextJS] NextJS ์—์„œ Material-Ui ์‚ฌ์šฉํ•˜๊ธฐ

Eun_zii 2023. 3. 24. 14:35

๐Ÿ“ ํ”„๋กœ์ ํŠธ ์„ธํŒ…

  • next ํ”„๋กœ์ ํŠธ๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์ดํ›„ ํ•„์š”ํ•œ ๋””ํŽœ๋˜์‹œ๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
npx create-next-app my-app

cd my-app
npm i @emotion/react @emotion/styled @mui/icons-material @mui/material @mui/styles

 

 

nextjs๋Š” ์„œ๋ฒ„์‚ฌ์ด๋“œ๋žœ๋”๋ง์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— react์—์„œ mui๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ์†์‰ฝ๊ฒŒ ๋ฐ˜์˜ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ช‡๊ฐ€์ง€ ์‚ฌ์ „์ž‘์—…์„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ“ _document.tsx

  • _document๋Š” ์„œ๋ฒ„์‚ฌ์ด๋“œ์— ๊ด€์—ฌํ•˜๋Š” ๋กœ์ง ๋˜๋Š” staticํ•œ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (_document๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค๋ฉด nextjs ๊ธฐ๋ณธ (opens new window)์ด ํฌ์ŠคํŒ…์„ ์ฐธ์กฐํ•ด์ฃผ์„ธ์š”.)
  • ssr ์ง€์›์„ ์œ„ํ•ด _dococument.tsx์— mui์— ๋Œ€ํ•œ ์‚ฌ์ „ ์ž‘์—…์„ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ html, css์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ Œ๋”๋งํ•œ html, css๊ฐ€ ๋‹ค๋ฅด๋ฉด next์—์„œ warning์„ ๋„์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์„œ๋ฒ„๋‹จ์—์„œ mui๋ฅผ ์ง€์›ํ•จ์œผ๋กœ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ„ ๊ฐ„๊ทน์„ ๋งž์ถ”๊ธฐ ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

 
import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
import { ServerStyleSheets } from "@mui/styles";

export default class MyDocument extends Document {
  render() {
    return (
      <Html>
        <body>
          <Head></Head>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

MyDocument.getInitialProps = async ctx => {
  const materialSheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: App => props => materialSheets.collect(<App {...props} />)
    });

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

 

๐Ÿ“ _app.tsx

  • nextjs์—์„œ mui๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ํ•„์ˆ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์›น์„ ์ •์ƒ์ ์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ผญ ํ•„์š”ํ•œ CssBaseline๋ฅผ ์ด๊ณณ์—์„œ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

CssBaseline

  • ํ”„๋กœ์ ํŠธ๋ฅผ ์ฒ˜์Œ ๊ตฌ์ƒํ•˜๊ณ  ์‹คํ–‰ํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๋งˆ๋‹ค ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๊ธฐ๋ณธ css๊ฐ€ default๋กœ ์„ค์ • ๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ์šฐ๋ฆฌ๋Š” ์ •์ƒ์ ์ธ ๊ตฌํ˜„์„ ์œ„ํ•ด ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ผ๊ด€์ ์œผ๋กœ ๋ณด์ด๋„๋ก ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” css๋ฅผ ์ „์—ญ์—์„œ normalize ํ•˜๊ธฐ ์œ„ํ•ด <CssBaseline />๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. <CssBaseline />๋Š” ์•ฑ์˜ ์ตœ์ƒ๋‹จ์— ๋„ฃ์–ด์ฃผ๋ฉด ์•Œ์•„์„œ normalize ํ•ด์ค๋‹ˆ๋‹ค.

 

// _app.tsx
import type { AppProps } from "next/app";
import CssBaseline from "@mui/material/CssBaseline";

const App = (props: AppProps) => {
  const { Component, pageProps } = props;

  return (
    <>
      <CssBaseline />
      <Component {...pageProps} />
    </>
  );
};

export default App;

 

๐Ÿ“ ์‚ฌ์šฉํ•˜๊ธฐ

์—ฌ๊ธฐ ๊นŒ์ง€ ์˜ค์…จ๋‹ค๋ฉด ๊ธฐ๋ณธ์ ์ธ ์„ธํŒ…์ด ๋ชจ๋‘ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ mui๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import type { NextPage } from "next";
import Button from "@mui/material/Button";

const Home: NextPage = () => {
  return (
    <div>
      <Button variant="contained">Contained</Button>
      <Button variant="outlined">Outlined</Button>
    </div>
  );
};

export default Home;
728x90