435 lines
22 KiB
Markdown
435 lines
22 KiB
Markdown
# 2026-02-10 작업 기록
|
|
|
|
## 요약
|
|
|
|
pop-dashboard 컴포넌트 17단계 코딩 완료 + 검수 + 팔레트 미노출 버그 수정
|
|
|
|
## 작업 내역
|
|
|
|
### 1. pop-dashboard 전체 구현 (17단계 코딩)
|
|
|
|
계획서 기반으로 15개 신규 파일 생성, 3개 기존 파일 수정:
|
|
|
|
| 단계 | 파일 | 핵심 내용 |
|
|
|------|------|----------|
|
|
| Step 1 | `types.ts` | Phase 0 공통 타입 + 대시보드 전용 타입 25개 추가 |
|
|
| Step 2 | `utils/formula.ts` | 재귀 하강 파서 기반 수식 계산, abbreviateNumber |
|
|
| Step 3 | `utils/dataFetcher.ts` | @INFRA-EXTRACT 직접 API 호출, SQL 생성 + 인젝션 방지 |
|
|
| Step 4 | `items/KpiCard.tsx` | CSS Container Query 반응형 KPI 카드 |
|
|
| Step 5 | `items/ChartItem.tsx` | Recharts 통합 (bar/pie/line) |
|
|
| Step 6 | `items/GaugeItem.tsx` | SVG 반원형 게이지 자체 구현 |
|
|
| Step 7 | `items/StatCard.tsx` | 카테고리별 건수 표시 |
|
|
| Step 8 | `modes/ArrowsMode.tsx` | 좌우 화살표 + 터치 최적화 |
|
|
| Step 9 | `modes/AutoSlideMode.tsx` | 자동 슬라이드 + 터치 일시정지 + 자동 재개 |
|
|
| Step 10 | `modes/GridMode.tsx` | CSS Grid + @container 셀 배치 |
|
|
| Step 11 | `modes/ScrollMode.tsx` | scroll-snap 가로 스크롤 |
|
|
| Step 12 | `PopDashboardComponent.tsx` | 메인 뷰어 컴포넌트, Promise.allSettled 병렬 로딩 |
|
|
| Step 13 | `PopDashboardPreview.tsx` | 디자이너 미리보기 (더미 데이터) |
|
|
| Step 14 | `PopDashboardConfig.tsx` | 3탭 설정 패널 (기본/아이템/레이아웃) |
|
|
| Step 15 | `pop-dashboard/index.tsx` | PopComponentRegistry 등록 |
|
|
| Step 16 | `pop-components/index.ts` | import 추가 |
|
|
| Step 17 | `pop-text.tsx` | datetime isRealtime 기본값 버그 수정 |
|
|
|
|
### 2. 코딩 후 자체 검수
|
|
|
|
| 검수 항목 | 결과 |
|
|
|----------|------|
|
|
| 린트 에러 | 0개 (기존 경고만) |
|
|
| 중복 정의 | 없음 |
|
|
| 미사용 import | 1건 발견 (AggregatedResult) |
|
|
| import 누락 | 없음 |
|
|
| props 불일치 | 없음 |
|
|
|
|
### 3. 팔레트 미노출 버그 수정
|
|
|
|
**문제**: pop-dashboard를 레지스트리에 등록했지만 디자이너 팔레트에 표시되지 않음
|
|
|
|
**원인**: 디자이너가 PopComponentRegistry를 읽지 않고 하드코딩된 배열/타입을 사용
|
|
|
|
**수정 (4개 파일)**:
|
|
|
|
| 파일 | 수정 내용 |
|
|
|------|----------|
|
|
| `pop-layout.ts` | `PopComponentType` 유니온에 `"pop-dashboard"` 추가, `DEFAULT_COMPONENT_GRID_SIZE`에 6x3 기본 크기 추가 |
|
|
| `ComponentPalette.tsx` | `PALETTE_ITEMS` 배열에 대시보드 항목 추가 (아이콘: BarChart3) |
|
|
| `PopRenderer.tsx` | `COMPONENT_TYPE_LABELS`에 `"pop-dashboard": "대시보드"` 추가 |
|
|
| `PopDashboardComponent.tsx` | 미사용 `type AggregatedResult` import 제거 |
|
|
|
|
---
|
|
|
|
## 이번 작업에서 배운 것
|
|
|
|
### 에러 패턴: 컴포넌트 등록 누락
|
|
|
|
POP 시스템에서 새 컴포넌트를 추가할 때 등록해야 하는 곳이 **5곳**이다:
|
|
|
|
1. `PopComponentRegistry.registerComponent()` - 레지스트리 등록 (index.tsx)
|
|
2. `pop-components/index.ts` - side-effect import 추가
|
|
3. `PopComponentType` 유니온 - 타입 시스템 (pop-layout.ts)
|
|
4. `PALETTE_ITEMS` 배열 - 팔레트 UI (ComponentPalette.tsx)
|
|
5. `DEFAULT_COMPONENT_GRID_SIZE` - 기본 크기 (pop-layout.ts)
|
|
6. `COMPONENT_TYPE_LABELS` - 라벨 표시 (PopRenderer.tsx)
|
|
|
|
계획서에서 1~2번만 포함하고 3~6번을 누락했다. 레지스트리와 디자이너가 자동 연동되지 않는 구조적 문제.
|
|
|
|
### 다음에 비슷한 작업할 때 주의할 점
|
|
|
|
- 새 POP 컴포넌트 추가 시 위 6곳 체크리스트를 반드시 확인
|
|
- 계획서 작성 시 "디자이너 연동" 단계를 별도 Step으로 포함
|
|
- 코딩 후 브라우저에서 실제 동작 확인 필수 (팔레트 노출, 드래그, 설정 패널)
|
|
- 장기적으로 디자이너가 PopComponentRegistry를 직접 읽도록 리팩토링 고려
|
|
|
|
---
|
|
|
|
## 수정된 파일 전체 목록
|
|
|
|
### 신규 생성 (15개)
|
|
|
|
```
|
|
frontend/lib/registry/pop-components/pop-dashboard/
|
|
├── index.tsx
|
|
├── PopDashboardComponent.tsx
|
|
├── PopDashboardConfig.tsx
|
|
├── PopDashboardPreview.tsx
|
|
├── items/
|
|
│ ├── KpiCard.tsx
|
|
│ ├── ChartItem.tsx
|
|
│ ├── GaugeItem.tsx
|
|
│ └── StatCard.tsx
|
|
├── modes/
|
|
│ ├── ArrowsMode.tsx
|
|
│ ├── AutoSlideMode.tsx
|
|
│ ├── GridMode.tsx
|
|
│ └── ScrollMode.tsx
|
|
└── utils/
|
|
├── formula.ts
|
|
└── dataFetcher.ts
|
|
```
|
|
|
|
### 수정 (6개)
|
|
|
|
| 파일 | 변경 |
|
|
|------|------|
|
|
| `pop-components/types.ts` | Phase 0 공통 + 대시보드 전용 타입 25개 추가 |
|
|
| `pop-components/index.ts` | `import "./pop-dashboard"` 1줄 추가 |
|
|
| `pop-text.tsx` | isRealtime 기본값 버그 수정 |
|
|
| `pop-layout.ts` | PopComponentType, DEFAULT_COMPONENT_GRID_SIZE 수정 |
|
|
| `ComponentPalette.tsx` | PALETTE_ITEMS에 대시보드 추가 |
|
|
| `PopRenderer.tsx` | COMPONENT_TYPE_LABELS에 대시보드 추가 |
|
|
|
|
---
|
|
|
|
---
|
|
|
|
### 4. pop-dashboard 페이지(슬라이드) 구조 재설계 (6단계 코딩)
|
|
|
|
기존 평면 아이템 리스트를 "페이지" 단위 독립 그리드 레이아웃으로 재구성:
|
|
|
|
| 단계 | 파일 | 핵심 내용 |
|
|
|------|------|----------|
|
|
| Step 1 | `types.ts` | `DashboardPage` 인터페이스 추가, `PopDashboardConfig`에서 grid* 속성 삭제 -> `pages` 추가 |
|
|
| Step 2 | `PopDashboardComponent.tsx` | `migrateConfig()` 함수 추가 (레거시 config 런타임 변환), 페이지 기반 렌더링으로 전환 |
|
|
| Step 3 | `PopDashboardPreview.tsx` | `migrateConfig` 적용, 첫 페이지 그리드 미리보기 + "N페이지" 배지 |
|
|
| Step 4 | `PopDashboardConfig.tsx` | "레이아웃" 탭 -> "페이지" 탭 교체, `PageEditor` 컴포넌트 신규, 아이템 삭제 시 모든 페이지 셀 정리 |
|
|
| Step 5 | `index.tsx` | defaultProps에서 `useGridLayout` 제거, `pages: []` 추가 |
|
|
| Step 6 | 린트 + 검수 | 린트 0, 중복 0, 잔여 참조 0 |
|
|
|
|
### 5. pop-dashboard 설정 패널 UI/UX 개선 (3건)
|
|
|
|
| 항목 | 파일 | 변경 |
|
|
|------|------|------|
|
|
| 아이템 라벨 인라인 편집 | `PopDashboardConfig.tsx` | `ItemEditor` 헤더의 `<span>` -> `<Input>` 교체, 확장 영역 중복 라벨 입력 제거 |
|
|
| 아이템 간격(gap) 의미 설명 | (대화에서 설명) | 페이지 내 그리드 셀 간격 (CSS Grid gap) |
|
|
| 페이지 탭 세로 스크롤 불가 | `ComponentEditorPanel.tsx` | Tabs/TabsContent에 `min-h-0` 추가 (Flexbox min-height:auto 문제) |
|
|
|
|
### 6. 설정 탭 스크롤 버그 수정
|
|
|
|
**문제**: POP 디자이너에서 대시보드 선택 -> 설정 탭 -> 페이지 3개 이상 추가 시 아래 잘림, 세로 스크롤 불가
|
|
|
|
**잘못된 접근**: `PopDashboardConfigPanel`(자식)에서 `flex h-full` / `overflow-y-auto` 시도 -> 부모 스크롤 깨짐
|
|
|
|
**근본 원인**: `ComponentEditorPanel.tsx`의 `Tabs`와 `TabsContent`에 `min-h-0` 누락. Flexbox에서 flex 자식의 기본 `min-height: auto`가 콘텐츠 축소를 막아 `overflow-auto` 미작동
|
|
|
|
**해결**: `ComponentEditorPanel.tsx` 수정
|
|
- `Tabs`에 `min-h-0` 추가
|
|
- `TabsList`에 `shrink-0` 추가
|
|
- 4개 `TabsContent`에 `min-h-0` 추가
|
|
|
|
---
|
|
|
|
## 이번 작업에서 배운 것
|
|
|
|
### 새로 알게 된 기술 개념: Flexbox min-height:auto 함정
|
|
|
|
Flexbox에서 `overflow-auto`가 작동하려면, 해당 요소와 **모든 flex 조상에 `min-h-0`(또는 `min-w-0`)이 필요**하다.
|
|
- `flex-1`만으로는 높이가 제한되지 않음
|
|
- flex 자식의 기본 `min-height: auto`가 콘텐츠 크기 이하로 축소를 막기 때문
|
|
- 스크롤 문제 발생 시 자식이 아니라 **부모 flex 체인부터 위로 추적**해야 함
|
|
|
|
### 에러 패턴: 잘못된 수정 위치
|
|
|
|
스크롤 문제를 자식 컴포넌트(`PopDashboardConfigPanel`)에서 해결하려고 시도했으나, 실제 문제는 부모(`ComponentEditorPanel.tsx`)의 높이 제약 전파 누락이었음.
|
|
- 부모가 높이를 확정해주지 않으면 자식의 `overflow` 설정은 무의미
|
|
- CSS 레이아웃 문제는 항상 **위에서 아래로** 추적
|
|
|
|
### 다음에 비슷한 작업할 때 주의할 점
|
|
|
|
- 스크롤 문제가 발생하면 DevTools에서 flex 체인의 각 노드에 `min-h-0`이 있는지 확인
|
|
- `overflow-auto`를 설정한 요소의 높이가 확정(px 또는 flex 제약)되어 있는지 확인
|
|
- Radix UI `TabsContent`의 기본 `flex-1`은 `min-h-0`을 포함하지 않으므로 수동 추가 필요
|
|
|
|
---
|
|
|
|
## 수정된 파일 (이번 대화 추가분)
|
|
|
|
| 파일 | 변경 |
|
|
|------|------|
|
|
| `ComponentEditorPanel.tsx` | Tabs/TabsList/TabsContent에 min-h-0, shrink-0 추가 (스크롤 수정) |
|
|
| `popdocs/PROBLEMS.md` | 설정 탭 스크롤 버그 상세 기록 추가 |
|
|
|
|
(이전 대화에서 이미 수정된 파일: types.ts, PopDashboardComponent.tsx, PopDashboardPreview.tsx, PopDashboardConfig.tsx, index.tsx)
|
|
|
|
---
|
|
|
|
## 다음 작업
|
|
|
|
- 브라우저에서 pop-dashboard 페이지 기반 동작 확인 (페이지 추가/삭제/편집)
|
|
- 기존 config 마이그레이션 정상 동작 확인
|
|
- 디자이너에서 설정 탭 스크롤 정상 동작 확인
|
|
- Phase 2: pop-button, pop-icon 구현
|
|
|
|
---
|
|
|
|
*작성: 2026-02-10 (오후 세션 추가)*
|
|
|
|
---
|
|
|
|
### 7. pop-dashboard 아이템 모드 완성 + 방어 로직 (야간 세션)
|
|
|
|
대시보드 컴포넌트의 4가지 아이템 모드(KPI, Chart, Gauge, Stat Card)가 실제 데이터와 연동되어 정상 작동하도록 설정 UI 보강, SQL 빌더 방어 로직, 렌더링 버그 수정을 수행.
|
|
|
|
#### 7-1. 설정 패널 UI 보강 (PopDashboardConfig.tsx)
|
|
|
|
| 항목 | 변경 |
|
|
|------|------|
|
|
| A-1: groupBy 설정 | DataSourceEditor에 "그룹핑(X축)" Combobox 추가. 집계 활성 시 X축 카테고리 컬럼 선택 가능 |
|
|
| A-2: 차트 축 설정 | Chart 아이템에 xAxisColumn / yAxisColumn 입력 필드 추가 |
|
|
| A-3: 통계 카드 카테고리 | StatCard에 카테고리 인라인 편집기 추가 (라벨/필터 조건/색상) |
|
|
|
|
#### 7-2. 뷰어 컴포넌트 로직 수정 (PopDashboardComponent.tsx)
|
|
|
|
| 항목 | 변경 |
|
|
|------|------|
|
|
| B-1: 차트 xAxisColumn 자동 보정 | groupBy 있으면 첫 번째 groupBy 컬럼을 xAxisColumn으로 자동 설정 |
|
|
| B-2: 통계 카드 카테고리 필터링 | rows를 카테고리별 filter 조건으로 필터링하여 독립 건수 계산 |
|
|
| useEffect 의존성 수정 | visibleItems 배열 참조 대신 visibleItemIds(JSON 문자열)로 안정화 |
|
|
|
|
#### 7-3. SQL 빌더 방어 로직 (dataFetcher.ts)
|
|
|
|
| 항목 | 변경 |
|
|
|------|------|
|
|
| C-1: validateDataSourceConfig | 테이블/컬럼/조인 미완료 상태에서 SQL 생성 차단 |
|
|
| buildWhereClause | 빈 컬럼명 필터 무시 (설정 중간 상태 방어) |
|
|
| buildAggregationSQL | COUNT 컬럼 없으면 COUNT(*), 불완전한 조인 건너뜀 |
|
|
| C-2: refreshInterval 최소값 | 5초 미만 설정 시 5초로 강제 |
|
|
|
|
#### 7-4. fetchTableColumns 수정 (dataFetcher.ts)
|
|
|
|
| 항목 | 변경 |
|
|
|------|------|
|
|
| API 우선순위 변경 | tableManagementApi(axios) 우선 시도, 실패 시 dashboardApi(fetch) 폴백 |
|
|
|
|
#### 7-5. 그리드 레이아웃 + 라벨 잘림 수정
|
|
|
|
| 항목 | 파일 | 변경 |
|
|
|------|------|------|
|
|
| 2열이 1열로 렌더링 | GridMode.tsx | MIN_CELL_WIDTH 160px -> 80px |
|
|
| 라벨 잘림 (truncate) | KpiCard.tsx | truncate 제거, text-[10px] -> text-xs, hidden 조건 제거 |
|
|
| 라벨 잘림 | GaugeItem.tsx | truncate 제거, hidden 조건 제거 |
|
|
| 라벨 잘림 | StatCard.tsx | truncate 제거, hidden 조건 제거 |
|
|
| 라벨 잘림 | ChartItem.tsx | truncate 제거, 폰트 크기 상향 |
|
|
| 패딩 부족 | 4개 아이템 모두 | p-2 -> p-3 (KPI/Gauge/Stat), p-1 -> p-2 (Chart) |
|
|
|
|
---
|
|
|
|
## 이번 작업에서 배운 것
|
|
|
|
### 에러 패턴: 불완전한 폼 상태가 백엔드 장애를 유발
|
|
|
|
대시보드 설정에서 집계 유형(SUM/AVG 등)만 선택하고 대상 컬럼을 아직 선택하지 않은 "중간 상태"에서 `SUM()`, `COUNT()` 같은 빈 괄호 SQL이 백엔드로 전송됨. 이 에러가 반복 발생하면 백엔드가 unhealthy 상태가 되고, 인증 API(/auth/me) 등 다른 요청도 30초 타임아웃 발생. 결과적으로 브라우저가 멈추는 증상.
|
|
|
|
**원인 체인**: 폼 중간 상태 -> 잘못된 SQL 생성 -> 백엔드 에러 폭주 -> API 타임아웃 -> 브라우저 멈춤
|
|
|
|
**해결**: `validateDataSourceConfig()` 함수로 SQL 생성 전 필수값 검증. 미완료 시 에러 메시지만 반환하고 SQL 전송 차단.
|
|
|
|
### 에러 패턴: CSS 반응형 열 축소 + 초기 containerWidth
|
|
|
|
`GridModeComponent`에서 `MIN_CELL_WIDTH = 160`으로 설정한 반응형 열 축소 로직이, 초기 `containerWidth = 300`(ResizeObserver 발동 전 기본값)에서 `(300-8)/2 = 146 < 160`으로 판단하여 2열을 1열로 강제 축소함. 사용자가 2열로 설정했는데 1열로 보이는 문제.
|
|
|
|
**해결**: MIN_CELL_WIDTH를 80px로 변경. 초기 300px 너비에서도 2열 유지.
|
|
|
|
### 에러 패턴: Tailwind truncate + Container Query 조합
|
|
|
|
`truncate` 클래스(text-overflow: ellipsis + overflow: hidden + white-space: nowrap)와 `@container` 기반 조건부 텍스트 크기(`@[150px]:text-xs`)를 함께 사용하면, 컨테이너가 작을 때 텍스트가 완전히 잘리거나 `hidden` 조건으로 아예 안 보일 수 있음. 대시보드처럼 셀 크기가 동적인 경우 `truncate`는 피하고, `hidden`도 최소한으로 사용해야 함.
|
|
|
|
### 다음에 비슷한 작업할 때 주의할 점
|
|
|
|
- 설정 폼에서 "중간 상태"(일부만 선택)를 항상 고려하고, SQL/API 호출 전에 `validate` 함수를 반드시 배치
|
|
- 반응형 열 축소 로직에서 초기 렌더링 시점의 containerWidth가 실제 크기가 아닐 수 있음 (ResizeObserver 지연)
|
|
- 아이템 컴포넌트 라벨에는 `truncate` 대신 줄바꿈을 허용하거나, 최소한 `text-xs` 이상의 폰트 크기 보장
|
|
- Docker `unhealthy` 상태가 반드시 서비스 장애를 의미하지 않음 - healthcheck 설정(curl 미설치 등) 확인 필요
|
|
|
|
---
|
|
|
|
## 수정된 파일 (야간 세션)
|
|
|
|
| 파일 | 변경 |
|
|
|------|------|
|
|
| `PopDashboardConfig.tsx` | groupBy Combobox, 차트 축 입력, 통계 카테고리 편집기 추가 |
|
|
| `PopDashboardComponent.tsx` | 차트 xAxisColumn 자동 보정, StatCard 카테고리 필터링, useEffect 의존성 안정화, refreshInterval 최소 5초 |
|
|
| `utils/dataFetcher.ts` | validateDataSourceConfig, buildWhereClause 빈 필터 무시, buildAggregationSQL COUNT(*) 처리, fetchTableColumns API 우선순위 변경 |
|
|
| `modes/GridMode.tsx` | MIN_CELL_WIDTH 160 -> 80 |
|
|
| `items/KpiCard.tsx` | truncate 제거, hidden 조건 제거, 폰트 크기 상향, p-2 -> p-3 |
|
|
| `items/GaugeItem.tsx` | truncate 제거, hidden 조건 제거, p-2 -> p-3 |
|
|
| `items/StatCard.tsx` | truncate 제거, hidden 조건 제거, p-2 -> p-3 |
|
|
| `items/ChartItem.tsx` | truncate 제거, 폰트 크기 상향, p-1 -> p-2 |
|
|
|
|
---
|
|
|
|
## 다음 작업
|
|
|
|
- 브라우저 새로고침 후 2열 레이아웃 + 라벨 표시 정상 확인
|
|
- 차트 groupBy / 통계카드 카테고리 동작 확인
|
|
- SQL 빌더 방어 로직 동작 확인 (설정 중간 상태에서 에러 없음)
|
|
- Phase 2: pop-button, pop-icon 계획 수립
|
|
|
|
---
|
|
|
|
*작성: 2026-02-10 (야간 세션 추가)*
|
|
|
|
---
|
|
|
|
### 8. pop-dashboard 차트/게이지/UI 디자인 개선 (심야 세션)
|
|
|
|
대시보드 컴포넌트의 차트 렌더링, 게이지 비율, 네비게이션 디자인, 카드 정렬 등 UX/UI 개선.
|
|
|
|
#### 8-1. 차트 데이터 및 렌더링 수정
|
|
|
|
| 항목 | 파일 | 변경 |
|
|
|------|------|------|
|
|
| apiClient 우선 사용 | dataFetcher.ts | `fetchAggregatedData`에서 apiClient(axios) 우선, dashboardApi(fetch) 폴백 |
|
|
| PostgreSQL bigint 문자열 변환 | dataFetcher.ts | 쿼리 결과 rows에서 숫자형 문자열을 `Number()`로 변환 (PieChart 필수) |
|
|
| 파이 차트 라벨/레전드 추가 | ChartItem.tsx | `Legend` 컴포넌트 추가, `label` 커스텀 포맷 (`name value (percent%)`) |
|
|
| X/Y축 입력 필드 제거 | PopDashboardConfig.tsx | 혼동 유발하는 수동 입력 제거, 자동 설정 안내 텍스트로 교체 |
|
|
|
|
#### 8-2. 게이지 설정/렌더링 수정
|
|
|
|
| 항목 | 파일 | 변경 |
|
|
|------|------|------|
|
|
| gaugeConfig 스프레드 순서 버그 | PopDashboardConfig.tsx | `...item.gaugeConfig`를 앞으로, 새 값(min/max/target)을 뒤로 배치. 이전: 새 값이 이전 값으로 덮어쓰임 |
|
|
| 게이지 SVG 비율 (가로 레이아웃) | GaugeItem.tsx | `max-w-[200px]` 고정 -> `h-full w-auto max-w-full` 높이 기반 스케일링. SVG 래퍼를 `flex-1 min-h-0`으로 변경 |
|
|
|
|
#### 8-3. 네비게이션 디자인 개선
|
|
|
|
| 항목 | 파일 | 변경 |
|
|
|------|------|------|
|
|
| 좌우 버튼 오버레이 | ArrowsMode.tsx | `px-12` 패딩 제거, 버튼이 콘텐츠 위에 겹침. `bg-background/70 backdrop-blur-sm` |
|
|
| 인디케이터 오버레이 | ArrowsMode.tsx, AutoSlideMode.tsx | 별도 영역 -> `absolute bottom-1`로 콘텐츠 하단에 겹침 |
|
|
| 상하 마진 불균형 해소 | ArrowsMode.tsx, AutoSlideMode.tsx | 버튼/인디케이터가 별도 영역 차지하지 않아 균형 맞춤 |
|
|
|
|
#### 8-4. 카드 정렬 통일
|
|
|
|
| 항목 | 파일 | 변경 |
|
|
|------|------|------|
|
|
| KPI 카드 가운데 정렬 | KpiCard.tsx | `items-center` 추가 (기존: 수직만 가운데) |
|
|
| 통계 카드 가운데 정렬 | StatCard.tsx | `items-center justify-center` 추가 (기존: 좌상단) |
|
|
|
|
---
|
|
|
|
## 이번 작업에서 배운 것
|
|
|
|
### 에러 패턴: JavaScript 스프레드 연산자 순서
|
|
|
|
```typescript
|
|
// 버그: 새 값이 이전 값으로 덮어쓰임
|
|
gaugeConfig: { max: newValue, ...item.gaugeConfig } // 이전 max가 새 max를 덮어씀
|
|
|
|
// 수정: 이전 값 먼저, 새 값 나중
|
|
gaugeConfig: { ...item.gaugeConfig, max: newValue } // 새 max가 이전 max를 덮어씀
|
|
```
|
|
|
|
JavaScript 객체 스프레드에서 **나중에 오는 속성이 우선**. 상태 업데이트 시 `...기존값`은 항상 **앞에**, 새 값은 **뒤에** 배치해야 한다.
|
|
|
|
### 에러 패턴: PostgreSQL bigint -> JS 문자열
|
|
|
|
PostgreSQL `COUNT()`, `SUM()` 반환값은 `bigint` 타입. Node.js `pg` 드라이버가 이를 **문자열**(`"79"`)로 변환. Recharts `BarChart`/`LineChart`는 문자열을 암묵적으로 처리하지만, `PieChart`는 명시적 숫자가 필수. 쿼리 결과를 UI에 전달하기 전에 `Number()` 변환 필수.
|
|
|
|
### 에러 패턴: fetch vs axios (iframe 컨텍스트)
|
|
|
|
Pop 대시보드가 iframe 내에서 렌더링될 때, `fetch` 기반 API(dashboardApi)가 간헐적으로 실패. `axios` 기반 `apiClient`는 인증 인터셉터와 세션 관리가 안정적이어서 우선 사용하고 `fetch`를 폴백으로 구성.
|
|
|
|
### 다음에 비슷한 작업할 때 주의할 점
|
|
|
|
- 상태 업데이트에서 스프레드 연산자 사용 시 순서 반드시 확인 (`...기존값` 먼저)
|
|
- PostgreSQL 집계 함수 결과를 프론트엔드에서 사용할 때 반드시 `Number()` 변환
|
|
- `fetch` vs `axios` 선택 시 iframe/인증 컨텍스트 고려
|
|
- 네비게이션 UI(버튼/인디케이터)는 `absolute` 오버레이가 공간 효율적
|
|
- 아이템 컴포넌트 정렬은 4개 모드(KPI/Chart/Gauge/Stat) 모두 통일해야 일관성 유지
|
|
|
|
---
|
|
|
|
## 수정된 파일 (심야 세션)
|
|
|
|
| 파일 | 변경 |
|
|
|------|------|
|
|
| `PopDashboardConfig.tsx` | gaugeConfig 스프레드 순서 수정, X/Y축 입력 제거 + 안내 텍스트 |
|
|
| `utils/dataFetcher.ts` | apiClient 우선 사용, bigint 문자열 -> 숫자 변환 |
|
|
| `items/ChartItem.tsx` | PieChart에 Legend/custom label 추가 |
|
|
| `items/GaugeItem.tsx` | SVG 스케일링 높이 기반으로 변경, 패딩 조정 |
|
|
| `items/KpiCard.tsx` | items-center 추가 (가운데 정렬) |
|
|
| `items/StatCard.tsx` | items-center justify-center 추가 (가운데 정렬) |
|
|
| `modes/ArrowsMode.tsx` | 좌우 버튼 + 인디케이터 오버레이 디자인 |
|
|
| `modes/AutoSlideMode.tsx` | 인디케이터 오버레이 디자인 |
|
|
|
|
---
|
|
|
|
## 다음 작업
|
|
|
|
- 게이지/통계카드 테스트 시나리오 동작 확인
|
|
- Phase 2: pop-button, pop-icon 계획 수립
|
|
|
|
---
|
|
|
|
## 9. 디자이너 캔버스 UX 개선
|
|
|
|
### 배경
|
|
|
|
사용자가 디자이너 캔버스와 실제 뷰어 간의 차이를 지적:
|
|
1. 디자이너에서 각 컴포넌트마다 5px 헤더 바가 표시되어 실제 뷰어와 다름
|
|
2. 대시보드가 더미 아이콘(PreviewComponent)으로만 표시됨 -> 실제 데이터 렌더링 요청
|
|
3. 헤더 제거 후 컴포넌트 식별이 어려워짐 -> 왼쪽 패널에 컴포넌트 목록 추가 요청
|
|
|
|
### 변경 사항
|
|
|
|
| 파일 | 변경 |
|
|
|------|------|
|
|
| `PopRenderer.tsx` | 디자인모드 헤더(5px) + 위치 정보 div 삭제. `PreviewComponent` 대신 `ActualComp`(실제 컴포넌트)로 렌더링. `pointer-events-none`으로 내부 클릭 차단 |
|
|
| `ComponentEditorPanel.tsx` | Props 3개 추가(`allComponents`, `onSelectComponent`, `selectedComponentId`). "위치" 탭에 배치된 컴포넌트 목록 UI 추가. `Layers` 아이콘 import. `COMPONENT_TYPE_LABELS` 타입 변경 + 키 보강 |
|
|
| `PopDesigner.tsx` | `ComponentEditorPanel`에 `allComponents={Object.values(layout.components)}`, `onSelectComponent={setSelectedComponentId}`, `selectedComponentId` 전달 |
|
|
|
|
### 검수에서 발견된 문제
|
|
|
|
| 문제 | 원인 | 해결 |
|
|
|------|------|------|
|
|
| `PopComponentType` 미사용 import | `COMPONENT_TYPE_LABELS` 타입을 `Record<string, string>`으로 변경하면서 유일한 참조 사라짐 | import에서 제거 |
|
|
|
|
### 이번 작업에서 배운 것
|
|
|
|
- **타입 변경 시 import 정리 필수**: 타입을 변경하거나 제거할 때, 해당 타입이 import된 것이라면 변경 후 파일 내 다른 참조가 남아있는지 Grep으로 확인해야 함
|
|
- **pointer-events-none 범위 주의**: 디자인 모드에서 내부 인터랙션만 차단하려면 `ComponentContent` 내부에만 적용. 부모 div의 onClick(컴포넌트 선택)은 정상 작동
|
|
- **React의 ActualComp 패턴**: 레지스트리에서 가져온 컴포넌트를 디자인 모드에서도 렌더링하면 마운트 시 API 호출이 발생할 수 있음. 현재는 refreshInterval/limit으로 제어되어 수용 가능
|
|
|
|
---
|
|
|
|
*작성: 2026-02-10 (디자이너 캔버스 UX 개선 세션 추가)*
|