프로젝트 생성 및 초기화
준비물
- 이 강의는 macOS에 최적화 되어 있습니다.
윈도우도 간간이 설명드리겠지만 macOS와 차이나는 부분은 검색을 통해 해결해보세요. - nodejs, yarn (이 강의에서는 npm 대신 yarn으로 설명드립니다)
- 프로그램 편집기는 vscode
- 윈도우 사용자는 반드시 Git Bash로 해보세요.
제가 윈도우 개발환경은 잘 몰라서, 시행착오를 겪다보니 Git Bash가 가장 좋더라구요.
먼저 이 강의를 들으시려면 Node.js를 먼저 설치하시기 바랍니다.
버전은 v14를 추천드리고, v16도 괜찮습니다.
그리고 가능하다면 npm 대신 yarn을 추천드립니다만, npm도 괜찮습니다.
npm은 Node.js를 설치하면 설치가 되고, yarn은 아래 다시 설명합니다.
그리고 코드편집기는 Vscode를 설치하세요~
윈도우 node 개발 환경 구성하기
윈도우 사용자라면 macOS의 터미널을 대신하여 윈도우를 리눅스처럼 만들어주는 Git Bash를 추천합니다.
윈도우 기본 파워쉘보다는 여러모로 Git Bash가 편합니다.
여기에서 자세히 확인하세요.
Yarn 설치
macOS에서 npm은 권한문제로 sudo 를 써 줘야할 때가 많아서 yarn을 설치하여 해결하겠습니다.
nodejs를 설치하면 npm도 기본적으로 설치될 거에요.
npm -v 명령어로 현재 설치된 버전을 확인해보세요.
설치가 안되어 있다면 반드시 nodejs를 설치 후 이 강의를 따라해주세요.
npm이 설치되어 있다면, 아래 명령어로 yarn을 설치합니다.
npm install -g yarn 혹시 에러메시지가 뜨면 sudo npm install -g yarn 으로 설치해주세요. sudo는 root비번을 물어볼 수 있습니다. 비번을 입력해서 설치해주세요.
에러 메시지 없이 설치가 잘 되었다면 다음 과정으로 넘어가주세요.
윈도우 사용자는 Git Bash까지 설치하세요.

Git Bash로 마음의 평화를 얻었습니다.
빠르게 Next.js 프로젝트 만들기
먼저 터미널을 열고 웹사이트를 만들 디렉토리로 이동하여 아래와 같이 입력합니다.
npx create-next-app tera-nextjs-mui5
cd tera-nextjs-mui
tera-nextjs-mui5에는 여러분이 만들기 원하는 앱의 이름을 입력하세요.

아래와 같이 메시지가 나오면 성공적으로 설치가 된 것입니다.
저의 경우 npm대신 yarn으로 빌드되는데, 여러분은 npm으로 표시 될 수도 있습니다. 그럴경우 강의 제일 윗부분의 yarn 설치를 다시 해 주세요.
✨ Done in 7.88s. Initialized a git repository. Success! Created tera-nextjs-mui5 at /Users/zauin/Project/lecture/tera-nextjs-mui5 Inside that directory, you can run several commands: yarn dev Starts the development server. yarn build Builds the app for production. yarn start Runs the built app in production mode. We suggest that you begin by typing: cd tera-nextjs-mui5 yarn dev
아래와 같이 입력하여 방금 만든 앱을 실행해 볼게요.
cd tera-nextjs-mui5 yarn dev

3000번 포트로 서버가 실행이 되었네요. 브라우저를 열고 접속해봅니다.
http://localhost:3000/
아래와 같이 Next.js 기본 페이지가 보입니다.

이제부터는 좀 어렵습니다.
너무 어렵다 생각되면 이해하려하지 마시고 그냥 복/붙 하세요.
_app.js 커스터 마이징 하기
자 이제 내가 만든 Next.js 앱 전체를 컨트롤하는 _app.js를 수정해볼게요.
그 전에 먼저 Material UI 5인 mui를 설치합니다.
터미널 창에서 Ctrl + C 로 앱을 잠시 중단하고 아래와 같이 입력합니다.
yarn add @mui/material@next @mui/icons-material@next @emotion/cache @emotion/react @emotion/server @emotion/styled npm으로 하는 분은 아래 명령어를 입력해보세요. npm install @mui/material@next @mui/icons-material@next @emotion/cache @emotion/react @emotion/server @emotion/styled --force
설치가 끝나면 vscode 로 프로젝트를 열고 편집을 해 보겠습니다.
./pages/_app.js를 열고 코드를 추가해보세요.
// ./pages/_app.js import Head from 'next/head'; import { ThemeProvider } from '@mui/material/styles'; import CssBaseline from '@mui/material/CssBaseline'; import { CacheProvider } from '@emotion/react'; import createEmotionCache from '../styles/createEmotionCache'; import "/styles/globals.css"; import theme from '../styles/theme'; // Client-side cache, shared for the whole session of the user in the browser. const clientSideEmotionCache = createEmotionCache(); export default function MyApp(props) { const { Component, emotionCache = clientSideEmotionCache, pageProps } = props; return ( <CacheProvider value={emotionCache}> <Head> <title>처음 만들어보는 Next.js + Mui5</title> <meta name="viewport" content="initial-scale=1, width=device-width" /> </Head> <ThemeProvider theme={theme}> {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */} <CssBaseline /> <Component {...pageProps} /> </ThemeProvider> </CacheProvider> ); }

