From 1995c3dca453707244801f654e8df6b705ffff6a Mon Sep 17 00:00:00 2001 From: kjs Date: Wed, 17 Dec 2025 12:01:16 +0900 Subject: [PATCH] =?UTF-8?q?=EC=97=91=EC=85=80=20=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/controllers/adminController.ts | 33 +++++++++++-------- .../components/common/ExcelUploadModal.tsx | 27 ++++++++++++--- frontend/lib/api/tableSchema.ts | 1 + 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/backend-node/src/controllers/adminController.ts b/backend-node/src/controllers/adminController.ts index a28712c1..c8e8ce82 100644 --- a/backend-node/src/controllers/adminController.ts +++ b/backend-node/src/controllers/adminController.ts @@ -3245,6 +3245,7 @@ export const resetUserPassword = async ( /** * 테이블 스키마 조회 (엑셀 업로드 컬럼 매핑용) + * column_labels 테이블에서 라벨 정보도 함께 가져옴 */ export async function getTableSchema( req: AuthenticatedRequest, @@ -3264,20 +3265,25 @@ export async function getTableSchema( logger.info("테이블 스키마 조회", { tableName, companyCode }); - // information_schema에서 컬럼 정보 가져오기 + // information_schema와 column_labels를 JOIN하여 컬럼 정보와 라벨 정보 함께 가져오기 const schemaQuery = ` SELECT - column_name, - data_type, - is_nullable, - column_default, - character_maximum_length, - numeric_precision, - numeric_scale - FROM information_schema.columns - WHERE table_schema = 'public' - AND table_name = $1 - ORDER BY ordinal_position + ic.column_name, + ic.data_type, + ic.is_nullable, + ic.column_default, + ic.character_maximum_length, + ic.numeric_precision, + ic.numeric_scale, + cl.column_label, + cl.display_order + FROM information_schema.columns ic + LEFT JOIN column_labels cl + ON cl.table_name = ic.table_name + AND cl.column_name = ic.column_name + WHERE ic.table_schema = 'public' + AND ic.table_name = $1 + ORDER BY COALESCE(cl.display_order, ic.ordinal_position), ic.ordinal_position `; const columns = await query(schemaQuery, [tableName]); @@ -3290,9 +3296,10 @@ export async function getTableSchema( return; } - // 컬럼 정보를 간단한 형태로 변환 + // 컬럼 정보를 간단한 형태로 변환 (라벨 정보 포함) const columnList = columns.map((col: any) => ({ name: col.column_name, + label: col.column_label || col.column_name, // 라벨이 없으면 컬럼명 사용 type: col.data_type, nullable: col.is_nullable === "YES", default: col.column_default, diff --git a/frontend/components/common/ExcelUploadModal.tsx b/frontend/components/common/ExcelUploadModal.tsx index 0f080bcc..5f021daa 100644 --- a/frontend/components/common/ExcelUploadModal.tsx +++ b/frontend/components/common/ExcelUploadModal.tsx @@ -236,13 +236,23 @@ export const ExcelUploadModal: React.FC = ({ } }; - // 자동 매핑 + // 자동 매핑 - 컬럼명과 라벨 모두 비교 const handleAutoMapping = () => { const newMappings = excelColumns.map((excelCol) => { - const matchedSystemCol = systemColumns.find( - (sysCol) => sysCol.name.toLowerCase() === excelCol.toLowerCase() + const normalizedExcelCol = excelCol.toLowerCase().trim(); + + // 1. 먼저 라벨로 매칭 시도 + let matchedSystemCol = systemColumns.find( + (sysCol) => sysCol.label && sysCol.label.toLowerCase().trim() === normalizedExcelCol ); + // 2. 라벨로 매칭되지 않으면 컬럼명으로 매칭 시도 + if (!matchedSystemCol) { + matchedSystemCol = systemColumns.find( + (sysCol) => sysCol.name.toLowerCase().trim() === normalizedExcelCol + ); + } + return { excelColumn: excelCol, systemColumn: matchedSystemCol ? matchedSystemCol.name : null, @@ -734,7 +744,14 @@ export const ExcelUploadModal: React.FC = ({ } > - + + {mapping.systemColumn + ? (() => { + const col = systemColumns.find(c => c.name === mapping.systemColumn); + return col?.label || mapping.systemColumn; + })() + : "매핑 안함"} + @@ -746,7 +763,7 @@ export const ExcelUploadModal: React.FC = ({ value={col.name} className="text-xs sm:text-sm" > - {col.name} ({col.type}) + {col.label || col.name} ({col.type}) ))} diff --git a/frontend/lib/api/tableSchema.ts b/frontend/lib/api/tableSchema.ts index 6e04187f..1d173804 100644 --- a/frontend/lib/api/tableSchema.ts +++ b/frontend/lib/api/tableSchema.ts @@ -2,6 +2,7 @@ import { apiClient } from "./client"; export interface TableColumn { name: string; + label: string; // 컬럼 라벨 (column_labels 테이블에서 가져옴) type: string; nullable: boolean; default: string | null;