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 ๋ฐฑ์๋ ์์คํ ์ ํฌ๊ด์ ์ธ ๋ชจ๋ํฐ๋ง, ๋๋ฒ๊น , ๊ด๋ฆฌ๋ฅผ ์ํ ์์คํฑ ์๋ฃจ์ ์ผ๋ก ์ค๊ณ๋์ด ์์ต๋๋ค.