Nx μν¬μ€νμ΄μ€λ₯Ό νμ©νμ¬ νλ‘ νΈμλ monorepo κ°λ°μ λ°°μ°κ³ , ν λ° νλ‘μ νΈ μ λ°μμ μ½λ 곡μ , λΉλ μ±λ₯, κ°λ°μ νμ μ κ°μ νμΈμ.
Frontend Nx Workspace: νμ₯ κ°λ₯ν μ ν리μΌμ΄μ μ μν Monorepo κ°λ°
μ€λλ λΉ λ₯΄κ² λ³ννλ μννΈμ¨μ΄ κ°λ° νκ²½μμ λκ·λͺ¨ νλ‘ νΈμλ μ ν리μΌμ΄μ μ ꡬμΆνκ³ μ μ§ κ΄λ¦¬νλ κ²μ μ΄λ €μΈ μ μμ΅λλ€. νλ‘μ νΈκ° 컀μ§μ λ°λΌ μ’ μμ± κ΄λ¦¬, μ½λ μΌκ΄μ± 보μ₯, λΉλ μκ° μ΅μ νκ° μ μ λ 볡μ‘ν΄μ§λλ€. Monorepoλ μ¬λ¬ νλ‘μ νΈμ λΌμ΄λΈλ¬λ¦¬λ₯Ό λ¨μΌ 리ν¬μ§ν 리μ ν΅ν©νμ¬ κ°λ ₯ν μ루μ μ μ 곡ν©λλ€. μ€λ§νΈνκ³ νμ₯ κ°λ₯ν λΉλ μμ€ν μΈ Nxλ κ³ κΈ λꡬμ κΈ°λ₯μ ν΅ν΄ monorepo κ°λ°μ ν₯μμν΅λλ€.
μ΄ ν¬κ΄μ μΈ κ°μ΄λμμλ νλ‘ νΈμλ monorepo κ°λ°μ μν΄ Nx μν¬μ€νμ΄μ€λ₯Ό μ¬μ©νλ μ΄μ μ μ΄ν΄λ³΄κ³ , ν΅μ¬ κ°λ , μ€μ μμ, λͺ¨λ² μ¬λ‘λ₯Ό λ€λ£Ήλλ€.
Monorepoλ 무μμΈκ°μ?
Monorepoλ λͺ¨λ νλ‘μ νΈμ ν΄λΉ μ’ μμ±μ λ¨μΌ 리ν¬μ§ν 리μ μ μ₯νλ μννΈμ¨μ΄ κ°λ° μ λ΅μ λλ€. μ΄ μ κ·Ό λ°©μμ κ° νλ‘μ νΈκ° μ체 리ν¬μ§ν 리λ₯Ό κ°λ κΈ°μ‘΄μ multi-repo μ κ·Ό λ°©μκ³Ό λμ‘°λ©λλ€.
Monorepoμ μ£Όμ νΉμ§:
- λ¨μΌ μ§μ€ μμ€: λͺ¨λ μ½λκ° ν κ³³μ μμ΅λλ€.
- μ½λ 곡μ λ° μ¬μ¬μ©: νλ‘μ νΈ κ°μ μ½λλ₯Ό λ μ½κ² 곡μ νκ³ μ¬μ¬μ©ν μ μμ΅λλ€.
- κ°μνλ μ’ μμ± κ΄λ¦¬: νλ‘μ νΈ κ°μ μ’ μμ± κ΄λ¦¬κ° λ κ°λ¨ν΄μ§λλ€.
- μμμ λ³κ²½ μ¬ν: μ¬λ¬ νλ‘μ νΈμ κ±Έμ³ λ³κ²½ μ¬νμ μ μ©νμ¬ μΌκ΄μ±μ 보μ₯ν μ μμ΅λλ€.
- κ°μ λ νμ : νμ΄ κ΄λ ¨ νλ‘μ νΈμμ λ μ½κ² νμ ν μ μμ΅λλ€.
νλ‘ νΈμλ κ°λ°μ Monorepoλ₯Ό μ¬μ©νλ μ΄μ λ 무μμΈκ°μ?
Monorepoλ νλ‘ νΈμλ κ°λ°, νΉν ν¬κ³ 볡μ‘ν νλ‘μ νΈμ μλΉν μ΄μ μ μ 곡ν©λλ€.
- ν₯μλ μ½λ 곡μ : νλ‘ νΈμλ νλ‘μ νΈλ μ’ μ’ κ³΅ν΅ UI κ΅¬μ± μμ, μ νΈλ¦¬ν° ν¨μ λ° λμμΈ μμ€ν μ 곡μ ν©λλ€. Monorepoλ μ½λ 곡μ λ₯Ό μ©μ΄νκ² νμ¬ μ€λ³΅μ μ€μ΄κ³ μΌκ΄μ±μ λμ λλ€. μλ₯Ό λ€μ΄, λμμΈ μμ€ν λΌμ΄λΈλ¬λ¦¬λ λμΌν μν¬μ€νμ΄μ€ λ΄μ μ¬λ¬ React μ ν리μΌμ΄μ κ°μ μ½κ² 곡μ ν μ μμ΅λλ€.
- κ°μνλ μ’ μμ± κ΄λ¦¬: μ¬λ¬ νλ‘ νΈμλ νλ‘μ νΈμμ μ’ μμ±μ κ΄λ¦¬νλ κ²μ νΉν λμμμ΄ μ§ννλ JavaScript μνκ³μμ μ΄λ €μΈ μ μμ΅λλ€. Monorepoλ μ’ μμ±μ μ€μ μ§μ€ννκ³ λ²μ λ° μ κ·Έλ μ΄λλ₯Ό κ΄λ¦¬νκΈ° μν λꡬλ₯Ό μ 곡νμ¬ μ’ μμ± κ΄λ¦¬λ₯Ό λ¨μνν©λλ€.
- ν₯μλ λΉλ μ±λ₯: Nxλ κ³ κΈ λΉλ μΊμ± λ° μ’ μμ± λΆμμ μ 곡νμ¬ λ λΉ λ₯΄κ³ ν¨μ¨μ μΈ λΉλλ₯Ό κ°λ₯νκ² ν©λλ€. μ’ μμ± κ·Έλνλ₯Ό λΆμνμ¬ Nxλ λ³κ²½ μ¬νμ μν₯μ λ°λ νλ‘μ νΈλ§ λ€μ λΉλν μ μμΌλ―λ‘ λΉλ μκ°μ ν¬κ² μ€μΌ μ μμ΅λλ€. μ΄λ μλ§μ κ΅¬μ± μμμ λͺ¨λμ κ°μ§ λκ·λͺ¨ νλ‘ νΈμλ μ ν리μΌμ΄μ μ λ§€μ° μ€μν©λλ€.
- κ°μνλ 리ν©ν λ§: μ¬λ¬ νλ‘μ νΈμμ μ½λλ₯Ό 리ν©ν λ§νλ κ²μ΄ monorepoμμ λ μ½μ΅λλ€. λ³κ²½ μ¬νμ μμμ μΌλ‘ μ μ©νμ¬ μΌκ΄μ±μ 보μ₯νκ³ λ²κ·Έ λ°μ μνμ μ€μΌ μ μμ΅λλ€. μλ₯Ό λ€μ΄, μ¬λ¬ μ ν리μΌμ΄μ μμ μ¬μ©λλ κ΅¬μ± μμμ μ΄λ¦μ λ°κΎΈλ κ²μ λ¨μΌ 컀λ°μΌλ‘ μνν μ μμ΅λλ€.
- λ λμ νμ : Monorepoλ 곡μ μ½λλ² μ΄μ€μ κ³΅ν΅ κ°λ° νκ²½μ μ 곡νμ¬ νλ‘ νΈμλ κ°λ°μ κ°μ λ λμ νμ μ μ΄μ§ν©λλ€. νμ λ€μν νλ‘μ νΈμ μ½κ² κΈ°μ¬νκ³ μ§μκ³Ό λͺ¨λ² μ¬λ‘λ₯Ό 곡μ ν μ μμ΅λλ€.
Nx μκ°: μ€λ§νΈνκ³ νμ₯ κ°λ₯ν λΉλ μμ€ν
Nxλ κ³ κΈ λꡬμ κΈ°λ₯μ ν΅ν΄ monorepo κ°λ°μ ν₯μμν€λ κ°λ ₯ν λΉλ μμ€ν μ λλ€. νμ€νλ κ°λ° νκ²½μ μ 곡νκ³ , λΉλ μ±λ₯μ ν₯μμν€λ©°, μ’ μμ± κ΄λ¦¬λ₯Ό λ¨μνν©λλ€.
Nxμ μ£Όμ κΈ°λ₯:
- μ€λ§νΈ λΉλ μμ€ν : Nxλ νλ‘μ νΈμ μ’ μμ± κ·Έλνλ₯Ό λΆμνκ³ μν₯μ λ°λ νλ‘μ νΈλ§ λ€μ λΉλνμ¬ λΉλ μκ°μ ν¬κ² μ€μ λλ€.
- μ½λ μμ±: Nxλ μλ‘μ΄ νλ‘μ νΈ, κ΅¬μ± μμ λ° λͺ¨λμ μμ±νκΈ° μν μ½λ μμ± λꡬλ₯Ό μ 곡νμ¬ κ°λ° μλλ₯Ό λμ΄κ³ μΌκ΄μ±μ 보μ₯ν©λλ€.
- ν΅ν©λ λꡬ: Nxλ React, Angular, Vue.jsμ κ°μ μΈκΈ° μλ νλ‘ νΈμλ νλ μμν¬μ ν΅ν©λμ΄ μνν κ°λ° νκ²½μ μ 곡ν©λλ€.
- νλ¬κ·ΈμΈ μνκ³: Nxλ μΆκ° λꡬ λ° ν΅ν© κΈ°λ₯μ ν΅ν΄ κΈ°λ₯μ νμ₯νλ νλΆν νλ¬κ·ΈμΈ μνκ³λ₯Ό κ°μΆκ³ μμ΅λλ€.
- μ μ§μ λΉλ: Nxμ μ μ§μ λΉλ μμ€ν μ λ³κ²½λ λ΄μ©λ§ λ€μ λΉλνμ¬ κ°λ° νΌλλ°± 루νλ₯Ό ν¬κ² κ°μνν©λλ€.
- κ³μ° μΊμ±: Nxλ λΉλ λ° ν μ€νΈμ κ°μ λΉμ©μ΄ λ§μ΄ λλ κ³μ° κ²°κ³Όλ₯Ό μΊμ±νμ¬ μ±λ₯μ λμ± ν₯μμν΅λλ€.
- λΆμ° μμ μ€ν: λ§€μ° ν° monorepoμ κ²½μ° Nxλ μ¬λ¬ λ¨Έμ μμ μμ μ λΆμ°νμ¬ λΉλ λ° ν μ€νΈλ₯Ό λ³λ ¬νν μ μμ΅λλ€.
νλ‘ νΈμλ κ°λ°μ μν Nx μν¬μ€νμ΄μ€ μ€μ
Nx μν¬μ€νμ΄μ€λ₯Ό μ€μ νλ κ²μ κ°λ¨ν©λλ€. Nx CLIλ₯Ό μ¬μ©νμ¬ μ μν¬μ€νμ΄μ€λ₯Ό λ§λ€κ³ νλ‘μ νΈμ λΌμ΄λΈλ¬λ¦¬λ₯Ό μΆκ°ν μ μμ΅λλ€.
μ¬μ μꡬ μ¬ν:
- Node.js (λ²μ 16 μ΄μ)
- npm λλ yarn
λ¨κ³:
- Nx CLI μ€μΉ:
npm install -g create-nx-workspace
- μ Nx μν¬μ€νμ΄μ€ μμ±:
npx create-nx-workspace my-frontend-workspace
ν리μ μ μ ννλΌλ λ©μμ§κ° νμλ©λλ€. μ νΈνλ νλ‘ νΈμλ νλ μμν¬(μ: React, Angular, Vue.js)μ μΌμΉνλ ν리μ μ μ ννμΈμ.
- μ μ ν리μΌμ΄μ
μΆκ°:
nx generate @nx/react:application my-app
μ΄ λͺ λ Ήμ μν¬μ€νμ΄μ€ λ΄μ "my-app"μ΄λΌλ μ React μ ν리μΌμ΄μ μ λ§λλλ€.
- μ λΌμ΄λΈλ¬λ¦¬ μΆκ°:
nx generate @nx/react:library my-library
μ΄ λͺ λ Ήμ μν¬μ€νμ΄μ€ λ΄μ "my-library"λΌλ μ React λΌμ΄λΈλ¬λ¦¬λ₯Ό λ§λλλ€. λΌμ΄λΈλ¬λ¦¬λ νλ‘μ νΈ κ°μ μ½λλ₯Ό 곡μ νλ λ° μ¬μ©λ©λλ€.
Nx μν¬μ€νμ΄μ€ ꡬμ±
μ ꡬμ±λ Nx μν¬μ€νμ΄μ€λ μ μ§ κ΄λ¦¬ μ©μ΄μ± λ° νμ₯μ±μ μν΄ λ§€μ° μ€μν©λλ€. μν¬μ€νμ΄μ€λ₯Ό ꡬμ±ν λ λ€μ μ§μΉ¨μ κ³ λ €νμΈμ.
- μ ν리μΌμ΄μ : μ ν리μΌμ΄μ μ νλ‘ νΈμλ νλ‘μ νΈμ μ§μ μ μ λλ€. μ¬μ©μ λλ©΄ μΈν°νμ΄μ€λ₯Ό λνλ λλ€. μΉ μ ν리μΌμ΄μ , λͺ¨λ°μΌ μ ν리μΌμ΄μ λλ λ°μ€ν¬ν± μ ν리μΌμ΄μ μ΄ κ·Έ μμ λλ€.
- λΌμ΄λΈλ¬λ¦¬: λΌμ΄λΈλ¬λ¦¬λ μ¬λ¬ μ ν리μΌμ΄μ κ°μ 곡μ ν μ μλ μ¬μ¬μ© κ°λ₯ν μ½λλ₯Ό ν¬ν¨ν©λλ€. κΈ°λ₯μ λ°λΌ λ€λ₯Έ μ νμΌλ‘ ꡬμ±λ©λλ€.
- κΈ°λ₯ λΌμ΄λΈλ¬λ¦¬: κΈ°λ₯ λΌμ΄λΈλ¬λ¦¬λ νΉμ κΈ°λ₯μ λν λΉμ¦λμ€ λ‘μ§ λ° UI κ΅¬μ± μμλ₯Ό ν¬ν¨ν©λλ€. μ½μ΄ λ° UI λΌμ΄λΈλ¬λ¦¬μ μ’ μλ©λλ€.
- UI λΌμ΄λΈλ¬λ¦¬: UI λΌμ΄λΈλ¬λ¦¬λ μ¬λ¬ κΈ°λ₯ λ° μ ν리μΌμ΄μ μμ μ¬μ©ν μ μλ μ¬μ¬μ© κ°λ₯ν UI κ΅¬μ± μμλ₯Ό ν¬ν¨ν©λλ€.
- μ½μ΄ λΌμ΄λΈλ¬λ¦¬: μ½μ΄ λΌμ΄λΈλ¬λ¦¬λ μν¬μ€νμ΄μ€ μ 체μμ μ¬μ©λλ μ νΈλ¦¬ν° ν¨μ, λ°μ΄ν° λͺ¨λΈ λ° κΈ°ν κ³΅ν΅ μ½λλ₯Ό ν¬ν¨ν©λλ€.
- 곡μ λΌμ΄λΈλ¬λ¦¬: 곡μ λΌμ΄λΈλ¬λ¦¬λ νλ μμν¬μ λ 립μ μΈ μ½λλ₯Ό ν¬ν¨νμ¬ νλ‘ νΈμλ νλ μμν¬(React, Angular, Vue.js)μ κ΄κ³μμ΄ μ¬λ¬ μ ν리μΌμ΄μ λ° λΌμ΄λΈλ¬λ¦¬μμ μ¬μ©ν μ μμ΅λλ€. μ΄λ κ² νλ©΄ μ½λ μ¬μ¬μ©μ μ΄μ§νκ³ μ€λ³΅μ μ€μΌ μ μμ΅λλ€.
μμ λλ ν 리 ꡬ쑰:
my-frontend-workspace/ βββ apps/ β βββ my-app/ β β βββ src/ β β β βββ app/ β β β β βββ app.tsx β β β β βββ app.module.css β β β βββ main.tsx β β βββ project.json β βββ my-other-app/ β βββ ... βββ libs/ β βββ feature-my-feature/ β β βββ src/ β β β βββ lib/ β β β βββ feature-my-feature.tsx β β βββ project.json β βββ ui/ β β βββ src/ β β β βββ lib/ β β β βββ button/ β β β βββ button.tsx β β βββ project.json β βββ core/ β β βββ src/ β β β βββ lib/ β β β βββ api.ts β β βββ project.json β βββ shared/ β βββ src/ β β βββ lib/ β β βββ date-formatter.ts β βββ project.json βββ tools/ β βββ generators/ βββ nx.json βββ package.json βββ tsconfig.base.json
Nx λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©ν μ½λ 곡μ λ° μ¬μ¬μ©
Nx λΌμ΄λΈλ¬λ¦¬λ monorepoμμ μ½λ 곡μ λ° μ¬μ¬μ©μ ν΅μ¬μ λλ€. μ½λλ₯Ό μ μ μλ λΌμ΄λΈλ¬λ¦¬λ‘ ꡬμ±νλ©΄ μ¬λ¬ μ ν리μΌμ΄μ κ°μ κ΅¬μ± μμ, μλΉμ€ λ° μ νΈλ¦¬ν°λ₯Ό μ½κ² 곡μ ν μ μμ΅λλ€.
μμ: UI κ΅¬μ± μμ 곡μ
μ¬λ¬ React μ ν리μΌμ΄μ κ°μ 곡μ νλ €λ λ²νΌ κ΅¬μ± μμκ° μλ€κ³ κ°μ ν΄ λ³΄κ² μ΅λλ€. "ui"λΌλ UI λΌμ΄λΈλ¬λ¦¬λ₯Ό λ§λ€κ³ μ΄ λΌμ΄λΈλ¬λ¦¬μ λ²νΌ κ΅¬μ± μμλ₯Ό λ°°μΉν μ μμ΅λλ€.
- UI λΌμ΄λΈλ¬λ¦¬ μμ±:
nx generate @nx/react:library ui
- λ²νΌ κ΅¬μ± μμ μμ±:
nx generate @nx/react:component button --project=ui
- λ²νΌ κ΅¬μ± μμ ꡬν:
// libs/ui/src/lib/button/button.tsx import styles from './button.module.css'; interface ButtonProps { text: string; onClick: () => void; } export function Button({ text, onClick }: ButtonProps) { return ( ); } export default Button;
- λΌμ΄λΈλ¬λ¦¬μμ λ²νΌ κ΅¬μ± μμ λ΄λ³΄λ΄κΈ°:
// libs/ui/src/index.ts export * from './lib/button/button';
- μ ν리μΌμ΄μ
μμ λ²νΌ κ΅¬μ± μμ μ¬μ©:
// apps/my-app/src/app/app.tsx import { Button } from '@my-frontend-workspace/ui'; function App() { return (
Welcome to My App
λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νλ©΄ λͺ¨λ μ ν리μΌμ΄μ μμ UI κ΅¬μ± μμμ μΌκ΄μ±μ 보μ₯ν μ μμ΅λλ€. UI λΌμ΄λΈλ¬λ¦¬μμ λ²νΌ κ΅¬μ± μμλ₯Ό μ λ°μ΄νΈνλ©΄ ν΄λΉ κ΅¬μ± μμλ₯Ό μ¬μ©νλ λͺ¨λ μ ν리μΌμ΄μ μ΄ μλμΌλ‘ μ λ°μ΄νΈλ©λλ€.
Nx μν¬μ€νμ΄μ€μ μ’ μμ± κ΄λ¦¬
Nxλ νλ‘μ νΈ λ° λΌμ΄λΈλ¬λ¦¬ κ°μ μ’ μμ±μ κ΄λ¦¬νκΈ° μν κ°λ ₯ν λꡬλ₯Ό μ 곡ν©λλ€. κ° νλ‘μ νΈ λλ λΌμ΄λΈλ¬λ¦¬μ `project.json` νμΌμμ μ’ μμ±μ λͺ μμ μΌλ‘ μ μν μ μμ΅λλ€.
μμ: μ’ μμ± μ μΈ
μ ν리μΌμ΄μ "my-app"μ΄ λΌμ΄λΈλ¬λ¦¬ "core"μ μ’ μλμ΄ μλ€κ³ κ°μ ν΄ λ³΄κ² μ΅λλ€. "my-app"μ `project.json` νμΌμμ μ΄ μ’ μμ±μ μ μΈν μ μμ΅λλ€.
// apps/my-app/project.json
{
"name": "my-app",
"projectType": "application",
...
"implicitDependencies": ["core"]
}
μ’ μμ±μ λͺ μμ μΌλ‘ μ μΈν¨μΌλ‘μ¨ Nxλ μν¬μ€νμ΄μ€μ μ’ μμ± κ·Έλνλ₯Ό λΆμνκ³ μ’ μμ±μ΄ λ³κ²½λ λ μν₯μ λ°λ νλ‘μ νΈλ§ λ€μ λΉλν μ μμ΅λλ€. μ΄λ κ² νλ©΄ λΉλ μ±λ₯μ΄ ν¬κ² ν₯μλ©λλ€.
Nxλ₯Ό μ¬μ©ν λΉλ μ±λ₯ μ΅μ ν
Nxμ μ€λ§νΈ λΉλ μμ€ν κ³Ό κ³μ° μΊμ± κΈ°λ₯μ λΉλ μ±λ₯μ ν¬κ² ν₯μμν΅λλ€. Nx μν¬μ€νμ΄μ€μμ λΉλ μ±λ₯μ μ΅μ ννκΈ° μν λͺ κ°μ§ νμ΄ μμ΅λλ€.
- μ’ μμ± κ·Έλν λΆμ: `nx graph` λͺ λ Ήμ μ¬μ©νμ¬ μν¬μ€νμ΄μ€μ μ’ μμ± κ·Έλνλ₯Ό μκ°νν©λλ€. μ μ¬μ λ³λͺ© νμμ μλ³νκ³ μ’ μμ±μ μ€μ΄κΈ° μν΄ νλ‘μ νΈ κ΅¬μ‘°λ₯Ό μ΅μ νν©λλ€.
- κ³μ° μΊμ± μ¬μ©: Nxλ λΉλ λ° ν μ€νΈμ κ°μ λΉμ©μ΄ λ§μ΄ λλ κ³μ° κ²°κ³Όλ₯Ό μΊμ±ν©λλ€. `nx.json` νμΌμμ κ³μ° μΊμ±μ΄ νμ±νλμ΄ μλμ§ νμΈν©λλ€.
- μμ λ³λ ¬ μ€ν: Nxλ μ¬λ¬ CPU μ½μ΄λ₯Ό νμ©νκΈ° μν΄ μμ μ λ³λ ¬λ‘ μ€νν μ μμ΅λλ€. `--parallel` νλκ·Έλ₯Ό μ¬μ©νμ¬ μμ μ λ³λ ¬λ‘ μ€νν©λλ€.
- λΆμ° μμ μ€ν μ¬μ©: λ§€μ° ν° monorepoμ κ²½μ° Nxλ μ¬λ¬ λ¨Έμ μμ μμ μ λΆμ°νμ¬ λΉλ λ° ν μ€νΈλ₯Ό λ³λ ¬νν μ μμ΅λλ€.
- μ½λ μ΅μ ν: λΉλ μκ°μ μ€μ΄κΈ° μν΄ μ½λλ₯Ό μ΅μ νν©λλ€. μ¬μ©νμ§ μλ μ½λλ₯Ό μ κ±°νκ³ , μ΄λ―Έμ§λ₯Ό μ΅μ ννκ³ , μ½λ λΆν μ μ¬μ©νμ¬ λ²λ€ ν¬κΈ°λ₯Ό μ€μ λλ€.
Nx μν¬μ€νμ΄μ€μ ν μ€νΈ
Nxλ λ¨μ ν μ€νΈ, ν΅ν© ν μ€νΈ λ° μ’ λ¨ κ° ν μ€νΈλ₯Ό μ€ννκΈ° μν ν΅ν© ν μ€νΈ λꡬλ₯Ό μ 곡ν©λλ€. `nx test` λͺ λ Ήμ μ¬μ©νμ¬ μν¬μ€νμ΄μ€μ λͺ¨λ νλ‘μ νΈ λλ νΉμ νλ‘μ νΈμ λν ν μ€νΈλ₯Ό μ€νν μ μμ΅λλ€.
μμ: ν μ€νΈ μ€ν
nx test my-app
μ΄ λͺ λ Ήμ μ ν리μΌμ΄μ "my-app"μ λν λͺ¨λ ν μ€νΈλ₯Ό μ€νν©λλ€.
Nxλ Jest, Cypress λ° Playwrightμ κ°μ μΈκΈ° μλ ν μ€νΈ νλ μμν¬λ₯Ό μ§μν©λλ€. κ° νλ‘μ νΈμ `project.json` νμΌμμ ν μ€νΈ νκ²½μ ꡬμ±ν μ μμ΅λλ€.
Nxλ₯Ό μ¬μ©ν CI/CD(Continuous Integration and Continuous Deployment)
Nxλ GitHub Actions, GitLab CI, Jenkinsμ κ°μ μΈκΈ° μλ CI/CD μμ€ν κ³Ό μννκ² ν΅ν©λ©λλ€. Nxμ λͺ λ Ήμ€ μΈν°νμ΄μ€λ₯Ό μ¬μ©νμ¬ CI/CD νμ΄νλΌμΈμμ λΉλ, ν μ€νΈ λ° λ°°ν¬λ₯Ό μλνν μ μμ΅λλ€.
μμ: GitHub Actions μν¬νλ‘μ°
Nx μν¬μ€νμ΄μ€λ₯Ό λΉλ, ν μ€νΈ λ° λ°°ν¬νλ GitHub Actions μν¬νλ‘μ°μ μμ λλ€.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 16
cache: 'npm'
- run: npm ci
- run: npx nx affected --target=lint --base=origin/main --head=HEAD
- run: npx nx affected --target=test --base=origin/main --head=HEAD --watchAll=false
- run: npx nx affected --target=build --base=origin/main --head=HEAD
μ΄ μν¬νλ‘μ°λ λ€μ μμ μ μ€νν©λλ€.
- λ¦°ν : μν₯μ λ°λ νλ‘μ νΈμμ λ¦°ν°λ₯Ό μ€νν©λλ€.
- ν μ€νΈ: μν₯μ λ°λ νλ‘μ νΈμμ ν μ€νΈλ₯Ό μ€νν©λλ€.
- λΉλ: μν₯μ λ°λ νλ‘μ νΈλ₯Ό λΉλν©λλ€.
Nxλ λ³κ²½ μ¬νμ μν₯μ λ°λ νλ‘μ νΈμμλ§ μμ μ μ€νν μ μλ `affected` λͺ λ Ήμ μ 곡ν©λλ€. μ΄λ κ² νλ©΄ CI/CD νμ΄νλΌμΈμ μ€ν μκ°μ ν¬κ² μ€μΌ μ μμ΅λλ€.
νλ‘ νΈμλ Nx μν¬μ€νμ΄μ€ κ°λ°μ μν λͺ¨λ² μ¬λ‘
Nxλ‘ νλ‘ νΈμλ μ ν리μΌμ΄μ μ κ°λ°νκΈ° μν λͺ κ°μ§ λͺ¨λ² μ¬λ‘λ λ€μκ³Ό κ°μ΅λλ€.
- μΌκ΄λ μ½λ© μ€νμΌ λ°λ₯΄κΈ°: Prettierμ κ°μ μ½λ ν¬λ§·ν°μ ESLintμ κ°μ λ¦°ν°λ₯Ό μ¬μ©νμ¬ μν¬μ€νμ΄μ€ μ 체μμ μΌκ΄λ μ½λ© μ€νμΌμ μ μ©ν©λλ€.
- λ¨μ ν μ€νΈ μμ±: λͺ¨λ κ΅¬μ± μμ, μλΉμ€ λ° μ νΈλ¦¬ν°μ λν λ¨μ ν μ€νΈλ₯Ό μμ±νμ¬ μ½λ νμ§μ 보μ₯νκ³ νκ·λ₯Ό λ°©μ§ν©λλ€.
- λμμΈ μμ€ν μ¬μ©: UI κ΅¬μ± μμ μ 체μμ μΌκ΄μ±μ 보μ₯νκΈ° μν΄ λμμΈ μμ€ν μ μ¬μ©ν©λλ€.
- μ½λ λ¬Έμν: λ€λ₯Έ κ°λ°μκ° μ½κ² μ΄ν΄νκ³ μ μ§ κ΄λ¦¬ν μ μλλ‘ μ½λλ₯Ό μ² μ ν λ¬Έμνν©λλ€.
- λ²μ κ΄λ¦¬ μ¬μ©: Gitμ λ²μ κ΄λ¦¬μ μ¬μ©νκ³ μΌκ΄λ λΈλμΉ μ λ΅μ λ°λ¦ λλ€.
- μν¬νλ‘μ° μλν: CI/CDλ‘ μν¬νλ‘μ°λ₯Ό μλννμ¬ μ½λκ° νμ μλμΌλ‘ ν μ€νΈλκ³ λ°°ν¬λλλ‘ ν©λλ€.
- μ’ μμ± μ΅μ μν μ μ§: μ΅μ κΈ°λ₯ λ° λ³΄μ ν¨μΉλ₯Ό νμ©νκΈ° μν΄ μ’ μμ±μ μ κΈ°μ μΌλ‘ μ λ°μ΄νΈν©λλ€.
- μ±λ₯ λͺ¨λν°λ§: μ ν리μΌμ΄μ μ μ±λ₯μ λͺ¨λν°λ§νκ³ μ μ¬μ λ³λͺ© νμμ μλ³ν©λλ€.
κ³ κΈ Nx κ°λ
Nxμ κΈ°λ³Έ μ¬νμ μ΅μν΄μ§λ©΄ κ°λ° μν¬νλ‘μ°λ₯Ό λμ± ν₯μμν€κΈ° μν΄ λͺ κ°μ§ κ³ κΈ κ°λ μ νμν μ μμ΅λλ€.
- μ¬μ©μ μ§μ μμ±κΈ°: μ¬μ©μ μ§μ μμ±κΈ°λ₯Ό λ§λ€μ΄ μλ‘μ΄ νλ‘μ νΈ, κ΅¬μ± μμ λ° λͺ¨λμ μμ±μ μλνν©λλ€. μ΄λ κ² νλ©΄ κ°λ° μκ°μ ν¬κ² μ€μ΄κ³ μΌκ΄μ±μ 보μ₯ν μ μμ΅λλ€.
- Nx νλ¬κ·ΈμΈ: μ¬μ©μ μ§μ λꡬ λ° ν΅ν© κΈ°λ₯μ ν΅ν΄ Nxμ κΈ°λ₯μ νμ₯νκΈ° μν΄ Nx νλ¬κ·ΈμΈμ κ°λ°ν©λλ€.
- λͺ¨λ νλλ μ΄μ : λͺ¨λ νλλ μ΄μ μ μ¬μ©νμ¬ μ ν리μΌμ΄μ μ λ 립μ μΈ λΆλΆμ λ³λλ‘ λΉλνκ³ λ°°ν¬ν©λλ€. μ΄λ κ² νλ©΄ λ°°ν¬ μλκ° λΉ¨λΌμ§κ³ μ μ°μ±μ΄ ν₯μλ©λλ€.
- Nx Cloud: κ³ κΈ λΉλ ν΅μ°°λ ₯, λΆμ° μμ μ€ν λ° μ격 μΊμ±μ μ»κΈ° μν΄ Nx Cloudμ ν΅ν©ν©λλ€.
κ²°λ‘
Nx μν¬μ€νμ΄μ€λ νλ‘ νΈμλ monorepoλ₯Ό κ΄λ¦¬νλ κ°λ ₯νκ³ ν¨μ¨μ μΈ λ°©λ²μ μ 곡ν©λλ€. Nxμ κ³ κΈ λꡬ λ° κΈ°λ₯μ νμ©νμ¬ μ½λ 곡μ , λΉλ μ±λ₯ λ° κ°λ°μ νμ μ κ°μ νμ¬ νμ₯ κ°λ₯νκ³ μ μ§ κ΄λ¦¬ κ°λ₯ν νλ‘ νΈμλ μ ν리μΌμ΄μ μ λ§λ€ μ μμ΅λλ€. Nxλ₯Ό μμ©νλ©΄ κ°λ° νλ‘μΈμ€λ₯Ό κ°μννκ³ λ³΅μ‘νκ³ λκ·λͺ¨ νλ‘μ νΈμμ μμ ν λ νΉν νμ μμ°μ±μ ν¬κ² ν₯μμν¬ μ μμ΅λλ€. νλ‘ νΈμλ νκ²½μ΄ κ³μ λ°μ ν¨μ λ°λΌ Nxλ₯Ό μ¬μ©ν monorepo κ°λ°μ λ§μ€ν°νλ κ²μ νλ‘ νΈμλ μμ§λμ΄μκ² μ μ λ κ°μΉ μλ κΈ°μ μ΄ λκ³ μμ΅λλ€.
μ΄ κ°μ΄λμμλ νλ‘ νΈμλ Nx μν¬μ€νμ΄μ€ κ°λ°μ λν ν¬κ΄μ μΈ κ°μλ₯Ό μ 곡νμ΅λλ€. λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄κ³ κ³ κΈ κ°λ μ νμν¨μΌλ‘μ¨ Nxμ λͺ¨λ μ μ¬λ ₯μ νμ©νκ³ λλΌμ΄ νλ‘ νΈμλ μ ν리μΌμ΄μ μ ꡬμΆν μ μμ΅λλ€.