๐ฌ node_modules ๊ตฌ์กฐ ์์ ํด๋ถ โ .pnpm ํด๋์ ๋น๋ฐ
๐ ๊ฐ์
pnpm ์ ์ฌ๋งํฌ ๊ธฐ๋ฐ node_modules ๊ฐ ์ด๋ป๊ฒ ๋์ํ๋์ง, ํฌํ ์์กด์ฑ์ ์ด๋ป๊ฒ ๋ง๋์ง, nodeLinker ์ต์ ์ผ๋ก ์ด๋ป๊ฒ ์กฐ์ ํ๋์ง ์์ ์ ๋ณต
02. node_modules ๊ตฌ์กฐ ํด๋ถ
๐ ๋ชฉ์ฐจ
- ๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
- ๐ค ์ ์์์ผ ํ๋๊ฐ
- ๐ฌ .pnpm ํด๋ ํด๋ถ
- ๐ ํผ์ด ์์กด์ฑ๊ณผ ์ฌ๋งํฌ์ ๊ด๊ณ
- ๐ ํธ์ด์คํ ์ ์ด
- ๐๏ธ nodeLinker ์ค์
- ๐ ๏ธ ์ค์ ํธ๋ฌ๋ธ์ํ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: ์ฝ 25๋ถ(์ ์ฒด) / ํต์ฌ ํํธ๋ง: 12๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ํ๋ฆ
[.pnpm ํด๋ ๊ตฌ์กฐ] โ [ํผ์ด ์์กด์ฑ ์ฒ๋ฆฌ] โ [ํธ์ด์คํ ์ ์ด] โ [nodeLinker ์ต์ ] โ [์๋ฌ ํด๊ฒฐ]
๐ฏ ์ด ๋ฌธ์๋ฅผ ๋ค ์ฝ์ผ๋ฉด ํ ์ ์๋ ๊ฒ
-
.pnpmํด๋ ๋ด๋ถ ๊ตฌ์กฐ๋ฅผ ์ง์ ํ์ํ๊ณ ํด์ํ ์ ์๋ค - ํผ์ด ์์กด์ฑ ๋ฒ์ ์ด ๋ค๋ฅผ ๋ pnpm ์ด ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋์ง ์ค๋ช ํ ์ ์๋ค
-
public-hoist-pattern์ผ๋ก ํน์ ํจํค์ง๋ฅผ ์ ํ์ ์ผ๋ก ํธ์ด์คํ ํ ์ ์๋ค -
nodeLinker์ต์ ์ ์ฐจ์ด๋ฅผ ์๊ณ ์ํฉ์ ๋ง๊ฒ ์ ํํ ์ ์๋ค
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'

