๋ชฉ์ฐจ
- Next.js๋?
- Next.js ๋ฑ์ฅ ๋ฐฐ๊ฒฝ
- React์ Next.js์ ์ฐจ์ด์
- Next.js ๊ฐ๋ฐํ๊ธฐ
- ํ์
์คํฌ๋ฆฝํธ ์ ์ฉ
- ๋ฐ๋ฒจ/์นํฉ ์ปค์คํฐ๋ง์ด์ง
Next.js๋?
- ๋ฆฌ์กํธ๋ฅผ ์ํด ๋ง๋ค์ด์ง ์คํ์์ค ์๋ฐ์คํฌ๋ฆฝํธ ์น ํ๋ ์์ํฌ
= ๋ฆฌ์กํธ ํ๋ ์์ํฌ
- ๋ค์ํ ๋ ๋๋ง ๋ฐฉ์
- ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR)
- ์ ์ ์ฌ์ดํธ ์์ฑ(SSG)
- ์ฆ๋ถ ์ ์ ์ฌ์์ฑ(ISR)
- ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง(CSR)
- ์๋ง์ ๋ด์ฅ ์ปดํฌ๋ํธ์ ํ๋ฌ๊ทธ์ธ ์ ๊ณต
- ์๊ท๋ชจ ์น ์ฌ์ดํธ, ๊ฑฐ๋ํ ์์ฉ ์ ํ๋ฆฌ์ผ์ด์
๋ชจ๋ ์ ์ฉ ๊ฐ๋ฅ
Next.js ๋ฑ์ฅ ๋ฐฐ๊ฒฝ
- ์น ๊ฐ๋ฐ ๋ถ์ผ์ ๋ฐ๋ฌ์ ๋ฐ๋ผ
- ๋์ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์ฌ์ฉ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ๋ฐํ๋ ๋ฆฌ์กํธ ๋ฑ์ฅ
๋ฆฌ์กํธ์ ํฐ ๋ฌธ์ ์
- ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง(CSR)๋ง ๊ฐ๋ฅ
- ๊ฒ์ ์์ง ์ต์ ํ(SEO) ๊ฑฐ์ ์ ๋จ
- ์น ์ฑ์ ์์ ํ ํ์ํ๋ ค๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ์ ์ฒด ์น์ฑ ๋ฒ๋ค์ ๋ค์ด๋ก๋ํด์ผ ํจ
- ๊ท๋ชจ๊ฐ ํฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฒซ ํ๋ฉด ํ์๊น์ง ์ ์ด๊ฐ ๊ฑธ๋ฆผ
์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR) ์ ์
- ๋ฆฌ์กํธ ์ฑ์ ์์ HTML ํ์ด์ง๋ก ์๋ฒ์์ ๋ฏธ๋ฆฌ ๋ ๋๋งํด๋๊ณ
- ๋ธ๋ผ์ฐ์ ๊ฐ ์ด๋ฅผ ๋ค์ด๋ก๋ํ์๋ง์ HTML์ ์ฆ๊ฐ ํ๋ฉด์ ํ์
- ๋ก๋ฉ ์๋๊ฐ ๋น ๋ฅด๊ฒ ๋๊ปด์ง
- ์ดํ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค๊น์ง ๋ค์ด๋๋ฉด ์ฌ์ฉ์๊ฐ ์น์ฑ๊ณผ ์ํธ ์์ฉ
Next.js ๋ฑ์ฅ
๋ฆฌ์กํธ๊ฐ ์ ๊ณตํ์ง ์๋ ๋ค์ํ ๊ธฐ๋ฅ ์ ๊ณต
- ์ฝ๋ ๋ถํ (code splitting)
- ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง (SSR)
- ํ์ผ ๊ธฐ๋ฐ ๋ผ์ฐํ
(=> react-router-dom ๋ถํ์)
- ๊ฒฝ๋ก ๊ธฐ๋ฐ pre-fetching (preload ๊ธฐ๋ฅ)
- ํด๋ผ์ด์ธํธ์ ์๋ฒ ์์ธก์์ ๋ชจ๋ ๊ฐ๋ฐ ๊ฐ๋ฅ
๊ทธ ์ธ ๊ธฐ๋ฅ
- ์ ์ ์ฌ์ดํธ ์์ฑ(SSG) ๋ ๋๋ง ๋ฐฉ์
- ์ฆ๋ถ ์ ์ ์ปจํ
์ธ ์์ฑ(ISR) ๋ ๋๋ง ๋ฐฉ์
- ํ์
์คํฌ๋ฆฝํธ ๊ธฐ๋ณธ ์ง์
- ์๋ polyfill ์ ์ฉ
- ์ด๋ฏธ์ง ์ต์ ํ
- ๊ตญ์ ํ ์ง์ (i18n)
- ์ฑ๋ฅ ๋ถ์
React์ Next.js์ ์ฐจ์ด์
- Next.js์ ๊ธฐ๋ณธ ์ฒ ํ์ ๋ฆฌ์กํธ์ ๊ฑฐ์ ๋์ผ
- ์ค์ ๋ณด๋ค ๊ด์ต (convention-over-configuration)
- ๊ฐ๋ฅํ ํ ๋ณต์กํ ์ค์ ์์ด '๊ด์ต'๋๋ก ์ฌ์ฉํ๋ฉด ์น์ฑ ๊ฐ๋ฐ ๊ฐ๋ฅ
- ์: ๋ณ๋์ ์ค์ ํ์ผ ์์ด ์ด๋ค ํ์ด์ง๋ SSR์ ์ ์ฉํ๊ณ ์ด๋ค ํ์ด์ง๋ SSG ์ ์ฉ ๊ฐ๋ฅ (๊ฐ ํ์ด์ง์์ ํน์ ํจ์๋ฅผ exportํ๋ฉด Next.js๊ฐ ๋๋จธ์ง ์์์ ์ฒ๋ฆฌ)
- ๋ฆฌ์กํธ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ, Next.js๋ ํ๋ ์์ํฌ
- Next.js์์ ์๋ฒ ์ธก ์ฝ๋ ๊ฐ๋ฐ ๊ฐ๋ฅ
- Node.js ์๋ฒ ๊ธฐ๋ฐ
- fetch, window, document์ ๊ฐ์ ์น ๋ธ๋ผ์ฐ์ ์ ์ญ ๊ฐ์ฒด๋ canvas ๊ฐ์ HTML ์์๋ Next.js์์ ์ ๊ทผ ๋ถ๊ฐ
- fs, child_process ๋ฑ Node.js์์๋ง ์ฌ์ฉ ๊ฐ๋ฅํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ/API ์ฌ์ฉ ์
- ๊ฐ ์์ฒญ๋ณ ๋ฐ์ดํฐ๋ฅผ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ด๊ธฐ ์ ์ Next.js๊ฐ ์๋ฒ ์ฌ์ด๋ ์ฝ๋๋ฅผ ์คํํ๊ฑฐ๋ ํ์ด์ง ์์ฑ ์์ ์ ํด๋น ์ฝ๋๋ฅผ ์ฒ๋ฆฌ
- ์ด๋ค ๋ฐฉ์์ ์ฐ๋์ง๋ ๊ฐ ํ์ด์ง๊ฐ ์ฌ์ฉํ๋ ๋ ๋๋ง ๋ฐฉ์์ ๋ฐ๋ผ ๋ค๋ฆ
Next.js ๊ฐ๋ฐํ๊ธฐ
์ค์น
create 'react' app ์๋๊ณ create 'next' app
npx create-next-app [ํ๋ก์ ํธ ๋ช
]
์คํ
npm run dev // localhost:3000
๊ธฐ๋ณธ ํด๋ ๊ตฌ์กฐ
ํ์ ํด๋ 2๊ฐ์ง (pages/, public/)
- README.md
- next.config.js
- node_modules/
- package-lock.json
- package.json
- pages/ => ํ์!
- _app.js
- api/ => ์๋ฒ ๊ฐ๋ฐ์ ์ํ ํด๋
- hello.js
- index.js
- public/ => ํ์!
- favicon.ico
- vercel.svg
- styles/
- Home.module.css
- globals.css
pages/ ํด๋
- ํ์ด์ง ๊ธฐ๋ฐ ๋ผ์ฐํ
์ ์ํ ํด๋
- pages/ ํด๋ ์์ ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ ํ์ด์ง๊ฐ ๋จ
- ํ์ผ ์ด๋ฆ์ด ๊ณง ๋ผ์ฐํ
๊ฒฝ๋ก
- ์: pages/about.js =>
http://localhost:3000/about
public/ ํด๋
- ์น ์ฌ์ดํธ์ ๋ชจ๋ public ํ์ด์ง์ ์ ์ ์ปจํ
์ธ ๋ฅผ ํฌํจ
- ์: ์ด๋ฏธ์ง ํ์ผ, ํฐํธ, (์ปดํ์ผ๋) CSS ์คํ์ผ์ํธ, (์ปดํ์ผ๋) ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ ๋ฑ
ํ์
์คํฌ๋ฆฝํธ ์ ์ฉ
- Next.js๋ ํ์
์คํฌ๋ฆฝํธ๋ก ์์ฑ๋ ํ๋ ์์ํฌ
- ๊ณ ํ์ง์ ํ์
์ ์ ์ง์
Next.js์์ TS๋ฅผ ๊ธฐ๋ณธ ์ธ์ด๋ก ์ฌ์ฉํ๊ธฐ
-
์ต์์ ๋๋ ํ ๋ฆฌ์ tsconfig.json ํ์ผ ์์ฑ
- ์ด ๋๋ ํ์ผ ์์ ์๋ฌด ๊ฒ๋ ์์
- ํ์ง๋ง ์๋ ํจํค์ง๋ฅผ ์ค์นํ๊ณ ๋๋ฉด ํ์ํ ๊ธฐ๋ณธ ์ค์ ๋ด์ฉ์ด ์ฌ๊ธฐ์ ๊ธฐ๋ก๋จ
-
npm run dev ์คํ
-
ํฐ๋ฏธ๋์ ํ์ธํ๋ฉด...
It looks like you're trying to use Typescript but do not have the required package(s) installed. (ํ์
์คํฌ๋ฆฝํธ ์ฐ๋ ค๊ณ ํ๋ ๊ฑฐ ๊ฐ์๋ฐ ํ์ํ ํจํค์ง๊ฐ ์ค์น ์ ๋์ด ์์ด)
... (ํ์ํ ํจํค์ง ์ค์น ๋ช
๋ น์ด)
-
ํฐ๋ฏธ๋์์ ์๋ ค์ค ํจํค์ง๋ค(= ํ๋ก์ ํธ๊ฐ ์ฌ์ฉํ๋ ์ฃผ ์ธ์ด์ ๋ํ ์์กด์ฑ ํจํค์ง) ์ค์น
- ์ฃผ์: ๊ฐ๋ฐ์๋ง ์ฐ์ด๋ ๊ฒ๋ค์ด๋ฏ๋ก dev๋ก ์ค์น
npm install --save-dev typescript @types/react @types/node
- ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ(.js)์ ํ์
์คํฌ๋ฆฝํธ ํ์ผ(.ts)๋ก ์์
- ์ต์์ ๋๋ ํ ๋ฆฌ์ next-env.d.ts
- ์ด ํ์ผ์ ๋ง์๋๋ก ์์ ํด๋ ๋์ง๋ง ์ง์ฐ๋ฉด ์ ๋จ
๋ฐ๋ฒจ๊ณผ ์นํฉ ์ค์ ์ปค์คํฐ๋ง์ด์ง
๋ฐ๋ฒจ์ด๋?
- ์๋ฐ์คํฌ๋ฆฝํธ ํธ๋์ค์ปดํ์ผ๋ฌ(transcompiler)
- ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ๊ตฌ์ ๋ธ๋ผ์ฐ์ ์์๋ ํธํ๋๋ ์คํฌ๋ฆฝํธ ์ฝ๋๋ก ๋ณํ
- ECMAScript ๋ช
์ธ๋ก ๋ฐํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ ๊ธฐ๋ฅ์ ์ง๊ธ ํ๊ฒฝ์์ ๋ฐ๋ก ์คํ ๊ฐ๋ฅ
- ์: Node.js๋ export default ํค์๋๋ฅผ ๋ชจ๋ฅด์ง๋ง ๋ฐ๋ฒจ ์ค์ ์ ํ๋ฉด ์๋ฌด ๋ฌธ์ ์์ด ์ฌ์ฉ ๊ฐ๋ฅ
๋ฐ๋ฒจ ์ค์ ์ปค์คํฐ๋ง์ด์ง
- ์ต์์ ๋๋ ํ ๋ฆฌ์ .babelrc ํ์ผ ์์ฑ
- ์๋๋ ์ต์ํ ๋ค์ด๊ฐ ์์ด์ผ ํ๋ ๋ด์ฉ
= Vercel ํ์์ ๋ฏธ๋ฆฌ ์ค์ ํ ๋ฐ๋ฒจ ์ค์
{
"presets": ["next/babel"]
}
์นํฉ์ด๋?
- ํน์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ํ์ด์ง, ๊ธฐ๋ฅ์ ๋ํด ์ปดํ์ผ๋ ์ฝ๋๋ฅผ ์ ๋ถ ํฌํจํ๋ ๋ฒ๋ค ์์ฑ
- ์: ์๋ก ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ฐ๊ฐ ํ๋์ฉ 3๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ค๋ ํ์ด์ง
- ์ด๊ฑธ ์นํฉ์ด ์คํ ๊ฐ๋ฅํ ํ๋์ ๋ฒ๋ค๋ก ํฉ์ณ์ค
- ์น์์ ์ฌ์ฉํ๋ ๋ชจ๋ ์์(์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ, CSS, SVG ๋ฑ)์ ๋ํด ๊ฐ๊ธฐ ๋ค๋ฅธ ์ปดํ์ผ, ๋ฒ๋ค, ์ต์ํ ์์
์ ์ฒ๋ฆฌํด์ฃผ๋ ์ผ์ข
์ ์ธํ๋ผ(infrastructure)
- ์: CSS ์ ์ฒ๋ฆฌ๊ธฐ(SASS)๋ฅผ ์ปดํฌ๋ํธ ์คํ์ผ๋ง์ ์ฌ์ฉํ ๋
- ์นํฉ ์ค์ ์ ์์ ํด์ SASS ํ์ผ์ ์ฒ๋ฆฌ ํ CSS ํ์ผ์ ๋ง๋ค๋๋ก ํจ
๋ฐ๋ฒจ/์นํฉ ์ ์์ฌํญ
- ๊ธฐ๋ณธ ๋ฐ๋ฒจ ์ค์ ์ด๋ ์นํฉ ์ค์ ์ ์์ ๋กญ๊ฒ ๋ฐ๊ฟ ์ ์์
- ํ์ง๋ง '์ค์ ๋ณด๋ค๋ ๊ด์ต'์ด๋ผ๋ ์ทจ์ง ํ์ ์ค์ ๊ฐ๋ฐ ์ ์ค์ ์ ๋ฐ๊พธ๊ธฐ๋ณด๋ค๋ Next.js๊ฐ ์ง์ ํ ์ฝ๋ ์ปจ๋ฒค์
์ ๋ฐ๋ผ ๊ฐ๋ฐํ ์ผ์ด ๋ ๋ง์
- ๋น๋ ๊ณผ์ ์ ๊ผญ ์์ ํด์ผ ํ๋ค๋ฉด ๋๋ถ๋ถ next.config.js๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ์ผ๋ก ์ถฉ๋ถ
- next.config.js์์ ๋ณ๊ฒฝํ ์ค์ ์ ๋ด์ ๊ฐ์ฒด๋ฅผ export๋ก ๋ด๋ณด๋ด๋ฉด ํด๋น ๊ฐ์ด Next.js์ ๊ธฐ๋ณธ ์ค์ ์ ๋ฎ์ด์
// next.config.js
module.exports = {
// ๋ณ๊ฒฝํ ์ค์ ๊ฐ (๊ฐ์ฒด - key: value ํํ)
}
- ์: ๊ธฐ๋ณธ ์นํฉ ์ค์ ๊ฐ์ ๋ฐ๊พธ๊ณ ์ถ๋ค๋ฉด?
- next.config.js์ ๊ฐ์ฒด์ 'webpack'์ด๋ผ๋ key์ ์๋ก์ด ๊ฐ ์ง์
// ์นํฉ ๋ก๋์ ์ปค์คํ
ํ loader ์ถ๊ฐํ๊ธฐ (์ค์ ๋์ํ๋ ์ฝ๋ ์๋)
module.exports = {
webpack: (config, options) => {
config.module.rules.push({
test: /\.js/,
use: [
options.defaultLoaders.babel,
{
loader: "my-custom-loader", // ์ฌ์ฉํ ์ปค์คํ
๋ก๋
options: loaderOptions, // ์ปค์คํ
๋ก๋์ ์ต์
},
],
});
return config;
},
}