diff --git a/frontend/lib/registry/components/universal-form-modal/TableSectionRenderer.tsx b/frontend/lib/registry/components/universal-form-modal/TableSectionRenderer.tsx index 9c238b47..4f872bc1 100644 --- a/frontend/lib/registry/components/universal-form-modal/TableSectionRenderer.tsx +++ b/frontend/lib/registry/components/universal-form-modal/TableSectionRenderer.tsx @@ -385,6 +385,9 @@ export function TableSectionRenderer({ // 소스 테이블의 카테고리 타입 컬럼 목록 const [sourceCategoryColumns, setSourceCategoryColumns] = useState([]); + // 소스 테이블의 컬럼 라벨 (API에서 동적 로드) + const [sourceColumnLabels, setSourceColumnLabels] = useState>({}); + // 소스 테이블의 카테고리 타입 컬럼 목록 로드 useEffect(() => { const loadCategoryColumns = async () => { @@ -410,6 +413,44 @@ export function TableSectionRenderer({ loadCategoryColumns(); }, [tableConfig.source.tableName]); + // 소스 테이블의 컬럼 라벨 로드 (source.columnLabels가 비어있을 때만) + useEffect(() => { + const loadColumnLabels = async () => { + const sourceTableName = tableConfig.source.tableName; + if (!sourceTableName) return; + + // 이미 source.columnLabels가 설정되어 있으면 스킵 + if (tableConfig.source.columnLabels && Object.keys(tableConfig.source.columnLabels).length > 0) { + return; + } + + try { + const response = await apiClient.get(`/table-management/tables/${sourceTableName}/columns`); + + if (response.data?.success && response.data.data) { + const columnsData = response.data.data.columns || response.data.data || []; + const labels: Record = {}; + + for (const col of columnsData) { + const colName = col.column_name || col.columnName; + // displayName: API에서 반환하는 라벨 (COALESCE(cl.column_label, c.column_name)) + const colLabel = col.displayName || col.column_label || col.columnLabel || col.comment; + // 라벨이 컬럼명과 다를 때만 저장 (의미있는 라벨인 경우) + if (colName && colLabel && colLabel !== colName) { + labels[colName] = colLabel; + } + } + + setSourceColumnLabels(labels); + } + } catch (error) { + console.error("소스 테이블 컬럼 라벨 조회 실패:", error); + } + }; + + loadColumnLabels(); + }, [tableConfig.source.tableName, tableConfig.source.columnLabels]); + // 조건부 테이블: 동적 옵션 로드 (optionSource 설정이 있는 경우) useEffect(() => { if (!isConditionalMode) return; @@ -1305,7 +1346,12 @@ export function TableSectionRenderer({ const sourceTable = source.tableName; const sourceColumns = source.displayColumns; const sourceSearchFields = source.searchColumns; - const columnLabels = source.columnLabels || {}; + // 컬럼 라벨: source.columnLabels가 있으면 우선 사용, 없으면 동적 로드된 라벨 사용 + const columnLabels = useMemo(() => { + const configLabels = source.columnLabels || {}; + // 설정된 라벨이 있으면 설정 우선, 없으면 API에서 로드한 라벨 사용 + return { ...sourceColumnLabels, ...configLabels }; + }, [source.columnLabels, sourceColumnLabels]); const modalTitle = uiConfig?.modalTitle || "항목 검색 및 선택"; const multiSelect = uiConfig?.multiSelect ?? true;