pnpm Workspace๋ก Monorepo ๋ง๋ค๊ธฐ
์ถ์์ ์ธ
ํ์ฌ ๋ค์ํ ๋๊ตฌ๋ค์ด monorepo ๊ฐ๋ ์ ์ง์ํ๊ณ ์์ต๋๋ค. ๊ธฐ๋ณธ ํจํค์ง ๋ ๋ฒจ์์ ์ง์
yarn berry
, pnpm workspace
์ด๋ ๊ด๋ จ ๋๊ตฌ๋คNx
, ์ต๊ทผ์ Nx
์ ์ธ์๋์ด ์๋ก์ด ๋ถ๋์ ํด์ ํ lerna
, Vercel
์ turborepo
๋ฑ์ ๋๊ตฌ๋ค์ด ๊ทธ ์์ด๋ค.์ด๋ฒ ์ถํ์์ ๊ต๋ฆฌ ๋ด์ฉ์ ์ด์ค์์ ๊ฐ์ฅ ์ฝ๊ณ ๊ฐ๋จํ๊ฒ monorepo ๊ฐ๋ ์ ๋ฌ์ฑํ ์ ์๋
pnpm workspace
์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค.์ฐธ๊ณ ๋งํฌ: https://monorepo.tools/
์ ์ ์กฐ๊ฑด
pnpm ์ค์น๊ฐ ํ์ํ๋ค.
๋จ๋ง๊ธฐ
npm i -g pnpm
์์ํ๊ธฐ
ํ๋ก์ ํธ ํด๋๋ฅผ ๊ตฌ์ฑํ๋ monorepo ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค.
๋จ๋ง๊ธฐ
pnpm init
pnpm-workspace.yaml
ํ์ผ์ ์์ฑํ๊ณ ๊ทผ์ ํ๊ฒ ์
๋ ฅpnpm-workspace.yaml
packages:
- 'packages/*'
package.json
์ ๋ค์๊ณผ ํจ๊ป ์
๋ ฅํ์ธ์.pnpm์ ๋ฒ์ ์ ์ต์ ๋ฒ์ ์ผ๋ก ์์ฒญํ๋ฉด ๋ฉ๋๋ค.
(2022/08/08 ๊ธฐ์ค 7.9.0)
ํจํค์ง.json
{
"name": "@soom/root",
"private": true,
"scripts": {
"preinstall": "pnpm dlx only-allow pnpm"
},
"workspaces": ["packages/*"],
"engines": {
"node": ">=16.14.2",
"pnpm": ">=7.9.0"
},
"packageManager": "pnpm@7.9.0",
"devDependencies": {
"pnpm": "^7.9.0"
}
}
package.json
๊ธฐ๋ฐ์ผ๋ก ์ค์น๋จ๋ง๊ธฐ
pnpm install
packages
ํด๋๋ฅผ ๋ง๋ค๊ธฐ common
, app
ํด๋๋ฅผ ์์ฑ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
.
โโโ packages/
โ โโโ app
โ โโโ common
โโโ package.json
โโโ pnpm-lock.yaml
โโโ pnpm-workspace.yaml
common
, app
๊ฐ๊ฐ์ ํด๋์์ ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค.์๋
vite
๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก์ ํธ ์์ฑreact-ts ํ์์ ์ด์ฉํ์๋ค.
๋จ๋ง๊ธฐ
pnpm create vite
โ Select a framework: โบ react
โ Select a variant: โบ react-ts
๊ฐ ํด๋์์ ํ๋ก์ ํธ๊ฐ ์๋ํ๋์ง ํ์ธ
์์ฌ

common
ํ๋ก์ ํธ์ ๊ฐ๋จํ ๋ฒํผ์ ์์ฑํจํค์ง/common/src/components/Button.tsx
import type { FC, PropsWithChildren } from 'react';
interface Props extends PropsWithChildren {
textColor: string;
}
const Button: FC<Props> = (props) => {
return <button style={{ color: props.textColor }}>{props.children}</button>;
};
export default Button;
main.tsx
, package.json
์ ๋ค์๊ณผ ํจ๊ป ์์ ํจํค์ง/common/src/main.tsx
import Button from './components/Button';
export { Button };
ํจํค์ง/๊ณตํต/package.json
{
"name": "@soom/common",
"private": true,
"version": "0.0.0",
"type": "module",
"main": "./src/main.tsx",
...
}
app
ํด๋๋ก ์ด๋ package.json
์ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ๊ณ pnpm install
์ ํตํด ์ค์นํ๋ค.์ฌ๊ธฐ
@soom/common
ํจํค์ง๋common
ํด๋์ ํ๋ก์ ํธ ์ด๋ฆ์ด๋ค.ํจํค์ง/์ฑ/package.json
{
"name": "@soom/app",
...
"dependencies": {
"@soom/common": "^0.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
...
}
๋จ๋ง๊ธฐ
pnpm install
dependencies:
+ @soom/common 0.0.0 <- ../common
App.tsx
์์ ์ค์นํ @soom/common
ํจํค์ง์์ ๋ฒํผ์ ๋ถ๋ฌ์ต๋๋ค.props
๋ ์ ์์๋ ๊ฑธ ํ์ธํ ์ ์๋ค.ํจํค์ง/์ฑ/src/App.tsx
import './App.css';
import { Button } from '@soom/common';
function App() {
return (
<div className='App'>
<h1>Monorepo Button?</h1>
<Button textColor='red'>Hello Common Package Button</Button>
</div>
);
}
export default App;
์์ฌ

โ ์ถ์
๋ง์ง๋ง์ผ๋ก monorepo๋ฅผ ํด๋์์ ์ง์
app
ํด๋์ ์ ๊ทผํ์ง ๋ชปํ๊ฒ ํ๊ธฐ ์ํด package.json
์ ๋ค์๊ณผ ๊ฐ์ด ํผ์ณ์ง ์ ์์ต๋๋ค.ํจํค์ง.json
{
"name": "@soom/root",
...
"scripts": {
"preinstall": "pnpm dlx only-allow pnpm",
"dev:app": "pnpm --filter @soom/app dev"
},
...
}
๋จ๋ง๊ธฐ
pnpm dev:app
โโ Stackblitz ์ํ
๊ฒฐ๋ก
pnpm workspace
๋ฅผ ์ด์ฉํ์ฌ monorepo๋ฅผ ๊ตฌ์ฑํด์์ต๋๋ค.์ด ํ๋ก์ ํธ์
turborepo
, lerna
๋ฑ์ ์ฌ๋ฌ ๊ฐ์ง๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค.monorepo๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ถ์ด ๋ฒ์ฉ ๋ฒ์ฉํ์ฌ
pnpm workspace
๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ๊ฐ์ฅ ์ทจ์๋ ๊ฒ์
๋๋ค.pnpm์ ์์ธํ ๋ด์ฉ์ ๋งํฌ๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
https://pnpm.io/ko/
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(pnpm Workspace๋ก Monorepo ๋ง๋ค๊ธฐ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://dev.to/soom/building-a-monorepo-with-pnpm-workspace-1544ํ ์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค