fix(ui): 모니터링/디자인시스템 런타임 에러 해소 #88

병합
htlee fix/runtime-errors-monitoring-designsystem 에서 develop 로 2 commits 를 머지했습니다 2026-04-20 06:36:32 +09:00
소유자

변경 사항

브라우저 콘솔에 찍힌 2건 런타임 에러 해소

1. /monitoringSystemStatusPanel TypeError

  • 증상: Uncaught TypeError: Cannot read properties of undefined (reading 'toLocaleString') at SystemStatusPanel (SystemStatusPanel.tsx:104:48)
  • 원인: 라인 104 의 stats ? \${stats.total.toLocaleString()}건` : '-'. stats객체 자체는 존재하나total필드가undefined` 인 경우 (백엔드 응답이 기대 shape 와 다를 때) 가 있음.
  • 수정: null-safe 전환
    • 라인 104~106: stats?.total != null ? ${stats.total.toLocaleString()}건 : '-' / 각 필드 동일
    • 라인 127~130: stats.critical ?? 0 식 fallback

2. /design-system.htmlCatalogBadges 렌더 실패

  • 증상:
    • Each child in a list should have a unique "key" prop (Warning)
    • Uncaught Error: Objects are not valid as a React child (found: object with keys {ko, en}) (Throw — 페이지 렌더 중단)
  • 원인: shared/constants/performanceStatus.tsPERFORMANCE_STATUS_META 의 meta 는 {intent, hex, label: {ko, en}} 형식. 즉
    • code 필드가 없음 → Object.values(items) 순회 + <Trk key={meta.code}> 는 undefined 중복 key
    • label{ko, en} 객체 → getKoLabel 이 이 객체를 그대로 반환 → <Badge>{label}</Badge> 에서 React child 가 객체 → throw
  • 다른 카탈로그fallback: {ko, en} 패턴이라 무사. performanceStatuslabel 객체를 쓴다. 이는 admin 페이지들(PerformanceMonitoring, DataRetentionPolicy, DataModelVerification) 이 meta.label.ko / meta.label.en 을 직접 참조하므로 기존 카탈로그 자체는 건드리지 않고 CatalogSection 렌더러만 두 포맷 수용하도록 확장.
  • 수정 (design-system/sections/CatalogSection.tsx):
    • Object.values()Object.entries() 로 순회해 Record key 를 안정적 식별자로 사용
    • AnyMeta.label 타입을 string | {ko, en} 로 확장
    • getKoLabel 우선순위: fallback.kolabel.kolabel(문자열) → code → key
    • getEnLabel 우선순위: fallback.enlabel.en → undefined
    • <Trk key={key}> + displayCode = meta.code ?? key

테스트

  • npx tsc --noEmit 통과 (0 에러)
  • pre-commit (tsc + ESLint) 통과
  • (브라우저) /monitoring 접속 → 콘솔 TypeError 재현 안 됨 확인
  • (브라우저) /design-system.html 카탈로그 섹션 PERFORMANCE_STATUS 배지 10개 정상 렌더 + 콘솔 경고 없음 확인

영향

  • frontend only — backend/prediction 변경 없음
  • PERFORMANCE_STATUS_META 카탈로그 자체는 변경 없음 (admin 페이지 참조 패턴 그대로 유지)
  • 다른 19+ 카탈로그는 fallback: {ko, en} 패턴 유지, 동작 영향 없음

