# 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` 헤더의 `` -> `` 교체, 확장 영역 중복 라벨 입력 제거 | | 아이템 간격(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`으로 변경하면서 유일한 참조 사라짐 | import에서 제거 | ### 이번 작업에서 배운 것 - **타입 변경 시 import 정리 필수**: 타입을 변경하거나 제거할 때, 해당 타입이 import된 것이라면 변경 후 파일 내 다른 참조가 남아있는지 Grep으로 확인해야 함 - **pointer-events-none 범위 주의**: 디자인 모드에서 내부 인터랙션만 차단하려면 `ComponentContent` 내부에만 적용. 부모 div의 onClick(컴포넌트 선택)은 정상 작동 - **React의 ActualComp 패턴**: 레지스트리에서 가져온 컴포넌트를 디자인 모드에서도 렌더링하면 마운트 시 API 호출이 발생할 수 있음. 현재는 refreshInterval/limit으로 제어되어 수용 가능 --- *작성: 2026-02-10 (디자이너 캔버스 UX 개선 세션 추가)*