Dimiplan λ°±μλ μμ€ν μ μν ν¬κ΄μ μΈ Angular κΈ°λ° κ΄λ¦¬μ μΈν°νμ΄μ€μ λλ€. Material Design 3 ν λ§λ₯Ό μ μ©ν νλμ μΈ κ΄λ¦¬μ ν¨λλ‘, μμ€ν λͺ¨λν°λ§, λ°μ΄ν°λ² μ΄μ€ κ΄λ¦¬, λ‘κ·Έ λΆμ, API λ¬Έμν λ±μ κΈ°λ₯μ μ 곡ν©λλ€.
- μ€μκ° μμ€ν λͺ¨λν°λ§: μλ² κ°λμκ°, λ©λͺ¨λ¦¬ μ¬μ©λ, CPU μ¬μ©λ₯ , νλ«νΌ μ 보, Node.js λ²μ λ± μ€μκ° νμ
- AI μ¬μ©λ μΆμ : AI API ν¬λ λ§ λ° μ¬μ©λ ν΅κ³, μ¬μ©λ μΆμΈ μκ°ν
- μ¬μ©μ ν΅κ³: μ΄ μ¬μ©μ μ, νμ± μ¬μ©μ(30μΌ), μ΅κ·Ό μ κ· μ¬μ©μ λ±λ‘ νν©
- λΉ λ₯Έ μμ : λ‘κ·Έ, λ°μ΄ν°λ² μ΄μ€, API λ¬Έμλ‘μ νΈλ¦¬ν νμ
- μκ°ν: λ©λͺ¨λ¦¬ λ° CPU μ¬μ©λ₯ μ§ν λ§λ, νκ²½λ³ μν λ°°μ§
- ν μ΄λΈ λΈλΌμ°μ : ν κ°μμ ν¨κ» λͺ¨λ λ°μ΄ν°λ² μ΄μ€ ν μ΄λΈ λͺ©λ‘ νμ
- μ€ν€λ§ λ·°μ΄: ν μ΄λΈ ꡬ쑰(컬λΌλͺ , λ°μ΄ν° νμ , ν€ μ 보, Nullable μ¬λΆ) μμΈ νμ
- λνν λ°μ΄ν° νμ: νμ΄μ§λ€μ΄μ (25, 50, 100, 200κ° λ μ½λ)μΌλ‘ ν μ΄λΈ λ°μ΄ν° νμ
- λ°μ΄ν° λ΄λ³΄λ΄κΈ°: ν μ΄λΈ λ°μ΄ν°λ₯Ό CSV νμμΌλ‘ λ€μ΄λ‘λ
- μ»¬λΌ μ 보 μκ°ν: λ°μ΄ν° νμ λ³ μμ ꡬλΆ, ν€ νμ λ³ μμ΄μ½ νμ(PRI, UNI, MUL)
- tooltips: κΈ΄ λ°μ΄ν°λ ν΄νμΌλ‘ μ 체 λ΄μ© νμΈ κ°λ₯
- λ‘κ·Έ νμΌ λΈλΌμ°μ : νμΌ ν¬κΈ°μ μμ λ μ§μ ν¨κ» μ¬μ© κ°λ₯ν λͺ¨λ λ‘κ·Έ νμΌ λͺ©λ‘
- μ€μκ° λ‘κ·Έ λ·°μ΄: μ νν λ‘κ·Έ νμΌμ λ΄μ©μ μ€μκ°μΌλ‘ νμ
- λ‘κ·Έ λ 벨 νν°λ§: λ‘κ·Έ λ λ²¨λ³ νν°λ§(error, warn, info, verbose)
- ꡬ문 κ°μ‘°: λ‘κ·Έ λ λ²¨λ³ μμ ꡬλΆ, νμμ€ν¬ν νμ±
- λ€μ΄λ‘λ: μμ ν λ‘κ·Έ νμΌ λ‘컬 λ€μ΄λ‘λ
- μ¬μ©μ μΉνμ νμ: νμΌ ν¬κΈ°λ₯Ό B, KB, MB, GB λ¨μλ‘ μλ ν¬λ§·ν
- μλ JSDoc λ¬Έμν: JSDoc μ£Όμ κΈ°λ° API λ¬Έμ μλ μμ± λ° νμ±
- λνν λ¬Έμ νμ: κ²½λ‘, λ©μλ, μ€λͺ μΌλ‘ API μλν¬μΈνΈ κ²μ
- νμΌλ³ νν°λ§: API μλν¬μΈνΈλ₯Ό νμΌλ³λ‘ κ·Έλ£Ήννμ¬ νμ
- 볡μ‘ν λ°νκ° μ²λ¦¬: μ€μ²©λ κ°μ²΄ λ° λ°°μ΄ κ΅¬μ‘°λ₯Ό κ·Έλ£Ήννμ¬ νμ
- cURL μμ : κ° μλν¬μΈνΈμ λν μ¦μ μ¬μ© κ°λ₯ν cURL λͺ λ Ήμ΄ μμ± λ° ν΄λ¦½λ³΄λ 볡μ¬
- λ¬Έμ λ΄λ³΄λ΄κΈ°: API λ¬Έμλ₯Ό Markdown νμμΌλ‘ λ΄λ³΄λ΄κΈ°
- μ€μκ° μ¬μμ±: μμ² μ JSDoc λ¬Έμ μ¬μμ±
- HTTP λ©μλλ³ μμ ꡬλΆ: GET, POST, PUT, DELETE λ©μλλ³ μκ°μ ꡬλΆ
- Angular 20.0.3 (μ΅μ λ²μ , Standalone μ»΄ν¬λνΈ μ¬μ©)
- Angular Material 20.0.3 (Material Design 3 ν λ§)
- RxJS 7.8.2 (λ°μν νλ‘κ·Έλλ°)
- Tailwind CSS 3.4.17 (μ νΈλ¦¬ν° μ°μ μ€νμΌλ§)
- Material Design 3 μμ μμ€ν λ° νμ΄ν¬κ·ΈλνΌ
- PostCSS & Autoprefixer (CSS μ²λ¦¬)
- μμ λ°μν λμμΈ: λͺ¨λ°μΌ μΉνμ λ μ΄μμ
- TypeScript 5.8.3 (κ°νμ μμ€ν )
- Jasmine & Karma (λ¨μ ν μ€νΈ)
- Angular CLI 20.0.2 (κ°λ° λꡬ)
- λͺ¨λ Angular ν¨ν΄: Standalone μ»΄ν¬λνΈ, ν¨μν μΈν°μ ν°
- μμ‘΄μ± μ£Όμ : μλΉμ€ κΈ°λ° μν€ν μ²
- νμ μμ μ±: λͺ¨λ API μλ΅μ λν TypeScript μΈν°νμ΄μ€
- Node.js 18+
- npm λλ yarn
- Angular CLI 20+
npm installnpm start
# λλ
ng serveκ°λ° μλ²κ° μ€νλλ©΄ λΈλΌμ°μ μμ http://localhost:4200/λ‘ μ μνμΈμ.
npm run build
# λλ
ng buildλΉλ κ²°κ³Όλ¬Όμ dist/ λλ ν 리μ μμ±λ©λλ€.
npm test
# λλ
ng test- Google κ³μ μ°λ: Google OAuthλ₯Ό ν΅ν μμ ν κ΄λ¦¬μ μΈμ¦
- κ°μ λ‘κ·ΈμΈ: 401 μλ¬ λ°μ μ μλμΌλ‘ λ‘κ·ΈμΈ λͺ¨λ¬ νμ
- μΈμ
μ μ§: μΏ ν€ κΈ°λ° μΈμ
κ΄λ¦¬ (
withCredentials: true) - μλ 리λ€μ΄λ νΈ: μΈμ¦ ν κ΄λ¦¬μ ν¨λλ‘ μλ 볡κ·
- HTTP μΈν°μ ν°: λͺ¨λ API μμ²μ μλ ν¬λ¦¬λ΄μ 첨λΆ
- 401 μλ¬ μλ μ²λ¦¬: μΈμ¦ μ€ν¨ μ μλ λ‘κ·ΈμΈ νλ‘μΈμ€
- CORS μ§μ: λλ©μΈ κ° μΏ ν€ μΈμ μν μ μ§
- νμ μμ μ±: TypeScriptλ₯Ό ν΅ν μ»΄νμΌ νμ 보μ
κΈ°λ³Έμ μΌλ‘ https://api-dev.dimiplan.comμ μ°κ²°λ©λλ€. λ€λ₯Έ API μλ²λ₯Ό μ¬μ©νλ €λ©΄ src/app/services/admin.service.tsμμ API_BASE_URLμ μμ νμΈμ.
- λ€ν¬/λΌμ΄νΈ λͺ¨λ: μ¬μ©μκ° ν κΈ λ²νΌμΌλ‘ ν λ§ μ ν κ°λ₯
- ν λ§ μ§μμ±: localStorageλ₯Ό ν΅ν ν λ§ μ€μ μ μ₯ λ° λ³΅μ
- Material Design 3: μ΅μ Material Design κ°μ΄λλΌμΈ λ° μμ ν ν° μ μ©
- μμ λ°μν: λͺ¨λ°μΌκ³Ό λ°μ€ν¬ν±μμ μ΅μ νλ λ μ΄μμ
src/app/
βββ components/ # μ£Όμ μ»΄ν¬λνΈ
β βββ dashboard/ # λμ보λ (μμ€ν
μν, μ¬μ©μ ν΅κ³, AI μ¬μ©λ)
β βββ database/ # λ°μ΄ν°λ² μ΄μ€ κ΄λ¦¬ (ν
μ΄λΈ νμ, λ°μ΄ν° λ·°μ΄)
β βββ logs/ # λ‘κ·Έ κ΄λ¦¬ (νμΌ λΈλΌμ°μ , λ‘κ·Έ λ·°μ΄)
β βββ api-docs/ # API λ¬Έμ (μλ μμ±, κ²μ, λ΄λ³΄λ΄κΈ°)
β βββ login-modal/ # λ‘κ·ΈμΈ λͺ¨λ¬ (Google OAuth)
βββ services/ # μλΉμ€ λ μ΄μ΄
β βββ admin.service.ts # κ΄λ¦¬μ API ν΅ν© μλΉμ€
β βββ auth-modal.service.ts # μΈμ¦ λͺ¨λ¬ κ΄λ¦¬ μλΉμ€
βββ interceptors/ # HTTP μΈν°μ
ν°
β βββ auth.interceptor.ts # μΈμ¦ λ° CORS μ²λ¦¬
βββ styles/ # μ μ μ€νμΌ
β βββ material-tokens.scss # Material Design 3 ν ν°
β βββ material-you-theme.scss # Material You ν
λ§
βββ app.config.ts # μ ν리μΌμ΄μ
μ€μ
βββ app.routes.ts # λΌμ°ν
μ€μ
βββ app.ts # λ©μΈ μ ν리μΌμ΄μ
μ»΄ν¬λνΈ
βββ app.html # μ ν리μΌμ΄μ
ν
νλ¦Ώ
κ΄λ¦¬μ ν¨λμμ μ¬μ©νλ μ£Όμ API μλν¬μΈνΈ:
GET /system-status- μμ€ν μν μ 보GET /stats/users- μ¬μ©μ ν΅κ³GET /ai-usage- AI μ¬μ©λ ν΅κ³GET /logs- λ‘κ·Έ νμΌ λͺ©λ‘GET /logs/{filename}- νΉμ λ‘κ·Έ νμΌ λ΄μ©GET /database/tables- λ°μ΄ν°λ² μ΄μ€ ν μ΄λΈ λͺ©λ‘GET /database/tables/{tableName}- ν μ΄λΈ λ°μ΄ν° λ° μ€ν€λ§GET /docs- API λ¬ΈμPOST /docs/regenerate- API λ¬Έμ μ¬μμ±
- Standalone μ»΄ν¬λνΈ:
@Componentλ°μ½λ μ΄ν°μμ imports μ§μ κ΄λ¦¬ - ν¨μν μΈν°μ ν°: ν΄λμ€ κΈ°λ°μ΄ μλ ν¨μν HTTP μΈν°μ ν° μ¬μ©
- μμ‘΄μ± μ£Όμ
:
inject()ν¨μλ₯Ό ν΅ν νλμ DI ν¨ν΄
- λ‘λ© μν: λͺ¨λ λΉλκΈ° μμ μ λν λ‘λ© μΈλμΌμ΄ν°
- μλ¬ μ²λ¦¬: μ¬μ©μ μΉνμ μλ¬ λ©μμ§ λ° μλ 볡ꡬ
- λ°μν νΌλλ°±: μ±κ³΅/μ€ν¨μ λν μ¦κ°μ μΈ μκ°μ νΌλλ°±
- ν€λ³΄λ λ€λΉκ²μ΄μ : μ κ·Όμ±μ μν ν€λ³΄λ μ§μ
- μ§μ° λ‘λ©: λΌμ°νΈλ³ μ»΄ν¬λνΈ λΆν
- λ©λͺ¨λ¦¬ κ΄λ¦¬: μ»΄ν¬λνΈ μλͺ μ£ΌκΈ°μ λ°λ₯Έ ꡬλ ν΄μ
- ν¨μ¨μ μΈ λ λλ§: Angularμ OnPush λ³κ²½ κ°μ§ μ λ΅ νμ©
μ΄ κ΄λ¦¬μ ν¨λμ Dimiplan λ°±μλ μμ€ν μ ν¬κ΄μ μΈ λͺ¨λν°λ§, λλ²κΉ , κ΄λ¦¬λ₯Ό μν μμ€ν± μ루μ μΌλ‘ μ€κ³λμ΄ μμ΅λλ€.