This commit is contained in:
2026-07-08 19:32:16 +09:00
parent 9c40dec070
commit 8ffa9b097a
14 changed files with 238 additions and 50 deletions
+7 -1
View File
@@ -260,5 +260,11 @@
* **엔드포인트:** `GET /api/dashboard/admin/resources?days=30` (SYSTEM_ADMIN 전용, 범위 1~90일)
* **응답:**
- `current`: 요청 시점 실시간 계측값 (그래프 미저장)
- `history`: `system_resources` 테이블의 최근 N일 시계열 (그래프 렌더링용)
- `history`: `system_resources` 테이블의 최근 N일 시계열 (그래프 렌더링용, **다운샘플링 적용**)
- `stats`: 활성 사용자/프로젝트/저장소 지표
* **다운샘플링 (조회 시):**
- 30일 원본은 약 21,600점(2분 간격) → 그대로 전송 시 페이로드 과다(~4MB)
- SQL에서 시간버킷 평균으로 축소: `bucket = max(120초, days*86400 / 300)` → 최대 약 300점
- `GROUP BY FLOOR(UNIX_TIMESTAMP(timestamp) / bucket)` + `AVG(...)`로 집계
- 계측 간격(2분)보다 버킷이 작으면 원본 해상도 유지 (하루 이하 조회 시)
- 효과: 30일 조회 페이로드 ~4MB → ~55KB 수준
+41
View File
@@ -157,10 +157,51 @@
- `npx tsc --noEmit` 통과, `ruff format`/`ruff check` 통과, `prettier --write` 변경 없음.
- 계측/로그 트림 로직은 스크립트로 실측 확인 (샘플 기록·30일 경과 줄 제거 동작 확인 후 테스트 로그 삭제).
## 후속 수정 (그래프 다운샘플링 + 스플라인 + 범례/X축)
### 조회 다운샘플링 (백엔드)
- `get_system_resources`의 history 조회를 시간버킷 평균으로 축소.
- `bucket = max(120초, days*86400 / 300)` → 최대 약 300점.
- `GROUP BY FLOOR(UNIX_TIMESTAMP(timestamp)/bucket)` + `AVG(...)`.
- 30일 조회 페이로드 ~4MB → ~55KB 수준으로 감소. 하루 이하 조회 시 원본 해상도 유지.
- DB 실측: 5행 → 1버킷 평균 집계 확인 후 테스트 데이터 삭제.
### 차트 컴포넌트 개선 (`ui_template_elements.ts`)
- 직선 → **스플라인**(Catmull-Rom → 3차 베지어). null 구간은 세그먼트로 분리해 각각 곡선 처리.
- **범례를 그래프 우상단 오버레이**로 이동 (`.ui-chart__plot` position:relative + `.ui-chart__legend` absolute, 반투명 배경).
- **X축 라벨** 지원: `opts.xLabels`, 양끝 포함 5개 균등 표기 (`.ui-chart__tick--x`).
- `B01_Dashboard_UI_Page.ts``formatChartTime`(MM/DD HH:mm) 추가 후 `xLabels` 전달.
### 리소스 지표 레이아웃 (`B01_Dashboard_UI_Style.css`)
- metric-grid를 5열 1행, 각 항목은 라벨·값 가로 1줄(`space-between`)로 컴팩트화. 값 폰트 축소.
### 검증
- `npx tsc --noEmit` 통과 (el() children 타입 이슈는 svg를 append로 분리해 해결).
- `ruff format/check` 통과, `prettier` 변경 없음.
## 후속 수정 (그래프 X축 레이블 - 데이터 기반 고정)
### 백엔드 timestamp 직렬화 (B01_Dashboard_Repository.py)
- 기존: `FROM_UNIXTIME()` → Python datetime 객체로 JSON 직렬화 불가
- 변경: `DATE_FORMAT(..., '%%Y-%%m-%%dT%%H:%%i:%%s')` → ISO 문자열로 명시적 변환
- SQL에 `date_fmt` 변수 도입해 ruff 100자 줄 제한 준수
### 프론트엔드 X축 라벨 고정 (ui_template_elements.ts, B01_Dashboard_UI_Page.ts)
- 기존: `X_TICK_COUNT=5` 고정으로 균등 선택 (데이터 개수와 무관)
- 변경: `X_TICK_STEP=3` — 데이터 포인트마다 3개씩 건너뛰며 표시 (실제 데이터량 기반)
- X축 라벨 루프를 `for (let idx = 0; idx < pointCount; idx += X_TICK_STEP)` 로 변경
- `formatChartTime`에 try-catch 추가로 예외 안전성 강화
### 검증
-`npx tsc --noEmit` 통과
-`ruff format/check` 통과 (100자 줄 제한 준수)
-`prettier` 변경 없음
## 남은 주의점
- B01 화면은 구현됐지만 실제 브라우저 검증은 수행하지 않았다.
- 그래프는 `system_resources` 이력이 쌓여야 선이 그려진다 (앱 최초 구동 직후에는 데이터 2점 미만이면 `—` 빈 상태 표시, 2분 주기로 누적).
- 그래프 갱신은 페이지 로드/새로고침 시점 1회 (자동 폴링 없음).
- 로그인/회사 상태별 실제 시나리오 검증은 별도 검증 AI 또는 사용자가 수행해야 한다.
- `B01_Dashboard_UI_Page.ts`는 645줄로 700줄 제한 이내지만, 향후 기능 추가 시 컴포넌트 분리를 고려해야 한다.
- 이전 import 검증 중 기존 B04 계열 Pydantic `model_*` 필드 경고가 출력됐으나, 이번 B01 구현에서 발생한 경고는 아니다.
+7 -4
View File
@@ -15,11 +15,14 @@
### 2.1 공통 컴포넌트 목록 (`ui_template_elements.ts`)
* **기본:** `createButton`, `createInputField`, `createCard`, `createTag`, `createWorkflowShell`
* **오버레이/알림:** `showLoadingOverlay`, `hideLoadingOverlay`, `showToast`
* **라인 차트:** `createLineChart(opts)` — 외부 라이브러리 없이 인라인 SVG로 시계열 렌더링
- 색상은 `--color-chart-0~3` 테마 변수 사용 (하드코딩 금지)
- `series[].values``null` 포함 시 해당 구간 선 끊김 처리
* **스플라인 차트:** `createLineChart(opts)` — 외부 라이브러리 없이 인라인 SVG로 시계열 렌더링
- **곡선:** Catmull-Rom → 3차 베지어 변환으로 스플라인(부드러운 곡선) 렌더
- **색상:** `--color-chart-0~3` 테마 변수 사용 (하드코딩 금지)
- **범례:** 그래프 영역 우상단에 반투명 오버레이 배치 (`opts.series[].name`)
- **X축:** `opts.xLabels` 전달 시 양끝 포함 5개 라벨 균등 표기
- **결측:** `series[].values``null` 포함 시 해당 구간 선 끊김 처리
- 데이터 2점 미만이면 빈 상태(`—`) 반환
- 사용 예: B01_Dashboard 리소스 현황(CPU/메모리/디스크 30일 추이)
- 사용 예: B01_Dashboard 리소스 현황(CPU/메모리/디스크 30일 추이, X축=시간)
---