- ๐ฃ ์์ฒ ( ์ ์
): "์ํธ ๋, pnpm ์ผ๋ก ๋ฐ๊ฟจ๋๋ฐ ESLint๊ฐ ๊ฐ์๊ธฐ ์ ๋์.
Cannot find module 'eslint'๋ผ๊ณ ๋์ค๋๋ฐ ๋ถ๋ช ํdevDependencies์ ์๊ฑฐ๋ ์. ๊ทธ๋ฆฌ๊ณnode_modulesํด๋ ๋ค์ด๊ฐ๋ดค๋๋ฐeslintํด๋๊ฐ ์๊ณ.pnpm์ด๋ผ๋ ์จ๊น ํด๋๋ง ์์ด์ ๋ญ๊ฐ ์ค์น๊ฐ ์๋ชป๋ ๊ฒ ๊ฐ์์.pnpm install๋ค์ ํด๋ดค๋๋ฐ๋ ๋๊ฐ๊ณ ..." - ๐ฆ ์ํธ ( ๋ฆฌ๋ ): "์์ฒ ๋,
.pnpmํด๋ ์์ ์ด์ด๋ดค์ด์?eslint๊ฐ ๊ฑฐ๊ธฐ ์์ ๊ฑฐ์์. pnpm ์ ๋ฃจํธnode_modules์๋package.json์ ์ง์ ์ ํ ํจํค์ง๋ง ์ฌ๋งํฌ๋ก ๋ ธ์ถํ๊ฑฐ๋ ์. ESLint ๊ฐ ์๋ค๋ ์๋ฌ๋ ์ญ์คํ๊ตฌ ESLint ํ๋ฌ๊ทธ์ธ์ด ๋ฃจํธnode_modules์์eslint๋ฅผ ์ฐพ์ผ๋ ค๊ณ ํ๋๋ฐ ๋ชป ์ฐพ๋ ์ผ์ด์ค์์..npmrc์public-hoist-pattern[]=*eslint*ํ ์ค ์ถ๊ฐํ๋ฉด ํด๊ฒฐ๋ผ์."
๐ค ์ ์์์ผ ํ๋๊ฐ
pnpm ์ ์ฒ์ ๋์ ํ๋ ํ์ 90% ๊ฐ ๋น์ทํ ๊ฒฝํ์ ํ๋ค.
"์ ๋๋ eslint, jest, tailwind ์ค์ ์ด pnpm ์ผ๋ก ๋ฐ๊พธ๊ณ ๋์ ๊ฐ์๊ธฐ ์ ๋๋ค."
์ด๊ฒ์ pnpm ์ ๋ฒ๊ทธ๊ฐ ์๋๋ค. pnpm ์ ์ฒ ํ์ด npm ๊ณผ ๊ทผ๋ณธ์ ์ผ๋ก ๋ค๋ฅด๊ธฐ ๋๋ฌธ ์ ๋ฐ์ํ๋ ์์ฐ์ค๋ฌ์ด ๋ง์ฐฐ์ด๋ค. .pnpm ํด๋์ ๊ตฌ์กฐ๋ฅผ ์ดํดํ๋ฉด ์ด๋ฐ ์๋ฌ๊ฐ ์ ๋ฐ์ํ๋์ง, ์ด๋ป๊ฒ ํด๊ฒฐํด์ผ ํ๋์ง๋ฅผ ๋ช
ํํ๊ฒ ์ ์ ์๋ค.
๐ฌ .pnpm ํด๋ ํด๋ถ
์ค์ ๊ตฌ์กฐ ํ์
์์๋ค ์ปค๋ฎค๋ํฐ ํ๋ก์ ํธ์์ ls node_modules/.pnpm ์ ์คํํ๋ฉด:
node_modules/
โโโ .modules.yaml โ pnpm ๋ฉํ๋ฐ์ดํฐ (๋ฒ์ , ์ค์ ๋ฑ)
โโโ next โ .pnpm/next@14.2.0/node_modules/next (์ฌ๋งํฌ)
โโโ react โ .pnpm/react@18.2.0/node_modules/react (์ฌ๋งํฌ)
โโโ typescript โ .pnpm/typescript@5.3.3/node_modules/typescript (์ฌ๋งํฌ)
โโโ .pnpm/
โโโ next@14.2.0/
โ โโโ node_modules/
โ โโโ next/ โ ํ๋๋งํฌ โ ๊ธ๋ก๋ฒ ์คํ ์ด
โ โโโ react/ โ ์ฌ๋งํฌ โ .pnpm/react@18.2.0/... (next์ ํผ์ด)
โ โโโ postcss/ โ ํ๋๋งํฌ โ ๊ธ๋ก๋ฒ ์คํ ์ด (next์ deps)
โโโ react@18.2.0/
โ โโโ node_modules/
โ โโโ react/ โ ํ๋๋งํฌ โ ๊ธ๋ก๋ฒ ์คํ ์ด
โ โโโ loose-envify/ โ ํ๋๋งํฌ โ ๊ธ๋ก๋ฒ ์คํ ์ด (react์ deps)
โโโ typescript@5.3.3/
โโโ node_modules/
โโโ typescript/ โ ํ๋๋งํฌ โ ๊ธ๋ก๋ฒ ์คํ ์ด
๋ค์ด๋ฐ ๊ท์น: ํจํค์ง๋ช @๋ฒ์
.pnpm ๋ด๋ถ์ ํด๋๋ช
์ ํจํค์ง๋ช
@๋ฒ์ ํ์์ด๋ค. ํผ์ด ์์กด์ฑ์ ๋ฒ์ ์ด ๋ฌ๋ผ์ง๋ฉด ํด๋๋ช
๋ ๋ฌ๋ผ์ง๋ค(์๋์์ ์์ธํ ๋ค๋ฃธ).
.modules.yaml โ pnpm ์ ๋ฉํ ์ ๋ณด
# node_modules/.modules.yaml
# ๐ก pnpm์ด node_modules ํด๋ ์ ์ฒด๋ฅผ ๊ด๋ฆฌํ ๋ ์ฐธ๊ณ ํ๋ "๋ด๋ถ ์ฅ๋ถ" ๊ฐ์ ํ์ผ์
๋๋ค.
hoistedDependencies:
/eslint@8.57.0:
eslint: public # ๋ฃจํธ ํด๋๋ก ๋์ด์ฌ๋ ค์ง(hoisting) ํจํค์ง ๋ชฉ๋ก์ ๋ณด์ฌ์ค๋๋ค.
layoutVersion: 5
packageManager: pnpm@9.15.0
pendingBuilds: []
publicHoistPattern:
# .npmrc์์ ์ค์ ํ ํธ์ด์คํ
๊ท์น์ด ์ด ์ฅ๋ถ์ ๊ทธ๋๋ก ๋ฐ์๋์ด ๋์ํฉ๋๋ค.
- '*types*'
- '*eslint*'
prunedAt: 2026-03-05 # ๋ง์ง๋ง์ผ๋ก ๋ถํ์ํ ํจํค์ง(์ฐ๋ ๊ธฐ)๋ฅผ ์ฒญ์ํ ๋ ์ง
registries:
default: https://registry.npmjs.org/
storeDir: /home/user/.pnpm-store/v3 # ๋ด ์ปดํจํฐ ์์ ์ง์ง ์๋ณธ ํ์ผ๋ค์ด ์จ์ด์๋ ๊ธ๋ก๋ฒ ์ ์ฅ์ ์์น
virtualStoreDir: .pnpm # ์ฌ๋งํฌ์ ํ๋๋งํฌ์ ๋ง๋ฒ์ด ์ผ์ด๋๋ ๊ฐ์ ์ ์ฅ์ ์ด๋ฆ๐ ํผ์ด ์์กด์ฑ๊ณผ ์ฌ๋งํฌ์ ๊ด๊ณ
ํผ์ด ์์กด์ฑ์ด ๋ค๋ฅธ ๋ฒ์ ์ผ๋ก ์ค์น๋ ๋
ํผ์ด ์์กด์ฑ(peerDependencies)์ ํจํค์ง๊ฐ "ํธ์คํธ ํ๋ก์ ํธ์์ ์ ๊ณตํด์ผ ํ๋ค"๊ณ ์ ์ธํ๋ ์์กด์ฑ์ด๋ค. ์๋ฅผ ๋ค์ด react-query ๋ react@>=18 ์ ํผ์ด๋ก ์๊ตฌํ๋ค.
๋ง์ฝ ๋ชจ๋ ธ๋ ํฌ์์ ํจํค์ง A ๋ react@17, ํจํค์ง B ๋ react@18 ์ ํผ์ด๋ก ์ฌ์ฉํ๋ ํ๋ฌ๊ทธ์ธ์ด ์๋ค๋ฉด, pnpm ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ๊น?
node_modules/.pnpm/
โโโ some-plugin@1.0.0_react@17.0.2/ โ react@17 ๊ณผ ํจ๊ป ํด๊ฒฐ๋ ๋ฒ์
โ โโโ node_modules/
โ โโโ some-plugin/
โ โโโ react/ โ .pnpm/react@17.0.2/...
โโโ some-plugin@1.0.0_react@18.2.0/ โ react@18 ๊ณผ ํจ๊ป ํด๊ฒฐ๋ ๋ฒ์
โโโ node_modules/
โโโ some-plugin/
โโโ react/ โ .pnpm/react@18.2.0/...
ํด๋๋ช
์ด ํจํค์ง๋ช
@๋ฒ์ _ํผ์ดํจํค์ง@ํผ์ด๋ฒ์ ํ์์ผ๋ก ๋ถ๊ธฐ๋๋ค. ํผ์ด๊ฐ ๋ค๋ฅด๋ฉด ์ฌ์ค์ ๋ค๋ฅธ ์ค์น ์ปจํ
์คํธ์ด๋ฏ๋ก, pnpm ์ด ์ด๋ฅผ ๋ณ๋ ํด๋๋ก ๊ฒฉ๋ฆฌํ๋ค.
npm ์ ์ด ๋ฌธ์ ๋ฅผ "๊ทธ๋ฅ ๋ ๋ค ํธ์ด์คํ " ํ๊ฑฐ๋ ํ๋๋ฅผ ํํด์ ์ฒ๋ฆฌํ๋๋ฐ, pnpm ์ ๋ช ํํ๊ฒ ๋ถ๋ฆฌ ํ๋ค.
autoInstallPeers ์ค์
# .npmrc ๋๋ pnpm-workspace.yaml
# ํผ์ด ์์กด์ฑ์ ์๋์ผ๋ก ์ค์นํ ์ง ์ฌ๋ถ (pnpm ๊ธฐ๋ณธ๊ฐ: true)
auto-install-peers=true๐ ํธ์ด์คํ ์ ์ด โ public-hoist-pattern
์ ํธ์ด์คํ ์ด ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋๊ฐ
pnpm ์ ์๊ฒฉํ ๊ฒฉ๋ฆฌ๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ข์ง๋ง, ์ผ๋ถ ๋๊ตฌ๋ ๋ฃจํธ node_modules ์์ ํน์ ํจํค์ง๋ฅผ ์ฐพ๊ธฐ ๋๋ฌธ์ ์ฌ๋งํฌ ๊ตฌ์กฐ์์ ์๋ฌ๊ฐ ๋๋ค.
๋ํ์ ์ธ ์:
โ ์๋ฌ ์ผ์ด์ค๋ค:
- ESLint ํ๋ฌ๊ทธ์ธ์ด ๋ฃจํธ node_modules ์์ eslint ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ฐพ์ ๋
- TypeScript ๊ฐ @types/* ๋ฅผ ๋ฃจํธ์์ ์ฐพ์ ๋
- Prettier ํ๋ฌ๊ทธ์ธ์ด ๋ฃจํธ prettier ๋ฅผ ์ฐพ์ ๋
- ์ผ๋ถ Jest ์ค์ ์ด ๋ฃจํธ jest-* ๋ฅผ ์ฐพ์ ๋
public-hoist-pattern ์ค์
.npmrc ์์ ํจํด ๋งค์นญ์ผ๋ก ํน์ ํจํค์ง๋ง ์ ํ์ ์ผ๋ก ๋ฃจํธ์ ํธ์ด์คํ
ํ ์ ์๋ค.
# .npmrc (์์๋ค ์ปค๋ฎค๋ํฐ ๊ถ์ฅ ์ค์ / ํ๋ก์ ํธ ๋ฃจํธ)
# ๐ฆ pnpm์ ๊ธฐ๋ณธ ์์น์ "package.json์ ์๋ ์ ๋ค์ ์จ๊ธด๋ค" ์ง๋ง, ์์ธ๋ฅผ ํ์ฉํด ์ค๋๋ค.
# TypeScript๊ฐ ์ฝ๋๋ฅผ ์์ฑํ ๋ ์๋์์ฑ(intellisense)์ ํด์ฃผ๋ ค๋ฉด ํ์
์ ์ ํ์ผ๋ค์ด ํ์ํ๋ฐ, ์๋ค๋ ์์ธ๋ก ๋ฃจํธ์ ๋ก๋๋ค.
public-hoist-pattern[]=*types*
# ESLint ์ญ์ ํ๋ฌ๊ทธ์ธ๋ค์ด ๋ฃจํธ ํด๋์์ ๋ณธ์ฒด๋ฅผ ์ฐพ์ผ๋ ค๋ ๋ฒ๋ฆ์ด ์์ด์ ์์ธ๋ก ๋ก๋๋ค.
public-hoist-pattern[]=*eslint*
# ์ฝ๋ ํฌ๋งคํฐ์ธ prettier ๊ณ์ด๋ ์์ธ.
public-hoist-pattern[]=prettier
# ๋ง์ฝ ์ด๋ฆ์ ๊ณตํต์ ์ด ์๋ค๋ฉด? ์ ํํ๊ฒ ์ฝ ์ง์ด์ ์ง์ ํ ์๋ ์์ต๋๋ค.
public-hoist-pattern[]=next# ๊ทน๋จ์ ์ธ ๊ฒฝ์ฐ: npm ์ฒ๋ผ ๋ชจ๋ ํจํค์ง๋ฅผ ํธ์ด์คํ
(๋น์ถ์ฒ)
# ํฌํ
์์กด์ฑ ์ฐจ๋จ ํจ๊ณผ๊ฐ ์ฌ๋ผ์ง
shamefully-hoist=true๐ฆ ์ํธ ๋ฆฌ๋์ ์กฐ์ธ:
shamefully-hoist=true ๋ ์ด๋ฆ๋ถํฐ "์ฐฝํผํ ํธ์ด์คํ
" ์ด์์.
pnpm ์ ์ฐ๋ฉด์ npm ์ฒ๋ผ ๋์ํ๊ฒ ๋ง๋๋ ์ต์
์ด๋ผ ์ด๋ฆ์ ์ด๋ ๊ฒ ์ง์ ๊ฑฐ์์.
ํธ์ด์คํ
์ด ํ์ํ๋ค๋ฉด shamefully-hoist ๋์
public-hoist-pattern ์ผ๋ก ํ์ํ ๊ฒ๋ง ์ ํํ๊ฒ ์ง์ ํ์ธ์.
Next.js ํ๋ก์ ํธ ๊ถ์ฅ .npmrc
# .npmrc (Next.js๋ฅผ ์ธ ๋ ์ด ์ ๋๋ ๋ฃ์ด์ค์ผ ์์ด ํธํฉ๋๋ค)
# ๐ก TypeScript types ํธ์ด์คํ
(VSCode ๋ฑ ์๋ํฐ์์ ๋นจ๊ฐ์ค ์ ๋จ๊ฒ ํ๋ ค๋ฉด ํ์!)
public-hoist-pattern[]=*types*
# ๐ก ESLint ๊ณ์ด ํธ์ด์คํ
(Next.js์ ๊ธฐ๋ณธ eslint-config-next๊ฐ ๋ฃจํธ์ eslint๋ฅผ ์ฐพ๊ธฐ ๋๋ฌธ)
public-hoist-pattern[]=*eslint*
# ๐ก Tailwind CSS์ ๊ด๋ จ๋ ์น๊ตฌ๋ค์ ํธ์ด์คํ
(Tailwind๊ฐ ํ๋ฌ๊ทธ์ธ๋ค์ ๋ชป ์ฐพ๋ ์๋ฌ ๋ฐฉ์ง)
public-hoist-pattern[]=tailwindcss
public-hoist-pattern[]=postcss
public-hoist-pattern[]=autoprefixer
# ๐ก [์ค์] ๋ฒ์ ์ด ๋ค๋ฅด๋ฉด ์๋ฌ! (ํ์ ๊ฐ, ํน์ ์๋ฒ ๊ฐ ํ๊ฒฝ ์ผ์น ๋ชฉ์ )
engine-strict=true๐๏ธ nodeLinker ์ค์ โ ์๊ฒฉํจ์ ์คํํธ๋ผ
pnpm ์ nodeLinker ์ค์ ์ผ๋ก node_modules ์์ฑ ๋ฐฉ์์ ์ ํํ ์ ์๋ค.
# pnpm-workspace.yaml ๋๋ .npmrc
# nodeLinker=isolated (๊ธฐ๋ณธ๊ฐ โ ์ฌ๋งํฌ ๊ฒฉ๋ฆฌ ๊ตฌ์กฐ)
# nodeLinker=hoisted (npm ๋ฐฉ์๊ณผ ์ ์ฌํ ํํํ)
# nodeLinker=pnp (Yarn PnP ๋ฐฉ์)nodeLinker=isolated (๊ธฐ๋ณธ๊ฐ)
node_modules/
โโโ react โ .pnpm/react@18.2.0/... (์ฌ๋งํฌ, ์ง์ ์์กด์ฑ๋ง)
โโโ .pnpm/
โโโ react@18.2.0/node_modules/react/ (ํ๋๋งํฌ โ ์คํ ์ด)
์ฅ์ : ํฌํ
์์กด์ฑ ์ฐจ๋จ, ๋์คํฌ ์ ์ฝ
๋จ์ : ์ฌ๋งํฌ๋ฅผ ๋ชป ๋ฐ๋ผ๊ฐ๋ ๊ตฌํ ๋๊ตฌ์ ํธํ ์ด์
nodeLinker=hoisted
node_modules/
โโโ react/ (ํ๋๋งํฌ โ ์คํ ์ด, npm ์ฒ๋ผ ๋ฃจํธ์ ๋ฐฐ์น)
โโโ loose-envify/ (react ์ deps ๋ ๋ฃจํธ๋ก ํธ์ด์คํ
)
โโโ .pnpm-store โ ๊ธ๋ก๋ฒ ์คํ ์ด (ํ๋๋งํฌ๋ ์ ์ง)
์ฅ์ : npm/Yarn Classic ๊ณผ ๋์ผํ ๊ตฌ์กฐ๋ผ ํธํ์ฑ ์ต๊ณ
๋จ์ : ํฌํ
์์กด์ฑ ๋ฐ์ ๊ฐ๋ฅ
nodeLinker=pnp (Plug'n'Play)
.pnp.cjs โ ์์กด์ฑ ๋งต์ ํ์ผ ํ๋์ ๋ด์
.pnp.loader.mjs
(node_modules ํด๋ ์์)
์ฅ์ : node_modules ์์ฒด๊ฐ ์์ด ๊ฐ์ฅ ๋น ๋ฆ (Zero-Install ๊ฐ๋ฅ)
๋จ์ : ๋๊ตฌ ํธํ์ฑ ๊ฐ์ฅ ๋ฎ์, ์ค์ ๋ณต์ก
์ธ์ ์ด๋ค ๊ฑธ ์ฐ๋๊ฐ
| ์ํฉ | ๊ถ์ฅ ์ค์ |
|---|---|
| ์ ํ๋ก์ ํธ, ํ๋์ ๋๊ตฌ ์คํ | isolated (๊ธฐ๋ณธ๊ฐ) |
| ๊ธฐ์กด npm ํ๋ก์ ํธ ๋ง์ด๊ทธ๋ ์ด์ | hoisted โ ์ ์ง์ ์ผ๋ก isolated ์ ํ |
| ๊ตฌํ jest, webpack ํ๋ฌ๊ทธ์ธ ํผ์ฌ | hoisted |
| Yarn PnP ๋ง์ด๊ทธ๋ ์ด์ | pnp |
๐ ๏ธ ์ค์ ํธ๋ฌ๋ธ์ํ โ ์ฌ๋งํฌ๋ก ์ธํ ์๋ฌ ํด๊ฒฐ
์ผ์ด์ค 1: Cannot find module 'eslint'
# ์๋ฌ
Error: Cannot find module 'eslint'
Require stack:
- /home/user/projects/youngsu-community/node_modules/.pnpm/eslint-config-next@14.2.0/node_modules/eslint-config-next/index.js์์ธ: eslint-config-next ๊ฐ ๋ฃจํธ node_modules ์์ eslint ๋ฅผ ์ฐพ์ผ๋ ค ํจ
ํด๊ฒฐ:
# .npmrc ์ ์ถ๊ฐ
public-hoist-pattern[]=*eslint*pnpm install # ์ฌ์ค์นํ๋ฉด eslint ๊ฐ ๋ฃจํธ๋ก ํธ์ด์คํ
๋จ์ผ์ด์ค 2: PostCSS / Tailwind ์ค์ ์๋ฌ
# ์๋ฌ
Error: Cannot find module 'tailwindcss/resolveConfig'ํด๊ฒฐ:
# .npmrc ์ ์ถ๊ฐ
public-hoist-pattern[]=tailwindcss
public-hoist-pattern[]=postcss์ผ์ด์ค 3: Prisma ์์ฑ ํ์ผ ์ธ์ ๋ชปํจ
# ์๋ฌ
Cannot find module '@prisma/client'์์ธ: Prisma ๋ postinstall ์ node_modules/.prisma/client ์ ํ์ผ์ ์์ฑํ๋๋ฐ, pnpm ์ ๊ฒฉ๋ฆฌ ๊ตฌ์กฐ์์ ๊ฒฝ๋ก๊ฐ ๋ค๋ฆ
ํด๊ฒฐ:
// package.json scripts ์ ์ถ๊ฐ
{
"scripts": {
"postinstall": "prisma generate"
}
}์ผ์ด์ค 4: ์ฌ๋งํฌ๋ฅผ ๋ฐ๋ผ๊ฐ์ง ๋ชปํ๋ ๊ตฌํ ๋๊ตฌ
# ์ตํ์ ์๋จ โ .npmrc
shamefully-hoist=true
# ๋๋
node-linker=hoisted๐ ์ด์ ๋ฆฌ
pnpm node_modules ๊ตฌ์กฐ ํต์ฌ ์ ๋ฆฌ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๋ฃจํธ node_modules: package.json ์ง์ ์์กด์ฑ๋ง ์ฌ๋งํฌ๋ก ๋
ธ์ถ
.pnpm/: ๋ชจ๋ ํจํค์ง + ๊ฐ์ ์์กด์ฑ์ด ํ๋๋งํฌ๋ก ์ ์ฅ
ํผ์ด ์์กด์ฑ: ๋ฒ์ ์ด ๋ค๋ฅด๋ฉด .pnpm/ํจํค์ง@๋ฒ์ _ํผ์ด@๋ฒ์ ์ผ๋ก ๋ถ๋ฆฌ
ํธ์ด์คํ
์ ์ด: public-hoist-pattern ์ผ๋ก ์ ํ์ ๋ฃจํธ ๋
ธ์ถ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| ์ค์ | ํจ๊ณผ | ๋ถ์์ฉ |
|---|---|---|
public-hoist-pattern[]=*eslint* | eslint ๊ณ์ด ๋ฃจํธ ๋ ธ์ถ | ์์ |
shamefully-hoist=true | npm ์ฒ๋ผ ์ ์ฒด ํธ์ด์คํ | ํฌํ ์์กด์ฑ ํ์ฉ |
nodeLinker=hoisted | npm ๋ฐฉ์ ๊ตฌ์กฐ | ํฌํ ์์กด์ฑ ํ์ฉ |
auto-install-peers=true | ํผ์ด ์๋ ์ค์น | ์์ (๊ธฐ๋ณธ๊ฐ) |
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. .pnpm ํด๋ ๋ด์ ์๋ธ ํด๋๋ช
์ด some-plugin@1.0.0_react@17.0.2 ์ฒ๋ผ ํผ์ด ๋ฒ์ ๊น์ง ํฌํจ๋๋ ์ด์ ๋ ๋ฌด์์ธ๊ฐ?
โ
์ ๋ต: ๋์ผํ ํจํค์ง๋ผ๋ ํผ์ด ์์กด์ฑ ๋ฒ์ ์ด ๋ค๋ฅด๋ฉด ์๋ก ๋ค๋ฅธ ์คํ ์ปจํ
์คํธ ์ด๊ธฐ ๋๋ฌธ์ด๋ค. some-plugin ์ด react@17 ๊ณผ react@18 ํ๊ฒฝ์์ ๊ฐ๊ฐ ๋ค๋ฅธ ๋์์ ํ ์ ์์ผ๋ฏ๋ก, pnpm ์ ์ด๋ฅผ ๋ณ๋ ํด๋๋ก ๊ฒฉ๋ฆฌ ํ์ฌ ๋ ๋ฒ์ ์ด ๊ณต์กดํ ์ ์๋๋ก ํ๋ค.
๐ก ์์ธ ํด์ค:
- npm ์ ํผ์ด ์์กด์ฑ ์ถฉ๋์ "๊ทธ๋ฅ ์ค์นํ๊ฑฐ๋ ๊ฒฝ๊ณ ๋ง ์ถ๋ ฅ" ํ๋๋ฐ, ์ด๋ ๋ฐํ์ ์๋ฌ๋ก ์ด์ด์ง ์ ์๋ค
- pnpm ์ ํผ์ด ๋ฒ์ ๊น์ง ํด๋๋ช ์ ํฌํจ์์ผ ์์ ํ ๊ฒฉ๋ฆฌ โ ๊ฐ์ ํจํค์ง์ ๋ ์ปจํ ์คํธ๊ฐ ์์ ํ๊ฒ ๊ณต์กด
- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "ํผ์ด๊ฐ ๋ค๋ฅด๋ฉด ์ฌ์ค ๋ค๋ฅธ ํจํค์ง๋ค โ pnpm ์ด ์ด ์ฌ์ค์ ํด๋๋ช ์ผ๋ก ํํํ๋ค."
Q2. public-hoist-pattern ๊ณผ shamefully-hoist ์ ์ฐจ์ด๋ ๋ฌด์์ด๋ฉฐ, ์ด๋ค ์ํฉ์์ ๊ฐ๊ฐ์ ์ฌ์ฉํ๋๊ฐ?
โ
์ ๋ต: public-hoist-pattern ์ ํจํด์ ์ผ์นํ๋ ํจํค์ง๋ง ์ ํ์ ์ผ๋ก ๋ฃจํธ node_modules ์ ํธ์ด์คํ
ํ๋ค. shamefully-hoist=true ๋ ๋ชจ๋ ํจํค์ง๋ฅผ npm ๋ฐฉ์์ฒ๋ผ ๋ฃจํธ๋ก ํธ์ด์คํ
ํ์ฌ ํฌํ
์์กด์ฑ์ ํ์ฉํ๋ค. ์ ์๋ pnpm ์ ๊ฒฉ๋ฆฌ ์ฒ ํ์ ์ ์งํ๋ฉด์ ํน์ ๋๊ตฌ ํธํ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๋, ํ์๋ ๋น ๋ฅธ ๋ง์ด๊ทธ๋ ์ด์
์ด๋ ๊ตฌํ ๋๊ตฌ ๋๋ฌธ์ ์ด์ฉ ์ ์์ ๋๋ง ์ด๋ค.
๐ก ์์ธ ํด์ค:
public-hoist-pattern[]=*eslint*โ eslint ๊ด๋ จ ํจํค์ง๋ง ๋ฃจํธ ๋ ธ์ถ, ๋๋จธ์ง ๊ฒฉ๋ฆฌ ์ ์งshamefully-hoist=trueโ pnpm ์ npm ์ฒ๋ผ ๋ง๋ค์ด๋ฒ๋ฆผ (์ด๋ฆ๋ถํฐ "์ฐฝํผํ" ์ด์ )- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "์ธ๊ณผ ์์ (public-hoist-pattern) vs ์ ์ ๋ง์ทจ(shamefully-hoist) โ ๊ฐ๋ฅํ๋ฉด ์ธ๊ณผ ์์ ์ ํํ๋ผ."
Q3. ์์ฒ ์ด์ ํ ์คํธ ํ์: ๊ธด๊ธ ๋๋ฒ๊น (์์์ ํธํต)
์์ ๋์ด Slack ์ผ๋ก ๋ฉ์์ง๋ฅผ ๋ณด๋๋ค.
"์์ฒ ๋, QA ์๋ฒ์์ ๋น๋ ์คํจํ์ด์.Cannot find module 'typescript'์๋ฌ์ธ๋ฐ ๋ก์ปฌ์์๋ ์ ๋๊ฑฐ๋ ์? ์ค๋ pnpm ์ผ๋ก ๋ฐ๊พผ ๊ฑฐ๋ ๊ด๋ จ ์๋์?"์์ฒ ์ด๊ฐ ํ์ธํด๋ณด๋ ๋ก์ปฌ
.npmrc์๋public-hoist-pattern[]=*types*๊ฐ ์๋๋ฐ QA ์๋ฒ์.npmrc์๋ ์์๋ค. ์ด ์ํฉ์ ๊ทผ๋ณธ ์์ธ๊ณผ ํด๊ฒฐ์ฑ ์?
โ
์ ๋ต: .npmrc ํ์ผ์ด ํ๊ฒฝ๋ง๋ค ๋ฌ๋ผ์ ๋ฐ์ํ ๋ฌธ์ ๋ค. .npmrc ๋ ํ๋ก์ ํธ ๋ฃจํธ์ ์ปค๋ฐ ๋์ด์ผ ๋ชจ๋ ํ๊ฒฝ์์ ๋์ผํ hoisting ์ค์ ์ด ์ ์ฉ๋๋ค. ํด๊ฒฐ์ฑ
์ ํ๋ก์ ํธ ๋ฃจํธ์ .npmrc ์ ํ์ํ public-hoist-pattern ์ค์ ์ ์ถ๊ฐํ๊ณ git ์ ์ปค๋ฐํ๋ ๊ฒ์ด๋ค.
๐ก ์์ธ ํด์ค:
.npmrc๋ ์ฌ๋ฌ ์์น์์ ๋ก๋๋จ: ํ๋ก์ ํธ ๋ฃจํธ โ ํ ๋๋ ํ ๋ฆฌ(~/.npmrc) โ ์ ์ญ- ๋ก์ปฌ ๊ฐ๋ฐ์์
~/.npmrc์๋ง ์๋ ์ค์ ์ด CI/QA ์๋ฒ์๋ ์๋ ๊ฒฝ์ฐ๊ฐ ํํ ํจ์ - ์ฌ๋ฐ๋ฅธ ๊ด๋ฆฌ: ํ๋ก์ ํธ๋ณ pnpm ์ค์ ์
.npmrc(ํ๋ก์ ํธ ๋ฃจํธ) ์ ๋๊ณ git ์ ์ปค๋ฐ - ์ฃผ์: ํ ํฐ(
_authToken) ๊ฐ์ ๋ฏผ๊ฐํ ์ ๋ณด๋ ์ ๋ git ์ ์ปค๋ฐํ์ง ๋ง ๊ฒ (ํ๊ฒฝ๋ณ์ ์ฌ์ฉ) - ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "์ค์ ์ ์ฝ๋๋ค โ
.npmrc๋ git ์ผ๋ก ๊ด๋ฆฌํ๋ผ."
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
์ค๋ ์ค์ ์ pnpm ์ผ๋ก ๋ฐ๊ฟจ๋ค๊ฐ ESLint ๊ฐ ์ ๋ผ์ ํ ์๊ฐ ๋ ๋ ธ๋ค. .pnpm ํด๋ ์์ eslint ๊ฐ ์ ์๋๋ฐ ์ ๋ชป ์ฐพ๋๊ณ ๋ต๋ตํด์ ์คํ ์ค๋ฒํ๋ก์ฐ๋ฅผ ํค๋งธ๋ค.
๊ฒฐ๊ตญ ์ํธ ๋ฆฌ๋ ๋ํํ
๋ฌผ์ด๋ดค๋๋ฐ .npmrc ํ ์ค์ด ๋ต์ด์๋ค. public-hoist-pattern[]=*eslint*. ๋ญ๊ฐ ๋๊ฒ ๊ฐ๋จํ ํด๊ฒฐ์ด์๋๋ฐ ์๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋๊น ํ ์๊ฐ์ด๋ ํ๋นํ ๊ฑฐ์๋ค.
๊ทธ๋์ ๋ .pnpm ํด๋ ๊ตฌ์กฐ๊ฐ ์ง์ง ์ ๊ธฐํ๋ค. some-package@1.0.0_react@18.2.0 ์ด๋ฐ ์ด๋ฆ์ผ๋ก ํผ์ด ์์กด์ฑ ๋ฒ์ ๊น์ง ํด๋๋ช
์ ๋ฐ์๋ฒ๋ฆฌ๋ ๋ฐฉ์์ด ์ฒ์์ ์ด์ํด๋ณด์๋๋ฐ, ์๊ณ ๋ณด๋๊น ์์ฒญ ์๋ฆฌํ ์ค๊ณ์๋ค. ํผ์ด๊ฐ ๋ค๋ฅด๋ฉด ๋ค๋ฅธ ์ปจํ
์คํธ๋ผ๋ ๊ฑธ ํด๋ ๊ตฌ์กฐ๋ก ํํํ๋ ๊ฑฐ์์.
๐ก ์ค๋์ ๊ตํ: "pnpm ์์ '๋ชจ๋ ๋ชป ์ฐพ๊ฒ ๋ค'๋ ์๋ฌ๋ ์ญ์คํ๊ตฌ
.npmrc์public-hoist-pattern์ ์ถ๊ฐํ๋ฉด ํด๊ฒฐ๋๋ค. ๊ตฌ์กฐ๋ฅผ ์๋ฉด ๋นํฉํ์ง ์๋๋ค."
๋ด์ผ์ pnpm CLI ๋ช
๋ น์ด๋ pnpm-lock.yaml ๊ตฌ์กฐ ๊ณต๋ถํด์ผ์ง. ์ค๋์ ์นํจ ๋จน๊ณ ์ผ์ฐ ์์ผ๊ฒ ๋ค. ๋จธ๋ฆฌ๊ฐ ๋ฌด๊ฑฐ์.