Docker 컨ν μ΄λ λͺ¨λν°λ§ λ° κ΄λ¦¬λ₯Ό μν μΉ λμ보λμ λλ€.
- React: UI μ»΄ν¬λνΈ λΌμ΄λΈλ¬λ¦¬
- TypeScript: μ μ νμ μ§μ
- Vite: λΉλ λꡬ
- TailwindCSS: CSS νλ μμν¬
- Tanstack Query: μλ² μν κ΄λ¦¬ λ° λ°μ΄ν° νμΉ
- React Router DOM: ν΄λΌμ΄μΈνΈ μ¬μ΄λ λΌμ°ν
- 컨ν μ΄λ λͺ©λ‘ μ‘°ν λ° νν°λ§
- 컨ν μ΄λ μμΈ μ 보 νμΈ
- 컨ν μ΄λ μμ/μ€μ§/μ¬μμ λ± μ μ΄
- μμ€ν 리μμ€ λͺ¨λν°λ§
- μλ μ€μΌμΌλ§ μ μ± κ΄λ¦¬
μ΄ νλ‘μ νΈλ Feature-Sliced Design (FSD) μν€ν μ²λ₯Ό λ°λ¦ λλ€.
src/
βββ app/ # μ± μμ€ μ€μ (λΌμ°ν
, λ μ΄μμ, ν
λ§, νλ‘λ°μ΄λ)
β βββ providers/ # μ± μ μ νλ‘λ°μ΄λ μ€μ
β β βββ query-provider.tsx # Tanstack Query νλ‘λ°μ΄λ
β βββ App.tsx # λ£¨νΈ μ± μ»΄ν¬λνΈ
βββ pages/ # νμ΄μ§ ꡬμ±
β βββ home/ # ν νμ΄μ§(λμ보λ)
β βββ containers/ # 컨ν
μ΄λ κ΄λ ¨ νμ΄μ§
β βββ scaling/ # μ€μΌμΌλ§ μ μ±
κ΄λ ¨ νμ΄μ§
βββ widgets/ # λ μ΄μμ λΈλ‘ (ν€λ, μ¬μ΄λλ° λ±)
β βββ header/ # ν€λ μ»΄ν¬λνΈ
β βββ sidebar/ # μ¬μ΄λλ° λ΄λΉκ²μ΄μ
β βββ layout/ # νμ΄μ§ λ μ΄μμ ꡬ쑰
β βββ container-grid/ # 컨ν
μ΄λ 그리λ μμ ―
β βββ stats-overview/ # ν΅κ³ κ°μ μμ ―
βββ features/ # κΈ°λ₯ λ¨μ
β βββ container-actions/ # 컨ν
μ΄λ μ‘μ
κ΄λ ¨ κΈ°λ₯
β βββ scaling-policy/ # μ€μΌμΌλ§ μ μ±
κ΄λ ¨ κΈ°λ₯
βββ entities/ # λλ©μΈ λ‘μ§ λ° λͺ¨λΈ
β βββ container/ # 컨ν
μ΄λ κ΄λ ¨ λλ©μΈ λ‘μ§
β βββ system/ # μμ€ν
μ 보 κ΄λ ¨ λλ©μΈ λ‘μ§
βββ shared/ # μ μ UI, μ νΈλ¦¬ν°, νμ
β βββ api/ # API ν΄λΌμ΄μΈνΈ λ° μ νΈλ¦¬ν°
β βββ ui/ # UI κΈ°λ³Έ μ»΄ν¬λνΈ
β βββ lib/ # μ νΈλ¦¬ν° ν¨μ
β βββ types/ # κ³΅ν΅ νμ
μ μ
βββ processes/ # λμ μμ€μ λΉμ¦λμ€ νλ‘μΈμ€
- src/main.tsx: μ ν리μΌμ΄μ μ§μ μ
- src/app/App.tsx: λ£¨νΈ μ ν리μΌμ΄μ μ»΄ν¬λνΈ
- src/app/providers/query-provider.tsx: Tanstack Query μ€μ
- src/widgets/layout/ui/layout.tsx: λ©μΈ λ μ΄μμ ꡬ쑰
- src/widgets/sidebar/ui/sidebar.tsx: μ¬μ΄λλ° λ΄λΉκ²μ΄μ μ»΄ν¬λνΈ
- src/widgets/header/ui/header.tsx: μλ¨ ν€λ μ»΄ν¬λνΈ
- package.json: νλ‘μ νΈ μμ‘΄μ± λ° μ€ν¬λ¦½νΈ
- vite.config.ts: Vite λΉλ λꡬ μ€μ
- tailwind.config.js: Tailwind CSS μ€μ
Tanstack Queryλ₯Ό μ¬μ©νμ¬ μλ²μμ ν΅μ λ° μν κ΄λ¦¬λ₯Ό ꡬννμ΅λλ€:
useContainers: 컨ν μ΄λ λͺ©λ‘ μ‘°νuseContainer: 컨ν μ΄λ μμΈ μ 보 μ‘°νuseContainerAction: 컨ν μ΄λ λμ μν (μμ, μ€μ§ λ±)useContainerTimeline: 컨ν μ΄λ μ±λ₯ νμλΌμΈ λ°μ΄ν° μ‘°νuseScalingPolicies: μλ μ€μΌμΌλ§ μ μ± λͺ©λ‘ μ‘°νuseCreateScalingPolicy: μλ μ€μΌμΌλ§ μ μ± μμ±useDashboardSummary: λμ보λ μμ½ μ 보 μ‘°νuseSystemSummary: μμ€ν μμ½ μ 보 μ‘°ν
# μμ‘΄μ± μ€μΉ
npm install
# κ°λ° μλ² μ€ν
npm run devnpm run buildnpm run test- ν΄λ¦° μ½λ: μλ―Έ μλ μ΄λ¦, μμ ν¨μ, DRY μμΉ μ μ©
- React λͺ¨λ² μ¬λ‘: ν¨μν μ»΄ν¬λνΈ, ν κ·μΉ μ€μ, μ μ ν μν κ΄λ¦¬
- Tailwind CSS: μ νΈλ¦¬ν° ν΄λμ€ μ¬μ©, μ»΄ν¬λνΈ μ€νμΌ μΌκ΄μ± μ μ§
- TypeScript: μΈν°νμ΄μ€ μ¬μ©, λͺ νν νμ μ μ, μ격ν νμ 체ν¬
- FSD μμΉ: λ μ΄μ΄ κ° μμ‘΄μ± κ·μΉ μ€μ, λ¨λ°©ν₯ μμ‘΄μ± μ μ§
Docker 컨ν μ΄λ κ΄λ¦¬λ₯Ό μν κ΅μ‘μ© λμ보λ νλ‘ νΈμλ μ ν리μΌμ΄μ μ λλ€.
μ΄ νλ‘μ νΈλ κ΅μ‘μ© μΏ λ²λ€ν±μ€ μκ°ν νμ΅ νλ«νΌμ λͺ©νλ‘ ν©λλ€:
- μ€μκ° ν΄λ¬μ€ν° λͺ¨λν°λ§μ ν΅ν μΏ λ²λ€ν±μ€ κ°λ νμ΅
- μκ°μ μΈν°νμ΄μ€λ₯Ό ν΅ν μ§κ΄μ μΈ μμ€ν μ΄ν΄
- μ€μ ν΄λ¬μ€ν° νκ²½κ³Όμ μνΈμμ©μ ν΅ν μ€μ΅ κ²½ν
- μ€μκ° ν΄λ¬μ€ν° μν λͺ¨λν°λ§: 5μ΄λ§λ€ μλ κ°±μ
- λ Έλ μν μκ°ν: λ§€λμ /μ컀 λ Έλ κ΅¬λΆ λ° μν νμ
- 리μμ€ μ¬μ©λ λμ보λ: CPU, λ©λͺ¨λ¦¬, λμ€ν¬ μ¬μ©λ₯ μ€μκ° μΆμ
- 컨ν μ΄λ μν μμ½: μ€ν/μ€μ§/μ€λ₯ μνλ³ μ»¨ν μ΄λ νν©
- κ΅μ‘μ νμ΅ ν¬μΈνΈ: κ° κ°λ μ λν μ€λͺ κ³Ό κ°μ΄λ
- μ 체 μμ€ν μν κ°μ
- λΉ λ₯Έ μν νμΈ μΉ΄λ
- ν΄λ¬μ€ν° λͺ¨λν°λ§μΌλ‘μ μν΄λ¦ μ΄λ
- 컨ν μ΄λ λͺ©λ‘ μ‘°ν
- κ°λ³ 컨ν μ΄λ μμΈ μ 보
- Frontend: React 18 + TypeScript
- μν κ΄λ¦¬: TanStack Query (React Query)
- μ€νμΌλ§: TailwindCSS + shadcn/ui
- μν€ν μ²: Feature-Sliced Design (FSD)
- λΉλ λꡬ: Vite
- λΌμ°ν : React Router
- Mock API: MSW (Mock Service Worker)
- λ°μ΄ν° μμμ±: localStorage
src/
βββ app/ # μ± λ 벨 μ€μ
βββ pages/ # νμ΄μ§ μ»΄ν¬λνΈλ€
β βββ cluster-monitoring/ # π ν΄λ¬μ€ν° λͺ¨λν°λ§ νμ΄μ§
β βββ dashboard/ # λ©μΈ λμ보λ
β βββ containers/ # 컨ν
μ΄λ κ΄λ ¨ νμ΄μ§λ€
βββ widgets/ # λ μ΄μμ λΈλ‘λ€
βββ features/ # κΈ°λ₯λ³ λͺ¨λλ€
βββ entities/ # λλ©μΈ λ‘μ§
βββ shared/ # κ³΅ν΅ μ νΈλ¦¬ν°
βββ api/ # API ν΄λΌμ΄μΈνΈ λ° ν
λ€
βββ ui/ # κ³΅ν΅ UI μ»΄ν¬λνΈλ€
μ΄ μ ν리μΌμ΄μ μ **MSW(Mock Service Worker)**μ localStorageλ₯Ό μ¬μ©νμ¬ λ°μ΄ν°λ₯Ό κ΄λ¦¬ν©λλ€:
- μλΉμ€ κ΄λ¦¬:
GET /api/services- μλΉμ€ λͺ©λ‘ μ‘°νPOST /api/services- μλΉμ€ μμ±PATCH /api/services/:id/scale- μλΉμ€ μ€μΌμΌλ§DELETE /api/services/:id- μλΉμ€ μμ
- μμ€ν
μ 보:
GET /api/summary- μμ€ν μμ½ μ 보
- 컨ν
μ΄λ κ΄λ¦¬:
GET /api/containers- 컨ν μ΄λ λͺ©λ‘
- ν΄λ¬μ€ν° κ΄λ¦¬:
GET /api/cluster/nodes- ν΄λ¬μ€ν° λ Έλ λͺ©λ‘PATCH /api/cluster/nodes/:id/availability- λ Έλ κ°μ©μ± λ³κ²½
- μλ μ μ₯: λͺ¨λ λ°μ΄ν° λ³κ²½μ¬νμ΄ localStorageμ μλ μ μ₯
- νμ΄μ§ μλ‘κ³ μΉ¨ μ μ§: λΈλΌμ°μ λ₯Ό μλ‘κ³ μΉ¨ν΄λ λ°μ΄ν°κ° μ μ§λ¨
- μ΄κΈ° λ°μ΄ν°: 첫 λ°©λ¬Έ μ 미리 μ μλ μν λ°μ΄ν°λ‘ μ΄κΈ°ν
- μ€μκ° λκΈ°ν: UI λ³κ²½μ¬νμ΄ μ¦μ localStorageμ λ°μ
- 5-10μ΄ κ°κ²©μ μλ λ°μ΄ν° κ°±μ μΌλ‘ μ€μκ° λ³ν κ΄μ°°
- μκ°μ μν νμκΈ°λ₯Ό ν΅ν μ§κ΄μ μ΄ν΄
- κ° νμ΄μ§λ§λ€ ν¬ν¨λ "νμ΅ ν¬μΈνΈ" μΉμ
- μΏ λ²λ€ν±μ€ ν΅μ¬ κ°λ μ λν μ€μ©μ μ€λͺ
- ν΄λ¦ κ°λ₯ν μν μΉ΄λ
- μ€μκ° μλ‘κ³ μΉ¨ κΈ°λ₯
- νμ΄μ§ κ° μνν λ€λΉκ²μ΄μ
npm installnpm run devnpm run build- μ 체 μμ€ν μν κ°μ
- ν΄λ¬μ€ν° λͺ¨λν°λ§μΌλ‘μ λΉ λ₯Έ μ κ·Ό
- μ€μκ° λͺ¨λν°λ§: ν΄λ¬μ€ν° μν μ€μκ° μΆμ
- λ Έλ κ΄λ¦¬: κ° λ Έλμ μνμ μν νμΈ
- 리μμ€ λͺ¨λν°λ§: CPU, λ©λͺ¨λ¦¬, λμ€ν¬ μ¬μ©λ
- κ΅μ‘ κ°μ΄λ: μΏ λ²λ€ν±μ€ κ°λ νμ΅ μ§μ
- 컨ν μ΄λ λͺ©λ‘ λ° μν νμΈ
- κ°λ³ 컨ν μ΄λ μμΈ μ 보
- ν΄λ¬μ€ν° μ 보: 5μ΄λ§λ€ κ°±μ
- μμ€ν μμ½: 10μ΄λ§λ€ κ°±μ
- λμ보λ λ°μ΄ν°: 10μ΄λ§λ€ κ°±μ
- λ°μν λμμΈ: λͺ¨λ°μΌλΆν° λ°μ€ν¬ν±κΉμ§ μ§μ
- λ€ν¬/λΌμ΄νΈ ν λ§: μ¬μ©μ μ νΈμ λ°λ₯Έ ν λ§ μ ν
- λ‘λ© μν: μ€μΌλ ν€ UIμ λ‘λ© μΈλμΌμ΄ν°
- μλ¬ μ²λ¦¬: μ¬μ©μ μΉνμ μλ¬ λ©μμ§
μ΄ μ ν리μΌμ΄μ μ ν΅ν΄ λ€μ κ°λ λ€μ νμ΅ν μ μμ΅λλ€:
- ν΄λ¬μ€ν° μν€ν μ²: λ§€λμ λ Έλμ μ컀 λ Έλμ μν
- 리μμ€ λͺ¨λν°λ§: μμ€ν μ±λ₯ μ§ν ν΄μ
- 컨ν μ΄λ λΌμ΄νμ¬μ΄ν΄: 컨ν μ΄λ μν λ³ν μΆμ
- μ€μκ° μ΄μ: μ€μ μ΄μ νκ²½μμμ λͺ¨λν°λ§ λ°©λ²
κ΅μ‘ λͺ©μ μΌλ‘ κ°λ°λ μΏ λ²λ€ν±μ€ νμ΅ νλ«νΌμ λλ€. μ€μ νλ‘λμ νκ²½μμλ μΆκ°μ μΈ λ³΄μ λ° μ±λ₯ μ΅μ νκ° νμν©λλ€.