From 25b7e637de6ec0fc23d6370c5c9ad06601a94ba2 Mon Sep 17 00:00:00 2001 From: SeongHyun Kim Date: Tue, 6 Jan 2026 15:29:26 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=A0=80=EC=9E=A5=20=EC=8B=9C=20=EC=A1=B4?= =?UTF-8?q?=EC=9E=AC=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=BB=AC?= =?UTF-8?q?=EB=9F=BC=20=EC=9E=90=EB=8F=99=20=ED=95=84=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - tableManagementService.addTableData: 테이블 스키마 기반 컬럼 필터링 로직 추가 - 무시된 컬럼 정보를 API 응답에 포함 (skippedColumns, savedColumns) - 프론트엔드 콘솔에 무시된 컬럼 경고 출력 - conditional-container의 UI 제어용 필드(condition) 등으로 인한 저장 에러 방지 --- .../controllers/tableManagementController.ts | 16 +++++-- .../src/services/tableManagementService.ts | 48 +++++++++++++++++-- frontend/lib/utils/buttonActions.ts | 7 +++ 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/backend-node/src/controllers/tableManagementController.ts b/backend-node/src/controllers/tableManagementController.ts index 83384be6..9b3d81a2 100644 --- a/backend-node/src/controllers/tableManagementController.ts +++ b/backend-node/src/controllers/tableManagementController.ts @@ -901,13 +901,23 @@ export async function addTableData( } // 데이터 추가 - await tableManagementService.addTableData(tableName, data); + const result = await tableManagementService.addTableData(tableName, data); logger.info(`테이블 데이터 추가 완료: ${tableName}`); - const response: ApiResponse = { + // 무시된 컬럼이 있으면 경고 정보 포함 + const response: ApiResponse<{ + skippedColumns?: string[]; + savedColumns?: string[]; + }> = { success: true, - message: "테이블 데이터를 성공적으로 추가했습니다.", + message: result.skippedColumns.length > 0 + ? `테이블 데이터를 추가했습니다. (무시된 컬럼 ${result.skippedColumns.length}개: ${result.skippedColumns.join(", ")})` + : "테이블 데이터를 성공적으로 추가했습니다.", + data: { + skippedColumns: result.skippedColumns.length > 0 ? result.skippedColumns : undefined, + savedColumns: result.savedColumns, + }, }; res.status(201).json(response); diff --git a/backend-node/src/services/tableManagementService.ts b/backend-node/src/services/tableManagementService.ts index 8ac5989b..98db1eee 100644 --- a/backend-node/src/services/tableManagementService.ts +++ b/backend-node/src/services/tableManagementService.ts @@ -2261,11 +2261,12 @@ export class TableManagementService { /** * 테이블에 데이터 추가 + * @returns 무시된 컬럼 정보 (디버깅용) */ async addTableData( tableName: string, data: Record - ): Promise { + ): Promise<{ skippedColumns: string[]; savedColumns: string[] }> { try { logger.info(`=== 테이블 데이터 추가 시작: ${tableName} ===`); logger.info(`추가할 데이터:`, data); @@ -2296,10 +2297,41 @@ export class TableManagementService { logger.info(`created_date 자동 추가: ${data.created_date}`); } - // 컬럼명과 값을 분리하고 타입에 맞게 변환 - const columns = Object.keys(data); - const values = Object.values(data).map((value, index) => { - const columnName = columns[index]; + // 🆕 테이블에 존재하는 컬럼만 필터링 (존재하지 않는 컬럼은 무시) + const skippedColumns: string[] = []; + const existingColumns = Object.keys(data).filter((col) => { + const exists = columnTypeMap.has(col); + if (!exists) { + skippedColumns.push(col); + } + return exists; + }); + + // 무시된 컬럼이 있으면 경고 로그 출력 + if (skippedColumns.length > 0) { + logger.warn( + `⚠️ [${tableName}] 테이블에 존재하지 않는 컬럼 ${skippedColumns.length}개 무시됨: ${skippedColumns.join(", ")}` + ); + logger.warn( + `⚠️ [${tableName}] 무시된 컬럼 상세:`, + skippedColumns.map((col) => ({ column: col, value: data[col] })) + ); + } + + if (existingColumns.length === 0) { + throw new Error( + `저장할 유효한 컬럼이 없습니다. 테이블: ${tableName}, 전달된 컬럼: ${Object.keys(data).join(", ")}` + ); + } + + logger.info( + `✅ [${tableName}] 저장될 컬럼 ${existingColumns.length}개: ${existingColumns.join(", ")}` + ); + + // 컬럼명과 값을 분리하고 타입에 맞게 변환 (존재하는 컬럼만) + const columns = existingColumns; + const values = columns.map((columnName) => { + const value = data[columnName]; const dataType = columnTypeMap.get(columnName) || "text"; const convertedValue = this.convertValueForPostgreSQL(value, dataType); logger.info( @@ -2355,6 +2387,12 @@ export class TableManagementService { await query(insertQuery, values); logger.info(`테이블 데이터 추가 완료: ${tableName}`); + + // 무시된 컬럼과 저장된 컬럼 정보 반환 + return { + skippedColumns, + savedColumns: existingColumns, + }; } catch (error) { logger.error(`테이블 데이터 추가 오류: ${tableName}`, error); throw error; diff --git a/frontend/lib/utils/buttonActions.ts b/frontend/lib/utils/buttonActions.ts index e9327082..9b847ef3 100644 --- a/frontend/lib/utils/buttonActions.ts +++ b/frontend/lib/utils/buttonActions.ts @@ -1063,6 +1063,13 @@ export class ButtonActionExecutor { dataWithMeta, ); console.log("✅ [handleSave] RepeaterFieldGroup INSERT 완료:", insertResult.data); + // 무시된 컬럼이 있으면 경고 출력 + if (insertResult.data?.data?.skippedColumns?.length > 0) { + console.warn( + `⚠️ [${repeaterTargetTable}] 테이블에 존재하지 않는 컬럼이 무시됨:`, + insertResult.data.data.skippedColumns, + ); + } } else if (item.id) { // UPDATE (기존 항목) const originalData = { id: item.id };