๐ฟ ์์กด์ฑ 4์ข ์ธํธ โ dependencies, devDependencies, peerDependencies, overrides
๐ ๊ฐ์
์์กด์ฑ 4์ข ๋ฅ๋ฅผ ์๋ฒฝํ๊ฒ ๊ตฌ๋ถํ๋ค. Next.js ๋งฅ๋ฝ์์ ์ด๋ค ํจํค์ง๊ฐ ์ด๋ ๋ค์ด๊ฐ์ผ ํ๋์ง, peerDependencies ๊ฐ ์ ์กด์ฌํ๋์ง, overrides ๋ก ์ถฉ๋์ ํด๊ฒฐํ๋ ๋ฒ๊น์ง ๋ค๋ฃฌ๋ค.
๐ ๋ชฉ์ฐจ
- ๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
- ๐ค ์ ์์์ผ ํ๋๊ฐ
- ๐ฆ dependencies
- ๐ง devDependencies
- ๐ค peerDependencies
- ๐ฒ optionalDependencies
- ๐ง overrides
- ๐ Next.js ํ๋ก์ ํธ ์์กด์ฑ ๋ถ๋ฅ ์ค์
- ๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
- ๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
- ๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
- ๐ ๋ ์์๋ณด๊ธฐ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 20๋ถ(์ ์ฒด) / ํต์ฌ ํํธ๋ง: 10๋ถ (peerDependencies + Next.js ๋ถ๋ฅ)
๐บ๏ธ ์ด ๋ฌธ์์ ํ๋ฆ
๋ฐํ์ ํ์(dependencies) โ ๊ฐ๋ฐ ๋๊ตฌ(devDependencies) โ peerDependencies ์๋ฆฌ โ overrides ์ถฉ๋ ํด๊ฒฐ โ Next.js ์ค์ ๋ถ๋ฅ
๐ฏ ์ด ๋ฌธ์๋ฅผ ๋ค ์ฝ์ผ๋ฉด ํ ์ ์๋ ๊ฒ
-
dependencies์devDependencies๋ฅผ ํญ์ ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ๋ถํ ์ ์๋ค -
peerDependencies๊ฐ ์ ์กด์ฌํ๋์ง, React ์ธ์คํด์ค ์ค๋ณต ๋ฌธ์ ๋ฅผ ์๋ฐฉํ๋ ์๋ฆฌ๋ฅผ ์ค๋ช ํ ์ ์๋ค -
overrides๋ก ๊ฐ์ ์์กด์ฑ์ ๋ฒ์ ์ ๊ฐ์ ์ง์ ํ ์ ์๋ค - Next.js ํ๋ก์ ํธ์์
tailwindcss,prisma,@prisma/client์ ์์น๋ฅผ ์ฆ์ ํ๋จํ ์ ์๋ค
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ๐ฃ ์์ฒ ( ์ ์
): "๋ฆฌ๋ ๋, ์ ๊ฐ
@youngsoo/ui๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ง๋ค๋ฉด์react๋ฅผdependencies์ ๋ฃ์๋๋ฐ, ๋ฉ์ธ ์ฑ์์ ํ ์ค๋ฅ๊ฐ ๋ฌ์ด์.Invalid hook call์ด์. ๊ทธ๋ฆฌ๊ณprisma๋@prisma/client์ค์ ๋ญ๊ฐdevDependencies์ธ์ง๋ ํท๊ฐ๋ ค์. ๋น๋ํ ๋ ์ฐ์ด๋ ๊ฑด ์ ๋ถdevDependencies์๋๊ฐ์?" - ๐ฆ ์ํธ ( ๋ฆฌ๋ ): "์์ฒ ๋,
Invalid hook call์ React ์ธ์คํด์ค๊ฐ ๋ ๊ฐ ์๊ฒผ์ ๋ ๋๋ ์๋ฌ์์.@youngsoo/ui๊ฐ ์๊ธฐnode_modules์ React ๋ฅผ ๋ฐ๋ก ๋ค๊ณ ์๊ฑฐ๋ ์.peerDependencies๋ฅผ ์ดํดํ๋ฉด ์ ๊ทธ๊ฒ ๋ฌธ์ ์ธ์ง ๋ฐ๋ก ์ ์ ์์ด์. ๊ทธ๋ฆฌ๊ณdevDependenciesํ๋จ ๊ธฐ์ค์ '๋น๋ํ ๋ ์ฐ์ด๋๋' ๊ฐ ์๋๋ผ 'ํ๋ก๋์ ์๋ฒ๊ฐ ์คํ ์ค์ ์ด ํจํค์ง๊ฐ ํ์ํ๋' ์์."
๐ค ์ ์์์ผ ํ๋๊ฐ
์์๋ค ์ปค๋ฎค๋ํฐ ํ์ Next.js ์ฑ๊ณผ ๋ด๋ถ UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ @youngsoo/ui ๋ฅผ ํจ๊ป ๊ฐ๋ฐํ๊ณ ์๋ค. ์ด๋ ๋ ์์ฒ ์ด๊ฐ UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ useState ๋ฅผ ์ฐ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์๋๋ฐ, ๋ฉ์ธ ์ฑ์์ ๊ฐ์ ธ๋ค ์ฐ์๋ง์ ์ด๋ฐ ์๋ฌ๊ฐ ๋ฌ๋ค:
Uncaught Error: Invalid hook call.
Hooks can only be called inside of the body of a function component.
์ง๋จํด๋ณด๋ @youngsoo/ui/node_modules/react ์ ๋ฉ์ธ ์ฑ์ node_modules/react ๊ฐ ๋ณ๋๋ก ์กด์ฌํ๊ณ ์์๋ค. ๋ ๊ฐ์ React ์ธ์คํด์ค ๊ฐ ์๊ธด ๊ฒ์ด๋ค.
์์ธ์ ์์ฒ ์ด๊ฐ @youngsoo/ui/package.json ์ react ๋ฅผ dependencies ์ ๋ฃ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด ๋ฌธ์ ๋ฅผ ์ดํดํ๋ ๊ฒ์ด peerDependencies ์ ํต์ฌ์ด๋ค.
๐ฆ dependencies โ ๋ฐํ์ ํ์ ์ฝ๋
{
"dependencies": {
// ๐ก ์ง๋ฌธ 1๊ฐ๋ง ๋์ ธ๋ณด์ธ์: "๋ด ์๋น์ค๊ฐ ๋์๊ฐ๋ ๋์ ์ด ์ฝ๋๊ฐ ํ์ํ๊ฐ?"
// ์๋ฒ๊ฐ ๋ ๋ ๋ ๋๋งํ๋ ค๋ฉด next, react ๊ฐ ๊ผญ ํ์ํ์ฃ !
"next": "^14.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"jotai": "^2.6.4",
// DB๋ฅผ ์ฐ๋ฅด๋ ค๋ฉด @prisma/client ๋ ๋ฐํ์์ ํธ์ถ๋์ด์ผ ํฉ๋๋ค.
"@prisma/client": "^5.9.1"
}
}ํ๋จ ๊ธฐ์ค โ ๋ฑ ํ๋๋ง ๊ธฐ์ตํด๋ผ:
"ํ๋ก๋์ ์๋ฒ๊ฐ ์คํ ์ค์ ์ด ํจํค์ง์ ์ฝ๋๊ฐ ์คํ๋๋๊ฐ?"
YES โ dependencies / NO โ devDependencies
์ค์น ๋์:
npm install # dependencies + devDependencies ๋ชจ๋ ์ค์น
npm install --production # dependencies ๋ง ์ค์น
NODE_ENV=production npm install # dependencies ๋ง ์ค์น๐ง devDependencies โ ๊ฐ๋ฐ ๋๊ตฌ, ๋น๋ ํ์์๋ง ํ์ํ ๊ฒ
{
"devDependencies": {
// ๐ฆ "์ฌ์ฉ์์๊ฒ ๋ฐฐํฌ๋ ๋๋ ์ ๋ณผ ๋
์๋ค" ์
๋๋ค.
// ํ์
์คํฌ๋ฆฝํธ์ฒ๋ผ ์ฝ๋ ์งค ๋๋ง ์ฐ๋ ๋๊ตฌ (๋์ค์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๋ณ์ ํ๋๊น์!)
"typescript": "^5.3.3",
"@types/react": "^18.2.48",
// ๋ฆฐํธ, ํฌ๋งคํฐ๋ ๋ฐฐํฌ์๋ฒ์๋ ์ฌ๋ผ๊ฐ ์ด์ ๊ฐ ์์ฃ .
"eslint": "^8.56.0",
"prettier": "^3.2.4",
// tailwind ๋ ๋น๋ํ ๋ CSS ํ์ผ์ ์ซ ๋ฝ์๋ด๊ณ ๋๋ฉด ์ญํ ๋!
"tailwindcss": "^3.4.1",
"prisma": "^5.9.1"
}
}ํท๊ฐ๋ฆฌ๊ธฐ ์ฌ์ด ์ผ์ด์ค โ ์ ์ด๊ฒ๋ค์ด devDependencies ์ธ๊ฐ?
| ํจํค์ง | ํท๊ฐ๋ฆฌ๋ ์ด์ | devDependencies ์ธ ์ด์ |
|---|---|---|
tailwindcss | ๋น๋์ ํ์! | ๋น๋ ๊ฒฐ๊ณผ๋ฌผ์ CSS ํ์ผ. ์๋ฒ ์คํ ์์ ์ด๋ฏธ ์์ฑ๋ CSS ๋ง ์์ผ๋ฉด ๋จ |
typescript | ์ฝ๋ ์์ฑ์ ํ์! | ๋น๋ ํ JS ๋ก ๋ณํ๋จ. ์๋ฒ๋ JS ์คํ, TS ํ์ ์์ |
@types/* | ์ฝ๋ ์์ฑ์ ํ์! | ํ์ ์ ๋ณด๋ ์ปดํ์ผ ํ์์๋ง ์ฌ์ฉ. ๋ฐํ์์ ์์ |
prisma (CLI) | DB ์์ด ๋ชป ๋ง๋ค์์! | ๋ง์ด๊ทธ๋ ์ด์
/์คํค๋ง CLI ๋๊ตฌ. ๋ฐํ์์ @prisma/client ๋ง ํ์ |
jest | ํ ์คํธ ์์ธ ๋ชป ๋ฐฐํฌ! | ํ ์คํธ๋ ๋ฐฐํฌ ์ ์๋ง ์คํ. ํ๋ก๋์ ์๋ฒ์๋ ๋ถํ์ |
๐ฃ ์์ฒ : "
tailwindcss๊ฐdevDependencies์ธ ๊ฒ ์์ง๋ ์ข ์ด์ํ๋ฐ์?"๐ฆ ์ํธ: "Next.js ๋น๋ ๊ณผ์ ์ ๊ทธ๋ฆผ์ผ๋ก ๊ทธ๋ ค๋ณผ๊ฒ์:
๊ฐ๋ฐ ์ ์์ค ์ฝ๋ (.tsx) + Tailwind ํด๋์ค ์ค์บ (tailwindcss ์ฌ์ฉ) + PostCSS ์ฒ๋ฆฌ (postcss, autoprefixer ์ฌ์ฉ) โ ๋น๋ .next/static/css/xxx.css (์์ฑ๋ CSS ํ์ผ) ํ๋ก๋์ ์๋ฒ .next/ ํด๋๋ง ์คํ โ tailwindcss? ํ์ ์์. CSS ์ด๋ฏธ ๋ง๋ค์ด์ง.๋น๋ ๋๊ตฌ๋ ๋น๋ํ ๋๋ง ํ์ํด์. ์์ฑ๋ ๊ฑด๋ฌผ ์ง๊ณ ๋๋ฉด ๊ณต์ฌ ๋๊ตฌ ์น์๋ ๋ผ์."
๐ค peerDependencies โ "๋๋ ๋ค ๊ฒ์ ๊ณต์ ํ ๊ฒ"
peerDependencies ๊ฐ ์์๋ค๋ฉด ์๊ธฐ๋ ๋ฌธ์
node_modules/
react/ โ ๋ด ์ฑ์ React 18.2.0
@youngsoo/ui/
node_modules/
react/ โ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ค๊ณ ์จ ๋ ๋ค๋ฅธ React 18.2.0
๋ฒ์ ์ด ๊ฐ์๋ ๋ฌธ์ ๋ค. node_modules ๋ด ๋ค๋ฅธ ๊ฒฝ๋ก์ ์์ผ๋ฉด Node.js ๋ ๋ค๋ฅธ ๋ชจ๋๋ก ์ทจ๊ธํ๋ค. React ๋ ๋ด๋ถ์ ์ผ๋ก ๋จ์ผ ์ ์ญ ์ธ์คํด์ค๋ฅผ ๊ฐ์ ํ๊ณ ๋์ํ๊ธฐ ๋๋ฌธ์, ๋ ๊ฐ์ ์ธ์คํด์ค๊ฐ ๊ณต์กดํ๋ฉด:
useState,useEffect๋ฑ ํ ์ด "์ด๋ค React ์ ๋ฑ๋กํด์ผ ํ์ง?" ํผ๋ โInvalid hook callContext.Provider์ ๊ฐ์ด ๋ค๋ฅธ React ์ธ์คํด์ค์useContext๋ก ์ฝํ์ง ์์ โundefined
peerDependencies ์ ํด๊ฒฐ์ฑ
// @youngsoo/ui/package.json
{
// ๐ก "๋ด๊ฐ ์ง์ ์ค์น ์ ํ ํ
๋, ๋ ์ฐ๋ ์ฑ์! ๋ค๊ฐ ์ค์นํ ๋ฆฌ์กํธ ์ข ๋น๋ ค์ค!"
// ์ด๋ ๊ฒ ํด์ผ ์๋ฅ์ด ๋ฆฌ์กํธ๊ฐ ์๊ฒจ์ ํ
์๋ฌ๊ฐ ๋๋ ๊ฑธ ๋ง์ ์ ์์ด์.
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
// ๐ฆ "ํ์ง๋ง ๋ด๊ฐ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ง๊ธ ๊ฐ๋ฐํ๊ณ ํ
์คํธํ๋ ค๋ฉด ๋ฆฌ์กํธ๊ฐ ํ์ํ๋๊น..."
// ๊ฐ๋ฐ์ฉ์ผ๋ก๋ง ์์๋ก ์ค์นํด๋ก๋๋ค.
"devDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}์๋ฏธ: "๋(@youngsoo/ui)๋ React ๊ฐ ํ์ํ์ง๋ง, ์ง์ ์ค์นํ์ง ์์๊ฒ. ๋๋ฅผ ์ฌ์ฉํ๋ ์ฑ์ด React ๋ฅผ ์ ๊ณตํด์ค. ๋๋ ๊ทธ๊ฒ์ ๊ณต์ ํด์ ์ธ๊ฒ."
๊ฒฐ๊ณผ:
node_modules/
react/ โ ์ฑ๊ณผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๊ณต์ ํ๋ ๋จ ํ๋์ React 18.2.0
@youngsoo/ui/ โ ์์ฒด node_modules/react ์์
devDependencies ์๋ ๋ฃ๋ ์ด์ : ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฒด๋ฅผ ๊ฐ๋ฐํ๊ณ ํ
์คํธํ ๋๋ React ๊ฐ ์ค์ ๋ก ์ค์น๋์ด ์์ด์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
npm v7+ ์์ peerDependencies ์๋ ์ค์น
# npm v7+ ๋ peerDependencies ๋ฅผ ์๋์ผ๋ก ์ค์นํจ
# (npm v6 ์ดํ์์๋ ๊ฒฝ๊ณ ๋ง ํ์ํ๊ณ ์๋ ์ค์น ์ ํจ)
npm install @youngsoo/ui
# โ @youngsoo/ui ์ค์น + peerDependencies ์ธ react, react-dom ๋ ํจ๊ป ์ค์นpeerDependenciesMeta โ ์ ํ์ peer
{
"peerDependencies": {
"react": "^18.0.0",
"next": ">=13.0.0"
},
"peerDependenciesMeta": {
"next": {
"optional": true
}
}
}next ๋ ์์ผ๋ฉด Next.js ์ ์ฉ ๊ธฐ๋ฅ์ ํ์ฑํํ์ง๋ง, ์์ด๋ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ๋์ํจ์ ์๋ฏธํ๋ค.
๐ฒ optionalDependencies โ ์์ผ๋ฉด ์ข๊ณ , ์์ด๋ ๊ด์ฐฎ์
{
"optionalDependencies": {
"fsevents": "^2.3.3"
}
}์ค์น์ ์คํจํด๋ ์ ์ฒด npm install ์ด ์ค๋จ๋์ง ์๋๋ค.
์ฃผ์ ์ฌ์ฉ ์ผ์ด์ค:
fseventsโ macOS ์ ์ฉ ํ์ผ ๊ฐ์ ๋ชจ๋ (Linux/Windows ์์๋ ์ค์น ์คํจํด๋ ๋ฌด๋ฐฉ)- ํน์ OS ์ ์ฉ ๋ค์ดํฐ๋ธ ๋ชจ๋
- ์์ผ๋ฉด ์ฑ๋ฅ์ด ํฅ์๋์ง๋ง ์์ด๋ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ๋์ํ๋ ํจํค์ง
์ฝ๋์์๋ ์กด์ฌ ์ฌ๋ถ๋ฅผ ํ์ธํด์ผ ํ๋ค:
let fsevents
try {
fsevents = require('fsevents')
} catch (e) {
// fsevents ๊ฐ ์์ ๋ fallback
fsevents = null
}๐ง overrides โ ๋ฒ์ ์ถฉ๋์ ์ธ๊ณผ์ ํด๊ฒฐ
overrides ๋ npm 8.3+ ์์ ์ง์ํ๋ ๊ธฐ๋ฅ์ผ๋ก, ์ง์ ์์กด์ฑ๋ฟ ์๋๋ผ ๊ฐ์ ์์กด์ฑ์ ๋ฒ์ ๊น์ง ๊ฐ์ ์ง์ ํ ์ ์๋ค.
์ฌ์ฉ ์ผ์ด์ค 1 โ ๊ฐ์ ์์กด์ฑ์ ๋ณด์ ์ทจ์ฝ์ ์์
๋ด ์ฑ
โโ some-library@2.0.0
โโ vulnerable-pkg@1.0.0 โ ์ทจ์ฝ์ ๋ฐ๊ฒฌ! 1.2.0 ์์ ํจ์น๋จ
some-library ๊ฐ ์์ง ์
๋ฐ์ดํธ๋ฅผ ์ ํ์ ๋:
{
"overrides": {
"vulnerable-pkg": "^1.2.0"
}
}์ฌ์ฉ ์ผ์ด์ค 2 โ ํน์ ํจํค์ง ์์ ์์กด์ฑ๋ง ์์
{
"overrides": {
"some-library": {
"vulnerable-pkg": "^1.2.0"
}
}
}some-library ๊ฐ ์ฌ์ฉํ๋ vulnerable-pkg ๋ง ๋ฒ์ ์ ์ฌ๋ฆฌ๊ณ , ๋ค๋ฅธ ๊ณณ์์ ์ฐ๋ ๊ฑด ๊ฑด๋๋ฆฌ์ง ์๋๋ค.
์ฌ์ฉ ์ผ์ด์ค 3 โ ๋ฒ์ ํต์ผ (์ค๋ณต ํจํค์ง ์ ๊ฑฐ)
{
"dependencies": {
"next": "^14.1.0",
"some-old-lib": "^3.0.0"
},
"overrides": {
"some-old-lib": {
"react": "$react"
}
}
}$react ๋ dependencies.react ์ ๋ฒ์ ์ ์ฐธ์กฐํ๋ ํํ์. some-old-lib ๊ฐ ๋ค๊ณ ์ค๋ React ๋ฅผ ๋ฉ์ธ ์ฑ์ React ์ ๋์ผํ๊ฒ ๊ฐ์ ํ๋ค.
๐ฆ ์ํธ์ ์กฐ์ธ: "
overrides๋ '์ธ๊ณผ์ ์์ ' ์ด์์. ํญ์ ๊ฐ์ฅ ์ข์ ๋ฒ์๋ก ์ ์ฉํ๊ณ , ์ ์ด override ๊ฐ ํ์ํ์ง ์ฃผ์์ผ๋ก ๋จ๊ฒจ์ผ ํด์."{ "overrides": { // react-beautiful-dnd ๊ฐ 14.3.0 ์์ Breaking Change ๋ฃ์ (SemVer ์๋ฐ) // 14.2.0 ์ด ๋ง์ง๋ง ์์ ๋ฒ์ "react-beautiful-dnd": "14.2.0" } }
๐ Next.js ํ๋ก์ ํธ ์์กด์ฑ ๋ถ๋ฅ ์ค์
์์๋ค ์ปค๋ฎค๋ํฐ์ ์์ฑํ ์์กด์ฑ ๋ถ๋ฅ:
{
"dependencies": {
"next": "^14.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"@prisma/client": "^5.9.1",
"next-auth": "^4.24.5",
"jotai": "^2.6.4",
"@tanstack/react-query": "^5.18.0",
"@tanstack/react-query-devtools": "^5.18.0",
"zod": "^3.22.4",
"socket.io-client": "^4.7.2",
"@youngsoo/ui": "workspace:*"
},
"devDependencies": {
"typescript": "^5.3.3",
"@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18",
"@types/node": "^20.11.5",
"eslint": "^8.56.0",
"eslint-config-next": "^14.1.0",
"prettier": "^3.2.4",
"tailwindcss": "^3.4.1",
"autoprefixer": "^10.4.17",
"postcss": "^8.4.33",
"prisma": "^5.9.1",
"jest": "^29.7.0",
"@testing-library/react": "^14.1.2",
"@testing-library/jest-dom": "^6.4.1",
"jest-environment-jsdom": "^29.7.0",
"husky": "^9.0.10",
"lint-staged": "^15.2.2",
"@next/bundle-analyzer": "^14.1.0",
"cross-env": "^7.0.3"
}
}๋ถ๋ฅ ๊ทผ๊ฑฐ ์์ธ ํด์ค
| ํจํค์ง | ์์น | ์ด์ |
|---|---|---|
@prisma/client | dependencies | Next.js ์๋ฒ ์ปดํฌ๋ํธ / Route Handler ์์ DB ์ฟผ๋ฆฌ ์คํ |
prisma (CLI) | devDependencies | ๋ง์ด๊ทธ๋ ์ด์ , ์คํค๋ง ์์ฑ CLI ๋๊ตฌ. ๋ฐํ์ ๋ถํ์ |
next-auth | dependencies | ๋ฏธ๋ค์จ์ด + ์๋ฒ์์ ์ธ์ ๊ฒ์ฆ. ๋ฐํ์ ํ์ |
jotai | dependencies | ํด๋ผ์ด์ธํธ ์ํ ๊ด๋ฆฌ. ๋ธ๋ผ์ฐ์ ์์ ์คํ |
@tanstack/react-query-devtools | dependencies | Next.js ์๋ฒ ๋ฒ๋ค์์ process.env.NODE_ENV ์ฒดํฌ ํ ๋ ๋ ์ฌ๋ถ ๊ฒฐ์ ํ๋ฏ๋ก dependencies |
zod | dependencies | Route Handler ์์ ์๋ฒ ์ฌ์ด๋ ์ ํจ์ฑ ๊ฒ์ฌ |
socket.io-client | dependencies | ๋ธ๋ผ์ฐ์ ์์ WebSocket ์ฐ๊ฒฐ |
tailwindcss | devDependencies | ๋น๋ ํ์ CSS ์์ฑ ๋๊ตฌ |
@types/* | devDependencies | ํ์ ์ ๋ณด๋ ๋ฐํ์์ ์์ |
๐ก
@tanstack/react-query-devtools์ฃผ์: ์ด ํจํค์ง๋ ๋ด๋ถ์ ์ผ๋กprocess.env.NODE_ENV !== 'production'์ผ ๋๋ง ์ค์ devtools UI ๋ฅผ ๋ ๋๋งํ๋ค. ๋ฐ๋ผ์devDependencies์ ๋ฃ์ด๋ ๋์ง๋ง, ์ผ๋ถ ๋ฒ๋ค๋ฌ ์ค์ ์ ๋ฐ๋ผ ์กฐ๊ฑด๋ถ import ๊ฐ ์ ๋๋ ๊ฒฝ์ฐ๊ฐ ์์ดdependencies์ ๋ฃ๋ ๊ฒ์ด ์์ ํ๋ค.
๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
| ์ข ๋ฅ | ํ๋จ ๊ธฐ์ค | ๋ํ ์์ |
|---|---|---|
dependencies | ํ๋ก๋์ ์๋ฒ ์คํ ์ ํ์ํ ์ฝ๋ | react, next, @prisma/client |
devDependencies | ๊ฐ๋ฐ/๋น๋ ํ์์๋ง ํ์ | typescript, tailwindcss, prisma CLI |
peerDependencies | ํธ์คํธ ์ฑ์ด ์ค์นํด์ผ ํ ๊ฒ (๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ฅ) | react, react-dom (๋ด๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ ์) |
optionalDependencies | ์์ด๋ ๋์์ ๋จ | fsevents |
overrides | ๊ฐ์ ์์กด์ฑ ๋ฒ์ ๊ฐ์ | ์ทจ์ฝ์ ํจ์น, Breaking Change ๊ณ ์ |
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. prisma ์ @prisma/client ์ ์ฌ๋ฐ๋ฅธ ์์กด์ฑ ์์น๋?
a) ๋ ๋ค dependencies
b) ๋ ๋ค devDependencies
c) prisma ๋ devDependencies, @prisma/client ๋ dependencies
d) prisma ๋ dependencies, @prisma/client ๋ devDependencies
โ
์ ๋ต: c
๐ก ์์ธ ํด์ค:
@prisma/clientโdependencies: Next.js ์๋ฒ ์ปดํฌ๋ํธ๋ Route Handler ์์ ์คํ ์ค์ DB ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฐ๋ค.prisma.$connect(),prisma.user.findMany()๊ฐ์ ์ฝ๋๊ฐ ํ๋ก๋์ ์๋ฒ์์ ์คํ๋๋ค. ๋ฐํ์ ํ์.prisma(CLI) โdevDependencies:npx prisma migrate dev,npx prisma generate๊ฐ์ ๋ช ๋ น์ด๋ ๊ฐ๋ฐ ์ค์๋ง ์คํ๋๋ค. ํ๋ก๋์ ์๋ฒ์์prismaCLI ๋ฅผ ์ง์ ํธ์ถํ๋ ์ผ์ ์๋ค.- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "
@prisma/client= ์๋ฒ๊ฐ DB ์ ์ ์ํ ๋ ์ฐ๋ ๋ฐํ์ ์ฝ๋.prisma= ์คํค๋ง ๊ด๋ฆฌ CLI ๋๊ตฌ."
Q2. ์๋ ์๋ฌ๊ฐ ๋ฐ์ํ๋ ๊ฐ์ฅ ์ง์ ์ ์ธ ์์ธ์?
Uncaught Error: Invalid hook call.
Hooks can only be called inside of the body of a function component.
a) React ๋ฒ์ ์ด ๋๋ฌด ๋ฎ์์ ํ
์ ์ง์ํ์ง ์๋๋ค
b) ์๋ฒ ์ปดํฌ๋ํธ์์ useState ๋ฅผ ์ฌ์ฉํ๋ค
c) ๋ ๊ฐ์ React ์ธ์คํด์ค๊ฐ ๊ณต์กดํด์, ํ
์ด ์ด๋ ์ธ์คํด์ค์ ๋ฑ๋กํด์ผ ํ ์ง ํผ๋์ด ์๊ฒผ๋ค
d) useEffect ๋ฅผ ์๋ชป๋ ์์น์์ ํธ์ถํ๋ค
โ
์ ๋ต: c โ ๋ ๊ฐ์ React ์ธ์คํด์ค ๋ฌธ์
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช
: React ํ
์ ๋ด๋ถ์ ์ผ๋ก ๋จ์ผ ์ ์ญ React ์ธ์คํด์ค์ ์ํ ์ ์ฅ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ด๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ
dependencies์react๋ฅผ ๋ฃ์ผ๋ฉดnode_modules/library/node_modules/react๋ผ๋ ๋ณ๋ ์ธ์คํด์ค๊ฐ ์๊ธด๋ค. ์ด ์ธ์คํด์ค๋ ์ฑ์node_modules/react์ ๋ค๋ฅธ ๊ฐ์ฒด์ด๋ฏ๋ก, ํ ์ด "์ด๋์ ๋ฑ๋กํด์ผ ํ์ง?" ํผ๋์ ๊ฒช๋๋ค. - ํด๊ฒฐ: ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
react๋ฅผpeerDependencies๋ก ์ด๋ํ๋ฉด ํธ์คํธ ์ฑ์ React ์ธ์คํด์ค๋ฅผ ๊ณต์ ํด ์ด ๋ฌธ์ ๊ฐ ์ฌ๋ผ์ง๋ค. - ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "Invalid hook call = React ์ธ์คํด์ค ๋ ๊ฐ. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ peerDependencies ๋ก ํด๊ฒฐ."
Q3. ๐ฃ ์์ฒ ์ด์ ํ ์คํธ ํ์ โ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํธ๋ ์ด๋์คํ
์์๋ค ํ์ด @youngsoo/ui ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ package.json ์ ์ค๊ณํ๋ ํ์๊ฐ ์ด๋ ธ๋ค. ๊ฐ ํ์์ด ์๊ฒฌ์ ๋๋ค.
- ๐ฃ ์์ฒ : "react ๋ฅผ dependencies ์ ๋ฃ์๊ฒ์. ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์๋ React ๊ฐ ํ์ํ์์์."
- ๐ ์์ (PM): "์ ๋ ์ ๋ชจ๋ฅด๊ฒ ๋๋ฐ, ๋ ๋ฐฉ์์ ์ฅ๋จ์ ์ด ๋ญ์ง ์ค๋ช ํด์ค์."
- ๐ฆ ์ํธ: "?"
์ํธ ๋ฆฌ๋์ ์ ์ฅ์์ ์ฌ๋ฐ๋ฅธ ๊ฒฐ๋ก ๊ณผ ๊ทผ๊ฑฐ๋ฅผ ์ค๋ช ํ๋ผ.
โ
์ ๋ต: react ๋ peerDependencies ์ devDependencies ์ ๋์์ ๋ฃ์ด์ผ ํ๋ค
{
"name": "@youngsoo/ui",
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}๐ก ์์ธ ํด์ค:
dependencies์ ๋ฃ์ผ๋ฉด: ํธ์คํธ ์ฑ(youngsoo-community)์ ์ด๋ฏธreact@18์ด ์ค์น๋์ด ์์ด๋,@youngsoo/ui๊ฐ ์์ ์node_modules์ ๋ ๋ค๋ฅธ React ๋ฅผ ์ค์นํ๋ค. โ ๋ ์ธ์คํด์ค โ Invalid hook call + Context ๋จ์ .peerDependencies์ ๋ฃ์ผ๋ฉด: "๋๋ React ๊ฐ ํ์ํ์ง๋ง ํธ์คํธ ์ฑ์ ๊ฒ์ ์ธ๊ฒ" ๋ผ๋ ์ ์ธ. npm ์ด ๋จ์ผnode_modules/react๋ฅผ ๊ณต์ ํ๋๋ก ์ค๊ณํ๋ค.devDependencies์๋ ๋ฃ๋ ์ด์ : ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฒด๋ฅผ ๊ฐ๋ฐํ๊ฑฐ๋ ํ ์คํธํ ๋(jest,storybook๋ฑ) ์ค์ ๋ก React ๊ฐ ์ค์น๋์ด ์์ด์ผ ํ๋ค.peerDependencies๋ง ์์ผ๋ฉด ๊ฐ๋ฐ ํ๊ฒฝ์์ React ๊ฐ ์์ด์ ํ ์คํธ๊ฐ ์ ๋์๊ฐ๋ค.- ์์(PM) ์๊ฒ ํ ๋ง๋: "๊ฐ์ React ๋ฅผ ๊ณต์ ํด์ผ Context ์ ํ ์ด ์ ์ ์๋ํด์. ๋น์ฉ์ ๊ฑฐ์ ์๊ณ ์์ ์ฑ์ ํฌ๊ฒ ์ฌ๋ผ๊ฐ์."
- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "๋ด๊ฐ ๋ง๋๋ ๊ฒ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ๋ฉด โ ํธ์คํธ ์ฑ๊ณผ ๊ณต์ ํด์ผ ํ ๊ฒ์ peerDependencies, ๊ฐ๋ฐํ ๋ ์ง์ ์ธ ๊ฒ์ devDependencies ์๋ ํจ๊ป."
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
์ค๋ ์คํ ๋ด๋ด Invalid hook call ์๋ฌ์ ์จ๋ฆํ๋ค. ์ฒ์์ ๋จ์ํ ํ
์ ์๋ชป ์ด ๊ฑด ์ค ์๊ณ ์คํ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋ค์ก๋๋ฐ, ์ํธ ๋ฆฌ๋ ๋์ด "๋ React ์ธ์คํด์ค ๋ฌธ์ " ๋ผ๊ณ ๋ฑ ์ง์ด์ฃผ์
์ ์์ธ์ ์ฐพ์๋ค.
@youngsoo/ui ์ react ๋ฅผ peerDependencies ๋ก ์ฎ๊ฒผ๋๋ ์๋ฌ๊ฐ ๋ฐ๋ก ์ฌ๋ผ์ก๋ค. ์ ๊ทธ๊ฒ ํด๊ฒฐ๋๋์ง๋ ์ด์ ์์ ํ ์ดํดํ๋ค. node_modules ๊ฒฝ๋ก๊ฐ ํ๋๋ก ํต์ผ๋๋ฉด์ React ์ธ์คํด์ค๊ฐ ํ๋๋ง ๋จ๋ ๊ฑฐ๋ค.
๐ก ์ค๋์ ๊ตํ: "๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค ๋
peerDependencies๋ฅผ ๋น ๋จ๋ฆฌ๋ฉด, ์ฌ์ฉํ๋ ์ฑ์์ ์ด์ ๋ชจ๋ฅผ ํ ์ค๋ฅ๊ฐ ํฐ์ง๋ค. ์์กด์ฑ์ ๊ณต์ ์ฌ๋ถ๋ฅผ ์ค๊ณํ๋ ๊ฒ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์์ ์ฑ ์์ด๋ค."
ํด๊ทผํ๋ฉด์ ๊ฑธ์ด๊ฐ๋ค๊ฐ ์ด๊ฒ์ ๊ฒ ๋จธ๋ฆฟ์์์ ์ ๋ฆฌ๋๋ค. dependencies vs devDependencies ํ๋จ ๊ธฐ์ค โ "ํ๋ก๋์
์๋ฒ๊ฐ ์คํ ์ค์ ํ์ํ๊ฐ?" โ ์ด๊ฑฐ ํ๋๋ง ๊ธฐ์ตํด๋ ์์ผ๋ก ํท๊ฐ๋ฆฌ์ง ์์ ๊ฒ ๊ฐ๋ค.
๋ด์ผ์ npm install ์ด ๋ด๋ถ์์ ์ด๋ป๊ฒ lock ํ์ผ์ ์ฐ๋์ง ํ๋ด์ผ์ง. ์ค๋์ ์ผ์ฐ ์์ผ๊ฒ ๋ค. ์ข ํผ๊ณคํ๋ค.