์žฌ๋ฐŒ๊ฒŒ ํ•ฉ์‹œ๋‹ค

๊ธฐ๋กํ•˜๊ธฐ, ๊ฐ€์‹œํ™”ํ•˜๊ธฐ

React

npm, yarn, pnpm์˜ ์ฐจ์ด์ ์„ ๋น„๊ตํ•ด๋ณด์ž

์€๋˜๋”” 2022. 9. 26. 07:35

 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ € npm, yarn, pnpm์˜ ์ฐจ์ด๋ฅผ ์•Œ์•„๋ณด์ž.

 

ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €๋ž€?

 

๐Ÿ’๐Ÿป‍โ™‚๏ธ ํŒจํ‚ค์ง€๋ž€?  npm์— ๋“ฑ๋ก๋œ node ๋ชจ๋“ˆ.

 

์ด๋Ÿฌํ•œ ํŒจํ‚ค์ง€๋“ค์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์šด๋กœ๋“œ, ์„ค์น˜, ์—…๋ฐ์ดํŠธ, ์˜์กด์„ฑ ๊ด€๋ฆฌ, ์ œ๊ฑฐ ๋“ฑ ๋ณต์žกํ•œ ์ƒํ™ฉ๋“ค์ด ๋งŽ์ด ์ƒ๊ธฐ๋Š”๋ฐ ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €๋Š” ์ด๋Ÿฌํ•œ ๊ณผ์ •๋“ค์„ ์ž๋™ํ™”ํ•˜์—ฌ ํŽธ๋ฆฌํ•˜๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.

 

ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €์˜ ๋“ฑ์žฅ ์ด์ „: ํ”„๋กœ๊ทธ๋žจ์˜ dependencies๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋‹ค์šด๋กœ๋“œ ํ•˜๊ณ  ๊ด€๋ฆฌ
๋“ฑ์žฅ ์ดํ›„: ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €๋ฅผ ์‚ฌ์šฉํ•ด dependencies๋ฅผ ๋‹ค์šด๋กœ๋“œ ๋ฐ ๊ด€๋ฆฌ


๋ชจ๋“  ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €์—์„œ ํ†ต์šฉ๋˜๋Š” ๊ฐœ๋…๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • package.json์€ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
  • node_modules ํด๋”์— dependencies๋ฅผ ์„ค์น˜ํ•œ๋‹ค.
  • lock ํŒŒ์ผ์—๋Š” ๊ฐ dependency์˜ ์ •ํ™•ํ•œ ๋ฒ„์ „์ด ๊ธฐ์žฌ๋˜์–ด ์žˆ๋‹ค. lock ํŒŒ์ผ์„ ํ†ตํ•ด ๋ชจ๋“  ํŒ€์›์ด ์ •ํ™•ํžˆ ๋™์ผํ•œ ๋ฒ„์ „์˜ dependency๋ฅผ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋ชจ๋“  ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • metadata์˜ ์ž‘์„ฑ ๋ฐ ๊ด€๋ฆฌ
  • dependencies์˜ ์„ค์น˜, ์—…๋ฐ์ดํŠธ, ์‚ญ์ œ
  • ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰
  • ํŒจํ‚ค์ง€ ํผ๋ธ”๋ฆฌ์‰ฌ
  • ๋ณด์•ˆ ๊ฒ€์‚ฌ

npm - yarn - pnpm ์ˆœ์œผ๋กœ ํผ์ง€๋ง‰ํ•œ ์ฐจ์ด์ ๋“ค์„ ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ž.

npm v.s. yarn

๐Ÿ‘‰ ํŒจํ‚ค์ง€ ์„ค์น˜ ๋ฐฉ์‹์˜ ์ฐจ์ด
npm: ํŒจํ‚ค์ง€๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์„ค์น˜ํ•œ๋‹ค.
yarn: ์—ฌ๋Ÿฌ ํŒจํ‚ค์ง€๋ฅผ ๋™์‹œ์— ๊ฐ€์ ธ์™€ ๋ณ‘๋ ฌ์ ์œผ๋กœ ์„ค์น˜ํ•œ๋‹ค.
→ ์†๋„ ์ธก๋ฉด์—์„œ yarn์ด ๋” ์šฐ์„ธํ•˜๋‹ค. (๋‹ค๋งŒ npm์˜ ์—…๋ฐ์ดํŠธ๋กœ ์ธํ•ด ํ˜„์žฌ๋Š” ๊ทธ ์ฐจ์ด๊ฐ€ ๊ทผ์†Œํ•˜๋‹ค๊ณ  ํ•œ๋‹ค.)

