์ด์ ๋ถํฐ Webpack์ ์ด์ฉํด ๋ง๋ค์ด๋๊ณ ์ถ์๋ React ๋ณด์ผ๋ฌํ๋ ์ดํธ๋ฅผ ๋ง๋ค์ด๋ดค๋ค. ์ฌ๋ฌ ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ๊ณ ํ๋ฉฐ ๋ง๋ค์ด๋ดค๋๋ฐ ํ๋ฌ๊ทธ์ธ ๋ถํฐ ๋ก๋, ์ค์ ๋ด์ฉ๊น์ง ํ๋ํ๋ ์ฐจ๊ทผ์ฐจ๊ทผ ๊ธฐ๋กํ๋ฉฐ ์ดํด๋ณด์. ํ์ฌ์ ๋ด๊ฐ๋ง๋ ๋ณด์ผ๋ฌํ๋ ์ดํธ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ๋ฑ์ด ์ ์ ์์ฌ๊ฐ๋ ๊ฑธ ๋ณด๋ฉฐ ํ๋ค์ง๋ง ๋ฟ๋ฏํ ์์ฆ์ด๋ค..โญ๏ธ
Webpack ์ด๋?
์นํฉ์ ๋จ์ํ ๋งํ์๋ฉด ๋ชจ๋ ๋ฒ๋ค๋ฌ์ด๋ค.
- ๋ชจ๋ : ์นํฉ์์์ ๋ชจ๋์ ๊ฐ์ข .js .css .png ๋ฑ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ฑํ๋ ์์์ ๋งํ๋ค.
- ๋ฒ๋ค๋ฌ : ์์์ ์กฐํฉํด์ ๋น๋ ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋๋ ์ญํ
ES2015๋ถํฐ ๋ชจ๋ ์ด๋ผ๋ ๋ฌธ๋ฒ์ ์ง์ํ๊ฒ ๋์๊ณ ์ด ๋ชจ๋์ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ค๋ฅธ ์ฌ๋์ ์ฝ๋๋ ๋ด๊ฐ ๋ง๋ ์ฝ๋๋ค์ ์ฌ์ฌ์ฉํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ค. ๊ธฐ์กด์๋ <script> ํ๊ทธ๋ฅผ ํตํด ์ฝ๋๋ฅผ ๋ถ๋ฌ์ค๊ณ ํด๋น ์ฝ๋๋ฅผ window ๊ฐ์ฒด๋ฅผ ํตํด ๋ถ๋ฌ์์ ์ฌ์ฉํ์ง๋ง ํด๋น ๋ฐฉ์์ ์ ์ญ ์ค์ฝํ๊ฐ ๋๋ฌ์ ์ง๋ฉฐ ๋ถ๋ฌ์จ ์ฝ๋์์ ๊ฐ์ ๋ณ์๋ฅผ ์ฌ์ฉํ ๋ ์ถฉ๋์ด ๋ ์ ์๋ค.
๋ชจ๋์์คํ ์ด ์ฌ๋ฌ ์ปค๋ฎค๋ํฐ์์ ๋์ค๊ฒ ๋๋๋ฐ ๋ํ์ ์ธ ๋ฐฉ๋ฒ์ 4๊ฐ์ง๋ค.
- AMD(Asynchronous Module Definition) : ๋น๋๊ธฐ์ ๋ชจ๋ ๋ฐฉ์์ผ๋ก ๋ชจ๋์ ์ ์์ ์์กด์ฑ ๊ด๋ฆฌ๋ฅผ ์ํ API(ํจ์)๋ฅผ ์ ๊ณตํ๊ณ ๋ธ๋ผ์ฐ์ ์์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ชจ๋์ ๋ก๋ํด์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ ๋ํ์ ์ผ๋ก RequireJS ๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ค.
- CJS(CommonJS) : Node ์์ ์ฑํํ ๋ฐฉ์์ผ๋ก ํ์ฌ๋ eslintrc.cjs ๋ฑ์ ์ค์ ํ ๋ ์์ฃผ ์ฌ์ฉํ๋ module.exports ๋ก ๋ด๋ณด๋ด๊ณ require ๋ก ๋ถ๋ฌ์ค๋ ๋ฐฉ์์ด๋ค. (์์ฆ์ Node ํ๊ฒฝ์์๋ ESM ๋ฐฉ์์ ์ง์ํ๊ธด ํ๋ค.)
- UMD(Universal Module Definition) : CJS์ AMD ๋ฐฉ์์ ๋ชจ๋ ํธํํ๊ธฐ ์ํด ๋์จ ๋ฐฉ์์ด๋ค.
- ESM (ES2015) : ๋ฌธ๋ฒ ์์ฒด์์ ์ง์ํ๋ ๋ฐฉ์์ผ๋ก import / export ๋ก ์ด๋ฃจ์ด์ง ๊ฐ์ฅ ์ต์ํ ๋ฐฉ์์ด๋ค.
Webpack ์ค์น
// node ํ๊ฒฝ์ด ๊ตฌ์ฑ์ด ๋์ด์์ง ์๋ค๋ฉด
// npm or yarn or pnpm init ๋ช
๋ น์ด๋ก package.json ํ์ผ์ ์์ฑํด ์ฃผ์ธ์.
// ์ด ๊ธ์์๋ npm์ ์ด์ฉํฉ๋๋ค.
npm install -D webpack @types/webpack webpack-cli
yarn add -D webpack @types/webpack webpack-cli
pnpm add -D webpack @types/webpack webpack-cli
- ์ํ๋ ํจํค์ง ๋งค๋์ ๋ฅผ ํตํด ์ค์นํ๋ค. -D ์ต์ ์ผ๋ก production ๋น๋ ์ ํฌํจ๋์ง ์๋๋ก ํด์ค๋ค.
- webpack์ ๋ง ๊ทธ๋๋ก webpack, webpack-cli๋ webpack์ cmd ๋ฑ์์ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
Config ํ์ผ ์์ฑ
ํ๋ก์ ํธ์ ๋ฃจํธ ๊ฒฝ๋ก์ webpack.config.{js ๋๋ ts} ํ์ผ์ ๋ง๋ค๋ฉด ๋๋ค.
// webpack.config.js
module.exports = {
...other
}
// webpack.config.ts
const config: Configuration = {
...other
}
export default config
Config ํ์ผ ์์ฑ
webpack config ํ์ผ์ ์ปค์คํ ํ ๋ ์ฃผ๋ก ์ฌ์ฉ๋๋ ์ต์ ๋ค์ด ์๋ค. ๋ง์ฝ ts ํ์ฅ์๋ก ํ์ผ์ ๋ง๋ค์ด ์คฌ๋ค๋ฉด ๊ฐ์ฒด ๋ด๋ถ์ ์ด๋ค ์ต์ ๋ค์ด ์๋์ง vscode์์ ์ถ๋ก ํ์ฌ ์๋์์ฑ์ ์ ๊ณตํด์ค๋ค. (์๋๋ผ๋ฉด ๊ณต์๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์)
npm i react react-dom react-router-dom
npm i -D @types/react @types/react-dom @types/node typescript
- ์นํฉ ์ค์ ์ ์์ ์ด ๊ธ์ ์์ง์ธ Webpack์ ํตํ React ๊ตฌ์ฑ์ด ํต์ฌ์ด๋ฏ๋ก React ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ์.
- ๊ทธ๋ฆฌ๊ณ ์ด๋ฏธ์ง์ ๊ฐ์ด scripts์ ๋น๋ ๋ช ๋ น์ด๋ฅผ ์ถ๊ฐํด์ค๋ค. --mode๋ development์ production์ด ์๋๋ฐ ์ถํ config ํ์ผ์์ ๋ค์ ์ค์ ํด ์ค ์์ ์ด๋ฏ๋ก ์ผ๋จ์ ํ ์คํธ๋ฅผ ์ํด production์ผ๋ก ๋ฃ์ด์ค๋ค.
<!-- pubilc/index.html -->
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
// src/index.tsx
import * as ReactDOM from "react-dom/client";
import App from "./App";
import { StrictMode } from "react";
const root = document.getElementById("root");
ReactDOM.createRoot(root as HTMLElement).render(
<StrictMode>
<App />
</StrictMode>
);
// src/App.tsx
const App = () => {
return <div>App</div>;
};
export default App;
- public ํด๋๋ฅผ ์์ฑํ๊ณ index.html ํ์ผ์ ๋ง๋ค์ด body์ ์์์ผ๋ก ๋ ๋๋ง์ ์ํ root id๋ฅผ ๊ฐ์ง div DOM์ ์ถ๊ฐํด์ค๋ค.
- src ํด๋ ์์ index.tsx, App.tsx ํ์ผ์ ์์ฑํ๊ณ index.tsx๋ ๋ง๋ค์ด ๋ DOM์ ์ ๋ ํด Root๋ก ๋ง๋ค๊ณ App ์ปดํฌ๋ํธ๋ฅผ ๋ ๋ํด์ค๋ค. (StrictMode๋ ์ ์ฉ)
- ์ด๋ ๊ฒ ๊น์ง ๊ตฌ์ฑ์ ํ๋ค๋ฉด ์๋ง React๋ UMD ์ ์ญ์ ์ฐธ์กฐํ๋ค๋ ์๋ฌ๊ฐ ๋ ํ ๋ฐ React๋ v17 ์ดํ๋ก import React from 'react'๋ฅผ ์์ฑํ์ง ์์๋ ๋๋ค. ๋ฐ๋ก ๋ค์์ tsconfig๋ฅผ ํตํด ์๋ฌ๋ฅผ ์์ ๋ณด์.
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"outDir": "dist",
"jsx": "react-jsx"
}
}
- ๋ ๋ง์ ์ค์ ์ ํด์ค์ผ ํ์ง๋ง ๋จ๊ณ๋ณ๋ก ๊ฑฐ์น๋ฉด์ ์ค์ ํ๊ธฐ ์ํด ์ต์ํ์ ์ค์ ๋ง ํด๋์. baseUrl๊ณผ outDir์ ๋ง๊ทธ๋๋ก ๋ฒ ์ด์ค ๊ฒฝ๋ก์ output ์ ๊ฒฝ๋ก๋ฅผ ์ค์ ํด์ค๊ฒ. jsx ์ต์ ์ ํตํด react-jsx๋ฅผ ๋ช ์ํด์ฃผ๋ฉด React import Error๋ ํด๊ฒฐํ ์ ์๋ค.
Babel-loader ์ค์
์๋ฐ์คํฌ๋ฆฝํธ๋ ๊ณ์ ๋ฐ์ ํ๋ฉฐ ๋ ํธ๋ฆฌํ ๋นํธ์ธ ๋ฉ์๋์ ๋ฌธ๋ฒ์ ์ ๊ณตํ๊ณ ์๋ค. ํ์ง๋ง IE๊ฐ์(ํ์ฌ IE๋ ์ฃฝ์๋ค.) ๋ธ๋ผ์ฐ์ ๋ ๋ฎ์ ๋ฒ์ ์ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ฌ์ฉํ๋ ์ฌ๋๋ค์๊ฒ ์ ๋ฐ์ดํธ ๋ ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ์ดํดํ์ง ๋ชปํ๋ค. ์ด๋ฅผ ํด๊ฒฐํ ๋ฐฉ๋ฒ์ผ๋ก ๋ฐ๋ฒจ์ ํตํด ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ ์ปดํ์ผํ์ฌ ์ด์ ๋ธ๋ผ์ฐ์ ์์๋ ์ ๋์๊ฐ๋๋ก ๋ง๋ค์ด์ฃผ๋ ์ ์ฉํ ์๋ฐ์คํฌ๋ฆฝํธ ์ปดํ์ผ๋ฌ๋ค.
์นํฉ์ ๋ฐ๋ฒจ ๋ฟ๋ง ์๋๋ผ css, svg ๋ฑ์ ๋ฆฌ์์ค๋ฅผ ๋ธ๋ผ์ฐ์ ์์ ์ดํดํ ์ ์๋๋ก ๋ค์ํ ๊ธฐ๋ฅ์ Loader๋ผ๋ ์ด๋ฆ์ผ๋ก ์ ๊ณตํ๊ณ ์๋ค.
npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
// webpack.config.ts
import path = require("path");
import { Configuration } from "webpack";
const config: Configuration = {
entry: "./src/index.tsx",
output: {
path: path.resolve("dist"),
publicPath: "auto",
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"],
},
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: [/node_modules/],
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
},
},
],
},
};
export default config;
- entry๋ ์ง์ ๊ฒฝ๋ก, output์ ๋น๋ ํ์ผ์ ์ด๋๋ก ๋ด๋ณด๋ผ ๊ฒ์ธ์ง๋ฅผ ์ ์ด์ค๋ค. create-react-app๊ณผ ๋์ผํ๊ฒ dist๋ก ์ค์ ํด์คฌ๋ค. publicPath๋ ๊ธฐ๋ณธ page ๊ฒฝ๋ก์ธ๋ฐ "/"๋ก ์ค์ ํด๋ ๋ฌธ์ ๋ ์์์ง๋ง "auto"๋ฅผ ์ ๊ณต ํด์ฃผ๊ธฐ์ auto๋ก ์ค์ ํ๋ค.
- resolve.extensions ์ต์ ์ ์ฐ๋ฆฌ๊ฐ import ํ ๋ ํ์ฅ์๋ฅผ ์ ์ด์ฃผ์ง ์๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ด๋ก ๋ช ์ํด์ฃผ๋ ๊ฒ์ด๋ค. ๊ธฐ๋ณธ๊ฐ์ ['.js', '.json', '.wasm'] ์ด๋ค.
- babel-loader์ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๊ฐ๋จํ๋ค. ํ์ํ babel ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ธ์คํจ ํ ํ module ์ต์ ์ ์ถ๊ฐํด์ฃผ๊ณ ๊ทธ ์์ rules ๋ฅผ ์ ์ฉํด์ค๋ค.
- ๊ทธ๋ฆฌ๊ณ npm run build๋ฅผ ์คํํด๋ณด๋ฉด, ์๋ฌ๊ฐ ํฐ์ง๋ค.
- ์ฌ์ค ๋น์ฐํ ์ด์ ์๋ค. config ํ์ผ์ typescript๋ก ์์ฑํ๊ธฐ๋ ํ๊ณ , ํ์ฌ ์ฝ๋๋ฅผ ๋ณด๋ฉด ESM ๋ฐฉ์์ ์ด์ฉํ์ง๋ง ์ ์ด์ webpack์ CJS ๋ฐฉ์์ผ๋ก ๋ง๋ค์ด์ก๊ธฐ์.. ๋ด๋ถ๋ฅผ ์ฝ์ง๋, .ts ํ์ฅ์๋ฅผ node์์ ๋ฐ์๋ค์ด์ง๋ ๋ชปํ๊ฒ์ด๋ค. ํด๊ฒฐํด๋ณด์!
Webpack ESM, TS ์ ์ฉํ๊ธฐ
npm i -D ts-node
- ์ผ๋จ TS ๋ฌธ๋ฒ์ Node์์ ์ฝ๊ธฐ ์ํด ts-node๋ฅผ ์ค์นํด์ค๋ค.
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"outDir": "dist",
"jsx": "react-jsx"
},
"ts-node": {
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "Node",
"target": "ES5",
"esModuleInterop": true
}
}
}
- tsconifg.json์ ํตํด ts-node์ ์ปดํ์ผ ์ต์ ์ CJS, ๊ทธ๋ฆฌ๊ณ Node๋ก ๋ง๋ค์ด ์ฃผ๊ณ esModuleInterop ์ต์ ์ true๋ก ์ฃผ๊ฒ๋๋ฉด CJSํ์์ ๋ชจ๋์ ES6 ๋ฐฉ์์ผ๋ก ๋ถ๋ฌ์ฌ ์ ์๊ฒ ํด์ค๋ค.
- ๊ทธ๋ฆฌ๊ณ npm run build๋ฅผ ํด๋ณด๋ฉด!!
- Webpack ๋น๋์ ์ฑ๊ณตํ๊ฒ ๋๋ค. ์์ง ๊ฐ๋ฐํ๊ฒฝ๊ณผ ํ๋ก๋์ ์ ํ๊ฒฝ ๋ถ๋ฆฌ์ ๋ค๋ฅธ loader, plugins ๋ฑ๋ฑ ์ค์ ํ ๊ฒ์ด ๋ง์ด ๋จ์์๋ค.
- ๊ธ์ด ๊ธธ์ด์ ธ 2ํธ์ผ๋ก ๋์์ค๊ฒ ๋ค. ํน์ ๊ธํ๊ฒ ํ๊ฒฝ์ ๊ตฌ์ฑํด์ผํ ๋ถ๋ค์ ์ํด Yarn Berry + React + TS + Webpack ์ผ๋ก ๊ตฌ์ฑ๋ ๋ด ๋ณด์ผ๋ฌํ๋ ์ดํธ๋ฅผ ๋จ๊ฒจ๋๋๋ค. (์คํ๋ ๋๋ฌ์ฃผ์๋ฉด ์ข๊ตฌ์..๐)
'React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Tailwind CSS] Tailwind ์๋์์ฑ ์กฐ๊ธ ๋ ํธํ๊ฒ ์ฐ๋ ๋ฐฉ๋ฒ (1) | 2023.11.03 |
---|---|
[React] ์ฌ๊ท ์ปดํฌ๋ํธ (1) | 2023.10.15 |
[React] debounce (feat. lodash) (0) | 2023.01.24 |
[React]useState (0) | 2022.11.16 |
[React]useLocation (0) | 2022.11.02 |