관련

  • Phase 0-2/0-3 (PR #85, #86) 와 독립적 버그 — 이전부터 있던 잠복 이슈가 테스트 중 사용자 재현
## 변경 사항 **브라우저 콘솔에 찍힌 2건 런타임 에러 해소** ### 1. `/monitoring` — `SystemStatusPanel` TypeError - **증상**: `Uncaught TypeError: Cannot read properties of undefined (reading 'toLocaleString') at SystemStatusPanel (SystemStatusPanel.tsx:104:48)` - **원인**: 라인 104 의 `stats ? \`${stats.total.toLocaleString()}건\` : '-'`. `stats` 객체 자체는 존재하나 `total` 필드가 `undefined` 인 경우 (백엔드 응답이 기대 shape 와 다를 때) 가 있음. - **수정**: null-safe 전환 - 라인 104~106: `stats?.total != null ? ${stats.total.toLocaleString()}건 : '-'` / 각 필드 동일 - 라인 127~130: `stats.critical ?? 0` 식 fallback ### 2. `/design-system.html` — `CatalogBadges` 렌더 실패 - **증상**: - `Each child in a list should have a unique "key" prop` (Warning) - `Uncaught Error: Objects are not valid as a React child (found: object with keys {ko, en})` (Throw — 페이지 렌더 중단) - **원인**: `shared/constants/performanceStatus.ts` 의 `PERFORMANCE_STATUS_META` 의 meta 는 `{intent, hex, label: {ko, en}}` 형식. 즉 - `code` 필드가 없음 → `Object.values(items)` 순회 + `<Trk key={meta.code}>` 는 undefined 중복 key - `label` 이 `{ko, en}` 객체 → `getKoLabel` 이 이 객체를 그대로 반환 → `<Badge>{label}</Badge>` 에서 React child 가 객체 → throw - **다른 카탈로그**는 `fallback: {ko, en}` 패턴이라 무사. `performanceStatus` 만 `label` 객체를 쓴다. 이는 admin 페이지들(`PerformanceMonitoring`, `DataRetentionPolicy`, `DataModelVerification`) 이 `meta.label.ko` / `meta.label.en` 을 직접 참조하므로 **기존 카탈로그 자체는 건드리지 않고** `CatalogSection` 렌더러만 두 포맷 수용하도록 확장. - **수정** (`design-system/sections/CatalogSection.tsx`): - `Object.values()` → `Object.entries()` 로 순회해 Record key 를 안정적 식별자로 사용 - `AnyMeta.label` 타입을 `string | {ko, en}` 로 확장 - `getKoLabel` 우선순위: `fallback.ko` → `label.ko` → `label`(문자열) → `code` → key - `getEnLabel` 우선순위: `fallback.en` → `label.en` → undefined - `<Trk key={key}>` + `displayCode = meta.code ?? key` ## 테스트 - [x] `npx tsc --noEmit` 통과 (0 에러) - [x] pre-commit (tsc + ESLint) 통과 - [ ] (브라우저) `/monitoring` 접속 → 콘솔 TypeError 재현 안 됨 확인 - [ ] (브라우저) `/design-system.html` 카탈로그 섹션 PERFORMANCE_STATUS 배지 10개 정상 렌더 + 콘솔 경고 없음 확인 ## 영향 - frontend only — backend/prediction 변경 없음 - PERFORMANCE_STATUS_META 카탈로그 자체는 변경 없음 (admin 페이지 참조 패턴 그대로 유지) - 다른 19+ 카탈로그는 `fallback: {ko, en}` 패턴 유지, 동작 영향 없음 ## 관련 - Phase 0-2/0-3 (PR #85, #86) 와 **독립적** 버그 — 이전부터 있던 잠복 이슈가 테스트 중 사용자 재현
htlee added 2 commits 2026-04-20 06:32:04 +09:00
### SystemStatusPanel TypeError
- 증상: /monitoring 에서 Uncaught TypeError: Cannot read properties of undefined (reading 'toLocaleString')
- 원인: stats 객체는 존재하나 total 필드가 undefined 인 경우 (백엔드 응답이 기대 shape 와 다를 때) 크래시
- 수정: stats?.total != null ? ... / stats.critical ?? 0 식 null-safe 전환 (total/clusterCount/gearGroups/critical/high/medium/low 전부)

### CatalogBadges 렌더링 오류
- 증상: /design-system.html 에서
  (1) Each child in a list should have a unique "key" prop
  (2) Objects are not valid as a React child (found: object with keys {ko, en})
- 원인: PERFORMANCE_STATUS_META 의 meta 는 {intent, hex, label: {ko, en}} 형식. code 필드 없고 label 이 객체.
  - Object.values() + <Trk key={meta.code}> 로 undefined key 중복
  - getKoLabel 이 meta.label (객체) 그대로 반환해 Badge children 에 객체 주입
  다른 카탈로그는 fallback: {ko, en} 패턴이라 문제 없음 (performanceStatus 만 label 객체)
- 수정:
  - Object.entries() 로 순회해 Record key 를 안정적 식별자로 사용
  - AnyMeta.label 타입을 string | {ko,en} 확장
  - getKoLabel/getEnLabel 우선순위: fallback.ko → label.ko → label(문자열) → code → key
  - PERFORMANCE_STATUS_META 자체는 변경 안 함 (admin 페이지들이 label.ko/label.en 직접 참조 중)

### 검증
- npx tsc --noEmit 통과
- pre-commit tsc+ESLint 통과
claude-bot 이 변경사항을 승인하였습니다. 2026-04-20 06:36:31 +09:00
claude-bot left a comment
멤버

Hotfix 승인: SystemStatusPanel null-safe + CatalogBadges label 객체 렌더링

Hotfix 승인: SystemStatusPanel null-safe + CatalogBadges label 객체 렌더링
htlee merged commit afde36480d into develop 2026-04-20 06:36:32 +09:00
htlee 삭제된 브랜치 fix/runtime-errors-monitoring-designsystem 2026-04-20 06:36:32 +09:00
"로그인하여 이 대화에 참여"
No reviewers
레이블 없음
마일스톤 없음
담당자 없음
참여자 2명
알림
마감일
기한이 올바르지 않거나 범위를 벗어났습니다. 'yyyy-mm-dd'형식을 사용해주십시오.

마감일이 설정되지 않았습니다.

의존성

No dependencies set.

Reference: gc/kcg-ai-monitoring#88
No description provided.