npm, yarn v.s. pnpm

๐Ÿ‘‰ node_modules์˜ structure ์ฐจ์ด

npm, yarn: flat structure
pnpm: flat structure์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•œ symlinked structure

flat structure๋ž€?

ํŒจํ‚ค์ง€ A,B,C๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž. ํŒจํ‚ค์ง€ A,C๋Š” ๋ชจ๋‘ ํŒจํ‚ค์ง€ B์— ์˜์กดํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์„ ๊ฐ€์ •ํ–ˆ์„ ๋•Œ npm@3 ์ด์ „์˜ node_modules ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•˜๋‹ค.

 

ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ์˜ ๋ฌธ์ œ์ ์„ ๊ฐ€์ง„๋‹ค.

  • depth๊ฐ€ ์ง€๋‚˜์น˜๊ฒŒ ๊นŠ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • depth๊ฐ€ ๊นŠ์–ด์ง์— ๋”ฐ๋ผ directory path ๋˜ํ•œ ๊ธธ์–ด์ง„๋‹ค.
  • ๋™์ผํ•œ ํŒจํ‚ค์ง€์— ๋Œ€ํ•œ ์ค‘๋ณต๋œ ํŒŒ์ผ๋“ค์ด ์ƒ์„ฑ๋œ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด npm์€ flat structure๋ฅผ ๋„์ž…ํ–ˆ๋‹ค. yarn ๋˜ํ•œ flat structure๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. flat structure๋Š” ์•„๋ž˜ ์ด๋ฏธ์ง€์ฒ˜๋Ÿผ ์ƒ๊ฒผ๋‹ค. 

flat structure

flat ํ•˜๋‹ค๋Š” ๋ง์ด ์ด์ œ ์ดํ•ด๊ฐ€ ๋˜๋Š”๊ฐ€? ๋ณด๋ฉด ๋ชจ๋“  ํŒจํ‚ค์ง€์˜ depth๊ฐ€ ๋™์ผํ•˜๋‹ค. ํŒจํ‚ค์ง€ A,C์˜ ํ•˜์œ„์— ์žˆ๋˜ B๊ฐ€ top์œผ๋กœ ํ˜ธ์ด์ŠคํŒ… ๋˜์—ˆ์œผ๋ฏ€๋กœ, ์ด๋ฅผ ํŒจํ‚ค์ง€ ํ˜ธ์ด์ŠคํŒ… ๋ฐฉ์‹์ด๋ผ๊ณ ๋„ ๋ถ€๋ฅธ๋‹ค. ํ•˜์ง€๋งŒ ๋งŒ์•ฝ ํŒจํ‚ค์ง€ A,C๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฒ„์ „์˜ ํŒจํ‚ค์ง€ B๋ฅผ ํ•„์š”๋กœ ํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ํŒจํ‚ค์ง€ A-C ์ˆœ์œผ๋กœ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๊ฐ€ ๋œ๋‹ค. 

a/
b/ # v1.0.0
c/
โ””โ”€โ”€ node_modules/
	โ””โ”€โ”€ b/  # v2.0.0

ํŒจํ‚ค์ง€ A ์„ค์น˜ ์‹œ B๋ฅผ ํ˜ธ์ด์ŠคํŒ… ํ•ด top์— ์„ค์น˜ํ•œ๋‹ค. C ์„ค์น˜ ์‹œ top์— ์ด๋ฏธ v1.0.0์˜ B๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ C ํ•˜์œ„์— v.2.0.0์˜ B๋ฅผ ์„ค์น˜ํ•œ๋‹ค. ์ฆ‰ ํŒจํ‚ค์ง€์˜ ์„ค์น˜ ์ˆœ์„œ์— ๋”ฐ๋ผ node_modules์˜ ๊ตฌ์กฐ๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค. 