Next.js는 SEO에 대응할 수 있는 SSR(서버사이드렌더링)이 가능합니다.
자세한 설명은 아래 주소를 참고하세요.
지금 클릭할 필요는 없습니다.
https://mui.com/material-ui/guides/server-rendering/
나중에 SSR을 사용하지 않고 만들다보면 SSR이 왜 필요한지 알게 됩니다.
CSR(Client-side Rendering)과 SSR(Server-side Rendering)에 대해 나중에 찾아보세요.
자 다시 강의로 돌아와서 아래처럼 emotion 캐시파일을 생성합니다.
(touch 명령어는 파일을 생성하는 리눅스 명령어입니다. 윈도우 사용자는 vscode에서 그냥 파일 생성해주세요.)
touch styles/createEmotionCache.js
그리고 생성한 파일의 코드를 아래와 같이 입력합니다.
import createCache from '@emotion/cache'; export default function createEmotionCache() { return createCache({ key: 'css' }); }

_document.js 커스터마이징 하기
파일을 생성하고
touch pages/_document.js
아래 코드를 붙여 넣어 주세요. 주석은 과감히 삭제해도 됩니다.
import * as React from 'react'; import Document, { Html, Head, Main, NextScript } from 'next/document'; import createEmotionServer from '@emotion/server/create-instance'; import createEmotionCache from '../styles/createEmotionCache'; import theme from '../styles/theme'; export default class MyDocument extends Document { render() { return ( <Html lang="en"> <Head> {/* PWA primary color */} <meta name="theme-color" content={theme.palette.primary.main} /> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" /> </Head> <body> <Main /> <NextScript /> </body> </Html> ); } } // `getInitialProps` belongs to `_document` (instead of `_app`), // it's compatible with static-site generation (SSG). MyDocument.getInitialProps = async (ctx) => { // Resolution order // // On the server: // 1. app.getInitialProps // 2. page.getInitialProps // 3. document.getInitialProps // 4. app.render // 5. page.render // 6. document.render // // On the server with error: // 1. document.getInitialProps // 2. app.render // 3. page.render // 4. document.render // // On the client // 1. app.getInitialProps // 2. page.getInitialProps // 3. app.render // 4. page.render const originalRenderPage = ctx.renderPage; // You can consider sharing the same emotion cache between all the SSR requests to speed up performance. // However, be aware that it can have global side effects. const cache = createEmotionCache(); const { extractCriticalToChunks } = createEmotionServer(cache); ctx.renderPage = () => originalRenderPage({ // eslint-disable-next-line react/display-name enhanceApp: (App) => (props) => <App emotionCache={cache} {...props} />, }); const initialProps = await Document.getInitialProps(ctx); // This is important. It prevents emotion to render invalid HTML. // See https://github.com/mui-org/material-ui/issues/26561#issuecomment-855286153 const emotionStyles = extractCriticalToChunks(initialProps.html); const emotionStyleTags = emotionStyles.styles.map((style) => ( <style data-emotion={`${style.key} ${style.ids.join(' ')}`} key={style.key} // eslint-disable-next-line react/no-danger dangerouslySetInnerHTML={{ __html: style.css }} /> )); return { ...initialProps, // Styles fragment is rendered after the app and page rendering finish. styles: [...React.Children.toArray(initialProps.styles), ...emotionStyleTags], }; };

theme 파일 만들기
touch styles/theme.js
아래 코드를 복붙합니다.
import { createTheme, responsiveFontSizes } from "@mui/material/styles";
import { deepPurple, amber } from "@mui/material/colors";
// theme 인스턴스 생성합니다.
// primary와 secondary는 여러분이 원하는대로 바꿔도 됩니다.
let theme = createTheme({
palette: {
primary: deepPurple,
secondary: amber,
},
});
// 화면 크기에 따라 MUI 반응형 글꼴을 설정합니다.
theme = responsiveFontSizes(theme);
export default theme;
홈페이지 기본 코드 삭제 및 변경
웹사이트의 첫페이지인 홈페지이파일인 ./pages/index.js 를 열고 아래와 같이 변경합니다.
나중에 스크롤 테스트를 위해 의미없는 텍스트를 길게 넣었습니다.
//./pages/index.js
import Container from "@mui/material/Container";
const Homepage = () => {
return (
<Container maxWidth="sm">
<h1>홈페이지</h1>
<p>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eos,
cupiditate! Odio, aliquam soluta vel, eum illum corrupti incidunt nobis
porro mollitia itaque reiciendis. Aut, minus dolore! Delectus pariatur
praesentium dolorem? In at, quibusdam vero eligendi provident veritatis
ipsam suscipit nisi similique nulla est magni harum. Cumque maiores eos
alias, aperiam ea deleniti voluptatem culpa a perferendis accusantium,
necessitatibus velit laborum. Molestias, reprehenderit accusantium. Ad
ipsa maiores, animi labore est voluptate eos aperiam iste adipisci sed
dolor consequatur dolore provident tenetur ipsum! Velit laudantium
excepturi accusantium numquam, similique nemo repellat impedit.
Reiciendis illo quibusdam atque possimus aliquid. Illo in voluptatum
nostrum quia nam fugit ipsa enim hic, eius sit qui recusandae dolorem
quis dolor ut deleniti est possimus. Fugiat, aliquam quam. Itaque
officiis culpa laborum voluptatum vel exercitationem temporibus, eos ad,
ab eum inventore, hic quaerat ea cumque dignissimos dolorem maxime.
Adipisci illo aspernatur eum. Minus, amet pariatur. Culpa, ratione
expedita. Nemo doloribus dignissimos, deleniti sit veniam quae deserunt
a nam sed, voluptas officia est recusandae consectetur exercitationem
omnis? Neque impedit aspernatur tempora iusto distinctio nam amet
recusandae inventore culpa eligendi! Sapiente accusantium aut animi eos
iusto officia ipsum exercitationem illo quae, cumque quidem, nemo amet
ad dicta fugit laboriosam mollitia soluta ratione corrupti maxime odit.
Ipsum tenetur architecto vel ullam. Hic at, veritatis dolore, beatae
totam amet alias unde odit veniam dolorum eos molestias quidem quo
explicabo asperiores libero assumenda nulla velit nihil. Rerum error
culpa cum voluptatibus beatae magnam? Repudiandae ratione iure,
similique rerum dolore consectetur animi vitae qui delectus pariatur
sapiente atque eos quaerat sed consequatur, quo suscipit optio harum
aliquam adipisci vero. Nihil neque nisi eius. Laborum. Voluptatem
voluptate officia numquam ut quae. Quod facilis pariatur in nostrum cum
quidem at nesciunt fugiat est unde enim commodi, animi nihil, recusandae
rerum ducimus sint qui assumenda distinctio id! Natus ea fugit molestiae
nostrum! Obcaecati nisi itaque harum. Officia temporibus nobis
repellendus beatae dolorem tempore accusamus! Quas debitis quos incidunt
dolore aliquam, quam assumenda alias, totam omnis aspernatur saepe? Non
debitis ab quis inventore vero. Possimus dicta labore quibusdam
consequatur incidunt ea molestias fugit tenetur facere autem reiciendis
animi amet, eligendi nobis impedit sunt consectetur deserunt doloremque
nisi! Minus. Accusamus nam a soluta porro repudiandae quis at cupiditate
ad impedit aperiam recusandae blanditiis ut enim repellendus velit qui
cumque alias doloribus, accusantium voluptas quam eius! Consequuntur
velit commodi minima. Saepe magnam fugit est et! Vel cumque modi itaque
maiores vitae id, esse autem provident necessitatibus eius porro fuga,
quod laborum, veritatis eum repellendus voluptatem aliquam ad
perferendis quasi corrupti? Voluptates blanditiis earum optio omnis
consectetur sapiente? Aliquid, expedita distinctio enim quos quis autem
totam blanditiis ducimus laborum temporibus non. Repellat eaque aliquid
perspiciatis fuga iste nam! Ut, iusto suscipit.
</p>
</Container>
);
};
export default Homepage;
안쓰는 파일 삭제
맥에서는 아래 rm 명령이지만, 윈도우 사용자라면 그냥 탐색기나 vscode에서 지우면 됩니다.
rm styles/Home.module.css
rm pages/api/hello.js

초기 설정 완료
초기 설정이 끝났습니다. 서버를 다시 실행해서 화면을 보겠습니다.
yarn dev http://localhost:3000

좀, 어렵죠? 이 수업이 가장 어렵습니다. 여기까지 쉬웠다면, 앞으로 얼마나 더 쉬울까요^^
Next.js의 내부를 잘 알아야 이해가 가능한 부분이라, 그냥 이해하지 말고 이 수업은 복/붙으로 넘어가세요.
다음 수업부터는 조금 쉬워질거에요.
윈도우에서도 저도 좌충우돌 성공했습니다.
다시한번 Git Bash + yarn 을 추천드립니다.
