From 8c08e7f8e98394f1a28351b65134becaccebd4d2 Mon Sep 17 00:00:00 2001
From: SeongHyun Kim
Date: Thu, 12 Feb 2026 09:19:17 +0900
Subject: [PATCH] =?UTF-8?q?fix(pop-dashboard):=20=EC=A7=91=EA=B3=84=20?=
=?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=84=A4=EC=A0=95=20=EC=9C=A0=ED=9A=A8?=
=?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=A6=9D=20=EA=B0=95=ED=99=94=20-=20?=
=?UTF-8?q?=EB=AC=B8=EC=9E=90=EC=97=B4=20=EC=BB=AC=EB=9F=BC=EC=97=90=20SUM?=
=?UTF-8?q?=20=EC=A0=81=EC=9A=A9=20=EB=B0=A9=EC=A7=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
팀원 pull 후 대시보드 500 에러 발생 원인 해결:
- subType별 허용 집계 함수 제한 (stat-card는 COUNT만)
- SUM/AVG 선택 시 숫자 타입 컬럼만 표시
- 비호환 집계 함수 선택 시 컬럼 자동 초기화
- subType 변경 시 비호환 aggregation 자동 전환 (STEP 7.5)
- chart 모드 groupBy 미설정 경고 추가
Co-authored-by: Cursor
---
.../pop-dashboard/PopDashboardConfig.tsx | 119 +++-
popdocs/PLAN.md | 630 ++++++++++--------
popdocs/STATUS.md | 27 +-
3 files changed, 474 insertions(+), 302 deletions(-)
diff --git a/frontend/lib/registry/pop-components/pop-dashboard/PopDashboardConfig.tsx b/frontend/lib/registry/pop-components/pop-dashboard/PopDashboardConfig.tsx
index 52f18d27..f64e09ae 100644
--- a/frontend/lib/registry/pop-components/pop-dashboard/PopDashboardConfig.tsx
+++ b/frontend/lib/registry/pop-components/pop-dashboard/PopDashboardConfig.tsx
@@ -60,6 +60,7 @@ import type {
JoinConfig,
JoinType,
ItemStyleConfig,
+ AggregationType,
} from "../types";
import {
TEXT_ALIGN_LABELS,
@@ -132,6 +133,50 @@ const JOIN_TYPE_LABELS: Record = {
right: "RIGHT JOIN",
};
+// ===== 집계 함수 유효성 검증 유틸 =====
+
+// 아이템 타입별 사용 가능한 집계 함수
+const SUBTYPE_AGGREGATION_MAP: Record = {
+ "kpi-card": ["count", "sum", "avg", "min", "max"],
+ chart: ["count", "sum", "avg", "min", "max"],
+ gauge: ["count", "sum", "avg", "min", "max"],
+ "stat-card": ["count"],
+};
+
+// 집계 함수 라벨
+const AGGREGATION_LABELS: Record = {
+ count: "건수 (COUNT)",
+ sum: "합계 (SUM)",
+ avg: "평균 (AVG)",
+ min: "최소 (MIN)",
+ max: "최대 (MAX)",
+};
+
+// 숫자 전용 집계 함수 (숫자 컬럼에만 사용 가능)
+const NUMERIC_ONLY_AGGREGATIONS: AggregationType[] = ["sum", "avg"];
+
+// PostgreSQL 숫자 타입 판별용 패턴
+const NUMERIC_TYPE_PATTERNS = [
+ "int", "integer", "bigint", "smallint",
+ "numeric", "decimal", "real", "double",
+ "float", "serial", "bigserial", "smallserial",
+ "money", "number",
+];
+
+/** 컬럼이 숫자 타입인지 판별 */
+function isNumericColumn(col: ColumnInfo): boolean {
+ const t = (col.type || "").toLowerCase();
+ const u = (col.udtName || "").toLowerCase();
+ return NUMERIC_TYPE_PATTERNS.some(
+ (pattern) => t.includes(pattern) || u.includes(pattern)
+ );
+}
+
+/** 현재 집계 함수가 숫자 전용(sum/avg)인지 판별 */
+function isNumericOnlyAggregation(aggType: string | undefined): boolean {
+ return !!aggType && NUMERIC_ONLY_AGGREGATIONS.includes(aggType as AggregationType);
+}
+
const FILTER_OPERATOR_LABELS: Record = {
"=": "같음 (=)",
"!=": "다름 (!=)",
@@ -149,9 +194,11 @@ const FILTER_OPERATOR_LABELS: Record = {
function DataSourceEditor({
dataSource,
onChange,
+ subType,
}: {
dataSource: DataSourceConfig;
onChange: (ds: DataSourceConfig) => void;
+ subType?: DashboardSubType;
}) {
// 테이블 목록 (Combobox용)
const [tables, setTables] = useState([]);
@@ -268,7 +315,15 @@ function DataSourceEditor({
@@ -331,10 +390,15 @@ function DataSourceEditor({
/>
- 컬럼을 찾을 수 없습니다.
+ {isNumericOnlyAggregation(dataSource.aggregation?.type)
+ ? "숫자 타입 컬럼이 없습니다."
+ : "컬럼을 찾을 수 없습니다."}
- {columns.map((col) => (
+ {(isNumericOnlyAggregation(dataSource.aggregation?.type)
+ ? columns.filter(isNumericColumn)
+ : columns
+ ).map((col) => (
차트에서 X축 카테고리로 사용됩니다
+ {subType === "chart" && !dataSource.aggregation?.groupBy?.length && (
+
+ 차트 모드에서는 그룹핑(X축)을 설정해야 의미 있는 차트가 표시됩니다
+
+ )}
)}
@@ -1144,9 +1213,30 @@ function ItemEditor({