flat structure์˜ ๋ฌธ์ œ์ 

  • ghost dependency 
    = modules can access packages they don't depend on ๋ชจ๋“  ํŒจํ‚ค์ง€๊ฐ€ ํ˜ธ์ด์ŠคํŒ… ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ํŒจํ‚ค์ง€์˜ dependency์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.
  • ํ•œ ํŒจํ‚ค์ง€์˜ ์—ฌ๋Ÿฌ ๋ฒ„์ „์ด ํ•„์š”ํ•  ๊ฒฝ์šฐ ๋™์ผํ•œ ํŒจํ‚ค์ง€์˜ ํŒŒ์ผ์ด ์—ฌ๋Ÿฌ ๊ณณ์— ๋ณต์‚ฌ๋˜์–ด์•ผ ํ•œ๋‹ค.

pnpm์˜ symlinked structure

์œ„์—์„œ ๊ธฐ์ˆ ํ•œ flat structure์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๊ณ ์ž, pnpm์€ symlinked structure๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

pnpm์˜ node_modules ํด๋”๋Š” nested ํ˜•ํƒœ์ด๋‹ค.(=flat ํ•˜์ง€ ์•Š๋‹ค) ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์œ„์—์„œ ์ด๋ฏธ nested node_modules์˜ ๋ฌธ์ œ์ ์— ๋Œ€ํ•ด ์‚ดํŽด๋ดค์—ˆ๋‹ค. pnpm์€ ์–ด๋–ป๊ฒŒ nested๊ณผ flat์˜ ๋ฌธ์ œ์ ์„ ๋™์‹œ์— ํ•ด๊ฒฐํ–ˆ์„๊นŒ?

 

์šฐ์„  ๋ชจ~๋“  ํŒจํ‚ค์ง€๋“ค์€ .pnpm-store ํด๋”์— ์ €์žฅ๋œ๋‹ค. ํ•„์š”ํ•œ ๋ชจ๋“  ํŒจํ‚ค์ง€์˜ ๋ชจ๋“  ๋ฒ„์ „์ด ํ•ด๋‹น ํด๋”์— ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์ €์žฅ๋˜๊ณ , node_modules์—์„œ๋Š” ํ•ด๋‹น ํด๋”์— ๋Œ€ํ•œ hard link์™€ symbolic link๋ฅผ ํ†ตํ•ด ํŒจํ‚ค์ง€์— ์ ‘๊ทผํ•œ๋‹ค. ๊ฐ ํŒจํ‚ค์ง€๊ฐ€ ํ•œ ๋ฒˆ๋งŒ ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— single source of truth๋ฅผ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋””์Šคํฌ ๊ณต๊ฐ„์„ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ๋‹ค. link๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋™์ผํ•œ ํŒจํ‚ค์ง€๊ฐ€ ์—ฌ๋Ÿฌ ๊ณณ์— ๋ณต์‚ฌ๋  ์ผ์ด ์—†๋‹ค. ๋˜ ๊ตฌ์กฐ์ ์œผ๋กœ nestedํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ํŒจํ‚ค์ง€์˜ ์˜์กด ๊ด€๊ณ„๋ฅผ ๋ช…ํ™•ํžˆ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ghost dependency ๋ฌธ์ œ ๋˜ํ•œ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

 ์ฐธ๊ณ ๋กœ pnpm์€ npm์˜ drop-in replacement๋กœ์„œ npm๋งŒ ์žˆ๋‹ค๋ฉด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

* drop-in replacement: ์„ค์ •์„ ๋ฐ”๊ฟ€ ํ•„์š” ์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ, ์†๋„์™€ ์•ˆ์ •์„ฑ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ ํ–ฅ์ƒ์ด ์ด๋ค„์ง€๋Š” ๋Œ€์ฒดํ’ˆ

 

์ฐธ๊ณ  ๋งํฌ

Switch from NPM to pnpm

https://blog.outsider.ne.kr/1230

https://medium.com/pnpm/why-should-we-use-pnpm-75ca4bfe7d93