Monorepo์ ๋ํด ํ์ตํ ๋ด์ฉ์ ์ ๋ฆฌํ ๊ธ์ด๋ค.
๐ฆ Monorepo?
์ฌ๋ฌ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ค ๋ณด๋ฉด ๋์ผํ ๋ชจ๋์ ๋ค๋ฅธ ํ๋ก์ ํธ์๋ ๊ฐ์ด ์ฌ์ฉํด์ผ ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธด๋ค. ์๋ฅผ ๋ค์ด backend์์ admin ๊ณผ ์ค์ ์๋น์ค ํ๋ก์ ํธ ๊ฐ์ ๋ชจ๋ธ, ๋๋ฉ์ธ ๋น์ง๋์ค ๋ก์ง์ ๋ํ ์ฝ๋๋ ํน์ react์ react-native ์ฌ์ด์ ์ปดํฌ๋ํธ ๊ณต์ ๋ฑ ์ฌ๋ฌ๊ฐ์ง ์ผ์ด์ค๊ฐ ์์ ์ ์๋ค. ์ด๋ ๊ฒ ๋ชจ๋์ ๊ณต์ ํด์ผ๋๋ ์ํฉ์์ ์ค๋ณต๋๋ ๋ชจ๋๋ง๋ค ๋ฆฌํฌ์งํ ๋ฆฌ ๋ถ๋ฆฌํด์ ํจํค์ง ๋งค๋์ ์ ๋ฑ๋กํ๊ณ ์ฌ์ฉํ๊ฒ ๋๋ฉด ๊ฐ๋ฐ, ํ ์คํธ, ๋ฐฐํฌ ์ ์์ด์ ๊ด๋ฆฌํ๊ธฐ๊ฐ ์ด๋ ค์์ง๋ค. ๋ชจ๋ ธ๋ฆฌํฌ๋ ํ๋์ ๋ฆฌํฌ์งํ ๋ฆฌ์ ์ฌ๋ฌ ํจํค์ง๋ค์ ๋๋ ๊ตฌ์กฐ์ด๋ค.
Monorepo ์ฅ์
- test, build, release ํ๋ก์ธ์ค๋ฅผ ํ ๋ฒ์ ์งํํ ์ ์๋ค.
- ํ๋์ ์ ์ฅ์์์ issue๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค.
- ๋ชจ๋๋ณ๋ก ๊ฐ๋ณ์ ์ธ ๋ฒ์ ๊ด๋ฆฌ
- ํจํค์ง ๋งค๋์ ์ ๋ฑ๋กํ์ง ์๊ณ ๋ ์ฝ๋๋ฅผ ๊ณต์ ํ๊ธฐ ์ฌ์์ง๋ค.
Monorepo ๋จ์
- ๋ฌ๋์ปค๋ธ ์ ์ด๊ธฐ์ ํ
- ์ปค์ง ๋ฆฌํฌ์งํ ๋ฆฌ ์ฌ์ด์ฆ?
์ด๊ฒ ๋ง๊ณ ๋ ๋ชจ๋ ธ๋ฆฌํฌ๋ก ๊ตฌ์ฑํด์ ์ข ๋ ๋ฒ๊ฑฐ๋ก์ ์ง๋ ๋ถ๋ถ๋ค๋ ์๊ฒ ์ง๋ง ์ข ๋ ์ฌ์ฉํด๋ด์ผ ํ ๊ฒ ๊ฐ๋ค.
Monorepo๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ
๋ชจ๋ ธ๋ฆฌํฌ๋ ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ ํ์์ด๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ๊ฐ์ง ๋๊ตฌ๋ฅผ ํตํด์ ๊ตฌ์ฑํ ์ ์๋ค. ๋ณ๋ค๋ฅธ ๋๊ตฌ ์์ด๋ ํ๋์ ๋ฆฌํฌ์์ ํด๋๋ฅผ ๊ตฌ๋ถํ๊ณ node_module๊ฐ์ ์ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ํตํด์ ๊ตฌํํ ์ ์๊ฒ ์ง๋ง ๋งค๋ฒ ๋งํฌ๋ฅผ ๊ฑฐ๋ ๋ฐฉ๋ฒ์ ๋นํจ์จ์ ์ด๊ณ ๋ฒ๊ฑฐ๋กญ๋ค. ์ฌ๊ธฐ์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ธ Yarn workspace ์ Lerna ์ ๋ํด ๊ฐ๋จํ ์๊ฐํด๋ณด๋ ค๊ณ ํ๋ค.
Yarn workspace
yarn workspace๋ ํจํค์ง ์ํคํ
์ณ๋ฅผ ์ค์ ํ๋ ์๋ก์ด ๋ฐฉ๋ฒ์ด๊ณ ๊ธฐ๋ณธ์ ์ผ๋ก 1.0๋ฒ์ ๋ถํฐ ์ฌ์ฉํ ์ ์๋ค๊ณ ํ๋ค. yarn workspace๋ฅผ ์ด์ฉํ๋ฉด ์ข ๋ ์ฝ๊ฒ ๋ชจ๋
ธ๋ฆฌํฌ ์์ ์ฌ๋ฌ ํจํค์ง๋ค์ ์์กด์ฑ์ ๊ด๋ฆฌํ ์ ์๋ค. root ํด๋์ ํจํค์ง๋ค๋ก ๊ตฌ์ฑํ ์ ์๋๋ฐ ๋ชจ๋ ํจํค์ง๋ค์ ๋ํ ์์กด์ฑ์ ํ๋ฒ์ yarn install
๋ก ์ฒ๋ฆฌํ ์ ์๋ค. ๋ํ ๋ชจ๋์ hoist
๋์ด์ root ํด๋์ node_modules ํด๋์ ์ค์น๋๋ค. ๋ฌผ๋ก ๊ณตํต๋ ๋ชจ๋์ธ๋ฐ ๋ฒ์ ๋ง ๋ค๋ฅผ ๊ฒฝ์ฐ์ ํด๋น ํจํค์ง node_modules์ ์ค์น๋๋ค.
์๋ ํํ ๋ฆฌ์ผ์ ๋ฐ๋ผํด๋ณด๋ฉด ์ด๋ค์์ผ๋ก ๋์ํ๋์ง ์ข ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋ค.
Repo Structure
๊ตฌ์ฑํด๋ณด๋ ค๊ณ ํ๋ ๋ชจ๋
ธ๋ฆฌํฌ์ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค. ๋ณดํต packages
๋ผ๋ ํด๋ ์๋ ํจํค์ง๋ค์ ๋ชจ์์ ๊ด๋ฆฌํ์ง๋ง ๋ค๋ฅธ์ด๋ฆ์ผ๋ก ๋ฐ๊ฟ๋ ๋ฌด๊ดํ๋ค.
1 | โโโ package.json |
root package.json
์์ฑ
root directory๋ ํจํค์ง๋ก ๋ฐฐํฌ๋ ๋ฆฌ ์๊ธฐ ๋๋ฌธ์ private์ผ๋ก ์ค์ ํ๊ณ workspaces์๋ ํจํค์ง ํด๋๋ช ์ ๋ฐฐ์ด๋ก ๋๊ธธ ์ ์๋ค. ํจํด๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
yarn init
ํ ์๋ property๋ฅผ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
1 | { |
ํจํค์ง๋ณ package.json
์์ฑ
1 | cd packages/shared && yarn init -y |
ํจํค์ง๋ช ๋ณ๊ฒฝ
package.json
์ด ์๊ฒผ์ง๋ง npm ์์ ๋ฐ๋ก ์ค์นํ ๋ชจ๋๊ณผ ๊ตฌ๋ถํด์ฃผ๊ธฐ ์ํด์ ์์ prefix
๋ฅผ ๋ถ์ฌ์ฃผ๋ ๊ฒ์ด ์ข๋ค. ์ฌ๊ธฐ์ ์์๋ก @project๋ก ์ค์ ํ์๋ค.
1 | { |
yarn install
root ํด๋๋ก ์ด๋ํ yarn install ์ ํ๋ฉด node_modules์ ํจํค์ง๋ค์ด ์ฌ๋ณผ๋ฆญ ๋งํฌ๊ฐ ์๋์ผ๋ก ๊ฑธ๋ ค์๋ค. ์ด๊ฑธํตํด์ ํจํค์ง๊ฐ์ ๋ชจ๋ ์ํธ์ฐธ์กฐ๊ฐ ๊ฐ๋ฅํด์ง๋ค.
1 | โโโ @project |
๊ฐ๋จํ ์ฝ๋ ์์ฑ
shared ํจํค์ง์ ์ด๋คํจ์๋ฅผ ์ถ๊ฐํ๊ณ serverํจํค์ง์์ shared๋ชจ๋์ ์ฐธ์กฐํด์ ์ฌ์ฉํ๋ ์์์ด๋ค.
packages/shared/index.js
1 | module.exports = () => { |
shared ๋ชจ๋์ ๋ก๋ฉํ๊ธฐ์ ์ serverํจํค์ง์ shared๋ฅผ ์์กด์ฑ์ผ๋ก ์ถ๊ฐํด์ฃผ์ด์ผ ํ๋ค.
(์๋์ผ๋ก ์ถ๊ฐํด๋ ๋ฌด๋ฐฉํ๋ค.)
1 | yarn workspace @project/server add @project/shared@1.0.0 |
packages/server/index.js
1 | const sharedFunc = require('@project/shared'); |
server/index.js
์คํ
1 | node packages/server/index |
npm ๋ชจ๋ ์ถ๊ฐ (hoist)
packages/server/package.json
1 | "dependencies": { |
packages/web/package.json
,packages/shared/package.json
1 | "dependencies": { |
๋ชจ๋์ ๋ค์๊ณผ ๊ฐ์ด ์ถ๊ฐํ ํ root์์ yarn install
์ ํ๋ฉด ํจํค์ง๋ณ๋ก ๊ณตํต๋ ๋ชจ๋์ ๊ฐ์ ๋ฒ์ ์ด๋ผ๋ฉด hoist
๋์ด์ root ํด๋์ node_modules์ ์ค์น๋๋ค. ๋ฒ์ ์ด ๋ค๋ฅด๋ค๋ฉด ํจํค์ง์๋ node_modules๊ฐ ์ฌ์ฉ๋ ๊ฒ์ด๋ค. ๋ง์ฝ hosit๋ฅผ ๊ธฐ๋ฅ์ผ๋ก ์ธํด ๊ฒฝ๋ก์์ ๋ฌธ์ ๋ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค๋ฉด nohoist
์ต์
์ ์ฌ์ฉํ ์ ์๋ค. ์ด์ ๋ํ ์์ธํ ์ค๋ช
์ ์๋ ์ฐธ์กฐ ๋งํฌ๋ฅผ ๋จ๊ฒจ๋์๋ค.
Lerna
Lerna๋ ๋ชจ๋ ธ๋ฆฌํฌ์ workflow๋ฅผ ์ต์ ํ ์์ผ์ฃผ๋ ํด์ด๋ค. ์ฌ๊ธฐ์ ๋งํ๋ workflow๋ test, build, versioning, publishing ๋ฑ๊ณผ ๊ฐ์ ํ๋๋ค์ ๋ปํ๋ค. ๋ฌผ๋ก ๋ชจ๋ ธ๋ฆฌํฌ์์ ์ฌ๋ฌ ํจํค์ง๊ฐ์ ์์กด์ฑ์ ๊ด๋ฆฌํด์ฃผ๋ ์ผ๋ ํ๊ณ ์๋ค. ๊ทธ๋ฌ๋ ์ต๊ทผ์๋ ์์กด์ฑ๊ด๋ฆฌ ์ ๊ฐ์ ๊ธฐ๋ฅ์ yarn workspace์ ์์ํ์ฌ ๊ฐ์ด ์ฌ์ฉํ๋ ์ถ์ธ์ธ ๊ฒ ๊ฐ๋ค.
์ด ๊ธ์์ yarn workspace์ ๊ฐ์ด ์ฌ์ฉํ๋ ํํ ๋ฆฌ์ผ์ ๋ง๋ค์ด๋ณด์๋ค.
์์์ ๊ตฌ์ฑํด๋์ yarn workspace์ lerna๋ฅผ ์ถ๊ฐํ๋ค.
lerna๋ root์ ์ค์นํด์ผํ๋ฏ๋ก -W
์ต์
์ ๋ถ์ฌ์ ์ถ๊ฐํ ์ ์๋ค.
1 | yarn add -W -D lerna |
lerna ์ค์ ํ์ผ์ ๋ง๋ค์ด์ค๋ค.
1 | npx lerna init |
yarn workspace์ ๊ฐ์ด ์ฌ์ฉํ๊ธฐ ์ํด lerna.json
ํ์ผ์ ์์ ํ๋ค.
1 | { |
๋ชจ๋ ํจํค์ง์ test scripts๋ฅผ ์ถ๊ฐํ๋ค.
ํด๋น ์คํฌ๋ฆฝํธ๋ ๋จ์ํ ์ฝ์์ ํจํค์ง๋ช ์ ์ถ๋ ฅํด์ค๋ค.
1 | "scripts": { |
lerna run
command๋ฅผ ํตํด์ ํจํค์ง์ script๋ฅผ ์คํ์ํจ๋ค.
1 | npx lerna run test |
์ถ๋ ฅ๊ฒฐ๊ณผ
1 | test @project/web |
โscope
์ต์
์ ํตํด์ ํน์ ํจํค์ง๋ง ์คํํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
1 | npx lerna run test --scope={@project/web,@project/server} |
lerna ์๋ run๋ง๊ณ ๋ ์ ์ฉํ command๊ฐ ๋ง์ด ์กด์ฌํ๋ค.
์๋์๋ ๊ฐ๋จํ ์ฃผ์๋ช ๋ น์ด์ ๋ํด ์ ๋ฆฌํด๋ณด์๋ค.
lerna bootstrap
- ํจํค์ง๋ค์ ์์กด์ฑ์ ์ค์นํ๋ค. yarn workspace๋ฅผ ์ฌ์ฉ์ค์ด๋ผ๋ฉด yarn์ ์์ํ๋ค.lerna clean
- ํจํค์ง์ node_modules ํด๋๋ฅผ ๋ชจ๋ ์ญ์ ํ๋ค.lerna run
- ํจํค์ง์ ํน์ scripts๋ฅผ ์คํํ ์ ์๋ค.lerna exec
- ํจํค์ง ๊ฒฝ๋ก์์ ํน์ command๋ฅผ ์คํํ ์ ์๋ค.lerna version
- ํจํค์ง๋ณ๋ก ๋ณ๊ฒฝ๋ ํจํค์ง๋ง version bump
์์ธํ ์ต์ ์ด๋ ์ฌ์ฉ์์๋ lerna github page์ ์ฐธ๊ณ ํ๋๋ก ํ์.
๋ง๋ฌด๋ฆฌ
ํ๋ก์ ํธ๋ฅผ ํ๋ค๋ณด๋ฉด โ์ด ๋ชจ๋์ ๋ค๋ฅธ๊ณณ์์๋ ์ฐ์ผ ๊ฒ ๊ฐ์๋ฐ?โ ์ด๋ ๊ฒ ์๊ฐํด๋ณธ๊ฒ ๋ง์ด ์์๋ ๊ฒ ๊ฐ๋ค.
์งํํ๋ reactํ๋ก์ ํธ ์ค ์ฌ๋ฌ ํ๋ก์ ํธ์์ ๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ๋ UI๋ค์ storybook๊ณผ ํจ๊ป component ๋ชจ์์ ๋ง๋ค์ด๋๊ณ ์ฌ์ฉํ ์ ์ด ์๋ค. ํ์ง๋ง ํ๋ก์ ํธ ๋ฆฌํฌ์งํ ๋ฆฌ๊ฐ ๋ถ๋ฆฌ๋์ด ์์๊ณ ๊ฐ์ด ์ฌ์ฉํ๊ธฐ ์ํด์ npm git repository๋ฅผ ์ด์ฉํ๊ฑฐ๋ git submodule์ ์ ํํด์ผํ๋๋ฐ ๊ฐ๋ฐ์ ์ํด์ ํ๋ก์ ํธ๋ฅผ ์ฌ๋ฌ๊ฐ ๋์์ผํ๊ณ ์กฐ๊ทธ๋ง ๋ณ๊ฒฝ์๋ ๋ฒ์ ์ ์ฌ๋ฆฌ๊ณ ๋ค์ ๋ฐ์์ผ๋์ ๋ฒ๊ฑฐ๋ก์ ๋ ๊ฒฝํ์ด ์๋ค. ๋ง์ฝ ๋ชจ๋
ธ๋ฆฌํฌ๋ก ๊ตฌ์ฑ๋์ด์๋ค๋ฉด ์ข ๋ ๋์ ๋ฐฉ๋ฒ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ง ์์์๊น ํ๋ ์๊ฐ์ด ๋ ๋ค.
๋ชจ๋
ธ๋ฆฌํฌ๊ฐ ๋ฉํฐ๋ฆฌํฌ๋ณด๋ค ๋ฌด์กฐ๊ฑด ์ข๋ค๊ณ ์๊ฐํ์ง ์๋๋ค. ๋ค๋ง ํ๋ก์ ํธ๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ๋ ์ฌ๋ฌ๊ฐ์ง ์์๋๋ฉด ์ํฉ์ ๋ง์ถฐ์ ์ข์ ๊ตฌ์กฐ๋ฅผ ์ ํํ ์ ์์๊ฒ ๊ฐ๋ค.