npm&dependency.md
๐กNPM
npm (ํจํค์ง ๋งค๋์ ) ์ ์ฌ์ฉํ๋ ์ด์
๐ ํจํค์ง ๋งค๋์ ๋ฅผ ์ฌ์ฉํ์ง ์์์ ๋
- ๋๊ท๋ชจ ํ๋ก์ ํธ์์ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ก๋๋ฅผ ๊ด๋ฆฌํ ์ ์์
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ๋ฒ์ ์ด ๋์์ ๋, ํ์ผ์ ์ ๋ฐ์ดํธํด์ผํจ
- ์ด์ ์๋ ๋ชจ๋ ํจํค์ง๋ฅผ ํฌํจํ ๋จ์ผ ์ ์ฅ์๊ฐ ์์์
์ฆ, ๋ ๋์ ๋ฐฉ์์ผ๋ก ์์กด์ฑ์ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ชจ๋ ๊ฐ๋ฐ ๋ฐฉ์์
๋๋ค.
global๋ก ํจํค์ง๋ฅผ ์ค์นํ๋ ์ด์
- ๊ธ๋ก๋ฒ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์์
๋๋ค.
- ex) live server, nodemon, parcel
- ํ์ง๋ง ํจํค์ง๋ฅผ ๊ธ๋ก๋ฒ๋ก ์ค์นํ๋ฉด ํญ์ ์ต์ ๋ฒ์ ์ ์ ์งํ๊ธฐ ์ด๋ ต์ต๋๋ค.
์ค์นํ๋ ํจํค์ง์ ๋ฒ์ ์ ์ต์ ์ผ๋ก ์ ์งํ๊ธฐ ์ํด, global ์ค์น๋ฅผ ์ง์ํ ์ด์ ๊ฐ ์์ต๋๋ค.
dev dependency๋?
npm i parcel --save-dev
- devDependency๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋น๋ํ๊ธฐ ์ํ ๋๊ตฌ์
๋๋ค.
๊ฐ๋ฐ์ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ devDependency๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
- dependency์ ๊ฐ์ด ์ฝ๋์ ํฌํจ๋๋ ์์กด์ฑ์ด ์๋๋๋ค.
๐ค **regular dependency์ dev dependency์ ์ฐจ์ด์ ์?**
์ํํธ์จ์ด ๊ฐ๋ฐ์์, ์์กด์ฑ์ ์ฝ๋ ์๋์ ํ์ํ ํจํค์ง๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
npm ํน์ yarn ๊ฐ์ ํจํค์ง ๊ด๋ฆฌ์๋ฅผ ์ฌ์ฉํ ๋๋ package.json ํ์ผ์ ์ด๋ฌํ ์์กด์ฑ์ ์ง์ ํ ์ ์์ต๋๋ค.
์ข
์์ฑ(dependency)์ ์ฝ๋๊ฐ **์ด์ ํ๊ฒฝ**์์ ์คํ๋ ๋ ํ์ํ ํจํค์ง์
๋๋ค.
์ด๋ค์ ์ฌ์ฉ์๊ฐ ์์ฉ ํ๋ก๊ทธ๋จ์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํ์ํ ๊ฒ๋ค์
๋๋ค.
์ด์ ์ข
์์ฑ(production dependency)๋ง์ ์ค์นํ๊ธฐ ์ํด npm i ~ โproduction ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ฐ๋ฐ ์ข
์์ฑ(dev dependencies)์ **๊ฐ๋ฐ ์ค์๋ง ํ์**ํ ํจํค์ง์
๋๋ค.
์ด๋ฌํ ๊ฒ๋ค์ ํ
์คํธ ํ๋ ์์ํฌ, ๋น๋ ๋๊ตฌ, ๋ฆฐํฐ ๋ฑ์ด ํฌํจ๋ ์ ์์ต๋๋ค.
์ด์ ํ๊ฒฝ์์ ์์ฉ ํ๋ก๊ทธ๋จ์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์คํํ ๋ ํ์ํ์ง ์์ผ๋ฏ๋ก, ์ฝ๋๋ฅผ ๋ฐฐํฌํ ๋๋ ํฌํจ๋์ง ์์ต๋๋ค.
leaflet : ์ธ๊ตญ map api
an open-source JavaScript library for mobile-friendly interactive maps
lodash : javaScript๋ฅผ ๋ ํธํ๊ฒ ์ฐ๊ธฐ
- ์ข
๋ฅ
- ๊ทธ๋ฅ lodash โ use common JS
- lodash-es โ es6
- cloneDeep ๋ฉ์๋
-
์ค์ฒฉ ๊ฐ์ฒด nested obejct์ ๊น์ ๋ณต์ฌ deep copy / deep clone์ ์๋์ผ๋ก ๊ตฌํํ๋ ๊ฒ์ ๋ณต์กํฉ๋๋ค.,
- json์ผ๋ก ๋ณํ ํ object๋ก ์ฌ๋ณํ โ ๋๋ฆฐ ์๋, ํจ์์ ์ ์ฉํ ์ x
- Lodash๋ฅผ ์ฌ์ฉ โ ์์กด์ฑ
- ์ฌ๊ท ํจ์๋ฅผ ์ฌ์ฉ โ ์ฐธ์กฐํ ๊ฐ์ฒด๋ฅผ ๋ถ๋ฆฌํด๊ฐ๋ฉฐ ๊น์ ๋ณต์ฌ
-
cloneDeep()์ ์ฌ์ฉํ์ฌ ๊น์ ๋ณต์ฌ๋ฅผ ์งํํ ์ ์์ต๋๋ค.
// ์ค์ฒฉ ๊ฐ์ฒด๋ฅผ ๊น์ ๋ณต์ฌ import { cloneDeep } from "lodash-es"; const state = { cart: [ { product: "๋ถ๋์ฐ๊ฐ", quantity: 1 }, { product: "๊ฝ์น์ฐ๊ฐ", quantity: 1 }, { product: "๊น์น์ฐ๊ฐ", quantity: 1 }, ], user: { loggedIn: true }, }; const objectClone = Object.assign({}, state); // ์์ ๋ณต์ฌ const objectDeepClone = cloneDeep(state); // lodash์ ๊น์ ๋ณต์ฌ ๊ธฐ๋ฅ state.user.loggedIn = false; console.log(objectClone); // loggedIn์ false์ ๋๋ค. console.log(objectDeepClone); // loggedIn์ true์ ๋๋ค.
-
Parcel
- ์ค์ ์์ด ์ฌ์ฉํ ์ ์๋ ๋ชจ๋ ๊ฐ๋ฐ ๋น๋ ๋๊ตฌ์ ๋๋ค.
parcel vs webpack
Parcel๊ณผ Webpack์ ๋ ๋ค JavaScript ๋ฒ๋ค๋ฌ์ ๋๋ค. ์ด๋ค์ JavaScript ์ฝ๋์ ๊ธฐํ ์์ฐ(์ด๋ฏธ์ง ๋๋ CSS ํ์ผ ๊ฐ์)์ ํ๋์ ํ์ผ(๋๋ ์ฌ๋ฌ ํ์ผ)๋ก ๊ฒฐํฉํ์ฌ ์น ๋ธ๋ผ์ฐ์ ๊ฐ ๋ก๋ํ ์ ์๊ฒ ํฉ๋๋ค.
๋ ๊ฐ์ง ์ฌ์ด์ ์ฃผ์ ์ฐจ์ด์ ์ Parcel์ ์ค์ ํ์ผ ์์ด ์๋ํ๋ ๋ฒ๋ค๋ฌ์ด๋ฉฐ, ์ฝ๋๋ฅผ ์ด๋ป๊ฒ ๋ฒ๋ค๋ง ํ ์ง๋ฅผ ์ง์ ํ๋ webpack.config.js์ ๊ฐ์ ์ค์ ํ์ผ์ ๋ง๋ค ํ์๊ฐ ์๋ค๋ ์ ์ ๋๋ค. ๋์ ๊ท์น๊ณผ ํ์๋ฆญ(heuristics)์ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ์๋์ผ๋ก ๋ฒ๋ค๋ง ํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ฐพ์๋ ๋๋ค.
Webpack์ ๋ฐ๋ฉด์ ์ค์ ํ์ผ์ด ํ์ํ๋ฉฐ, ์ฝ๋๋ฅผ ๋ฒ๋ค๋ง ํ ๋ ๋ ์ธ๋ถํ๋ ์ ์ด๋ฅผ ํ ์ ์์ต๋๋ค. ์ด๋ Parcel๋ณด๋ค ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ์ง๋ง, ์ค์ ํ๊ณ ์ค์ ํ๋ ๊ฒ์ด ๋ ๋ณต์กํ๋ฉฐ ํ์ต ๊ณก์ ์ด ๋์์ง ์ ์์ต๋๋ค.
๋ค๋ฅธ ์ฐจ์ด์ ์ผ๋ก๋ webpack์ด ๋ ์ธ๊ธฐ์๊ณ ์ฌ์ฉ๋์ด ๋ ๋ง๊ธฐ ๋๋ฌธ์, ๋ ๋ง์ ์ปค๋ฎค๋ํฐ ์ํฌํธ์ ์๋ํํฐ ํ๋ฌ๊ทธ์ธ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
parcel ์คํํ๊ธฐ
npx parcel index.html
- npx : npm์ ๋ด์ฅ๋ ์์ฉ ํ๋ก๊ทธ๋จ
- parcel์ ์ต์
: entry point
- /dist
-
parcel ๋น๋ โ dist์ ์์น
-
index.html
<script src="/index.8cfc62b9.js" defer=""></script>
-
npx parcel index.html vs โstartโ: โparcel index.htmlโ
โ **why "npx parcel index.html" is became "start": "parcel index.html" in package.json script?
โ why there is no npx prefix?**
---
"npx parcel index.html"๊ณผ "start": "parcel index.html"๋ ๊ด๋ จ๋์ง๋ง ์๋ก ๋ค๋ฅธ ๋ชฉ์ ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
"npx parcel index.html"๋ฅผ command line์์ ์คํํ๋ฉด **npx ํจํค์ง ๋ฌ๋๋ฅผ ์ฌ์ฉํ์ฌ
parcel ๋ช
๋ น์ ์คํํ๊ณ ๊ฐ๋ฐ ์๋ฒ๋ฅผ ์์**ํฉ๋๋ค. ์ด๋ npx ํจํค์ง ๋ฌ๋๋ฅผ ์ฌ์ฉํ์ฌ
**์ค์นํ ๋ก์ปฌ ๋ฒ์ ์ parcel์ ์ฌ์ฉ**ํ๋๋ก ํฉ๋๋ค.
๋ฐ๋ฉด์ package.json์ script ์น์
์ ์๋ "start": "parcel index.html"๋ npm script ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ
์คํํ ์ ์๋ ๋ช
๋ น์ ์ ์ํ๋๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. "npm start" ๋๋ "yarn start"๋ฅผ ์คํํ๋ฉด
start ์คํฌ๋ฆฝํธ์ ์ ํ ๋ช
๋ น์ธ "parcel index.html"์ด ์คํ๋ฉ๋๋ค. ์ด ๋ช
๋ น์ **๊ฐ๋ฐ ์๋ฒ๋ฅผ ์์**ํ์ง๋ง
**npx ํจํค์ง ๋ฌ๋๋ฅผ ์ฌ์ฉํ์ง ์๊ณ , ํ๋ก์ ํธ์ ์ค์น๋ ๋ก์ปฌ ๋ฒ์ ์ parcel ๋ช
๋ น**์ ์ฌ์ฉํฉ๋๋ค.
package.json ์คํฌ๋ฆฝํธ์์ **npx ์ ๋์ฌ๊ฐ ํ์ํ์ง ์์ ์ด์ **๋ ์คํฌ๋ฆฝํธ๊ฐ ํ๋ก์ ํธ์
**๋ก์ปฌ node_modules ์ปจํ
์คํธ ๋ด์์ ๋ช
๋ น์ ์คํ**ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
์ด๊ณณ์๋ **๋ก์ปฌ๋ก ์ค์น๋ parcel ํจํค์ง**๊ฐ ์์นํด ์๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ทธ๋ฌ๋ ๋ช
๋ น์ ๋ช
๋ น ํ์์ ์ง์ ์คํํ ๋๋ npx ์ ๋์ฌ๊ฐ ํ์ํ๋ฉฐ
์ด๋ฅผ ํตํด ์ ํํ ๋ฒ์ ์ parcel์ ์ฌ์ฉํ ์ ์๋๋ก ํฉ๋๋ค.
| ์คํํ๋ ๊ณณ | ๋ช ๋ น์ด | ์คํํ๋ ํจํค์ง์ ์์น | | --- | --- | --- | | command line | npx parcel index.html | npx ํจํค์ง ๋ฌ๋์์, ์ค์นํ ๋ก์ปฌ ๋ฒ์ ์ parcel ์คํ | | script | โstartโ : โparcel index.htmlโ | ๋ก์ปฌ node_module ์ปจํ ์คํธ ๋ด, ๋ก์ปฌ๋ก ์ค์น๋ parcel ํจํค์ง |
build
- compress build โ
/dist
๋ด
"build": "parcel build index.html"
๐ซ parcel build ์๋ฌ : main entry ์ ๋ํด์!
- ํ์ฌ parcel ๋ฒ์
"parcel": "^2.8.3โ
์์ ์์ ์ ๊ฐ์ด ๋น๋ ์, ๋ค์๊ณผ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
- โmainโ ํ๋๊ฐ โscript.jsโ์ธ๋ฐ ๋ฐํด, ์ปดํ์ผ๋ ๋ฒ๋ค์ ํ์
์ โhtmlโ์ด๋ฏ๋ก, ํ์
์ด ๋งค์น๋์ง ์์ ์๊ธฐ๋ ์๋ฌ์
๋๋ค.
-
ํฐ๋ฏธ๋์ ์๋ด์ ๋ฐ๋ผ โscript.htmlโ์ผ๋ก ๋ฐ๊พธ๊ฑฐ๋ ( main์ html๋ก ) ๋๋ script์ build๋ฅผ js๋ก ๋ฐ๊พธ๋ ค๊ณ ํ์ ๋๋ ๋ ๋ค๋ฅธ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
-
๊ด๋ จ ๋ฌธ์: https://parceljs.org/features/targets/#library-targets
-
- main ํ๋๋ฅผ ์ง์ฐ๋ฉด ์๋ฌ๊ฐ ํด๊ฒฐ๋ฉ๋๋ค. (๊ฐ์ ์ง์ฐ๋ ๊ฒ์ด ์๋๋ผ, ํ๋ ์์ฒด๋ฅผ ์ญ์ ํฉ๋๋ค.)
main field is not mandatory for every package,
if you don't want to set the main field in your package.json file,
you can remove it.
hot module replacement
- ์ ์ฒด ํ์ด์ง๊ฐ ์๋ก๊ณ ์นจ ๋์ง ์์
- ํ์ด์ง๋ฅผ ๋ก๋ํด๋, ๋ฐ์ดํฐ ์ ์ง
if (module.hot) {
module.hot.accept();
}
- ์คํ
- ์๋ก ๊ณ ์นจ ๋์ง ์์ผ๋ฏ๋ก ๋ฒํผ append + ๋ฒํผ์ ์ฆ๊ฐ๊ฐ ๋ค๋ฆ
- ์ ์ฅ ํ ๋๋ง๋ค ๊ณ์ append
let num = 0;
let acc = 5; // 1์์ 5๋ก ๋ณ๊ฒฝ
const button = document.createElement("button");
button.innerHTML = `${acc} ๋ํ๊ธฐ ๋ฒํผ: ๊ฐ ${num}`;
const newNum = () => {
num += acc;
button.innerHTML = `${acc} ๋ํ๊ธฐ ๋ฒํผ: ๊ฐ ${num}`;
};
button.removeEventListener("click", newNum);
button.addEventListener("click", newNum);
document.querySelector(".button-box").append(button);
if (module.hot) {
module.hot.accept();
}