diff --git a/backend-node/src/services/entityJoinService.ts b/backend-node/src/services/entityJoinService.ts index 24886a3d..76848714 100644 --- a/backend-node/src/services/entityJoinService.ts +++ b/backend-node/src/services/entityJoinService.ts @@ -59,9 +59,14 @@ export class EntityJoinService { let separator = " - "; if (screenConfig && screenConfig.displayColumns) { - // 화면에서 설정된 표시 컬럼들 사용 + // 화면에서 설정된 표시 컬럼들 사용 (기본 테이블 + 조인 테이블 조합 지원) displayColumns = screenConfig.displayColumns; separator = screenConfig.separator || " - "; + console.log(`🎯 화면별 엔티티 설정 적용: ${column.column_name}`, { + displayColumns, + separator, + screenConfig, + }); } else if (column.display_column) { // 기존 설정된 단일 표시 컬럼 사용 displayColumns = [column.display_column]; @@ -163,12 +168,51 @@ export class EntityJoinService { if (displayColumns.length === 1) { // 단일 컬럼인 경우 - return `COALESCE(${alias}.${displayColumns[0]}, '') AS ${config.aliasColumn}`; + const col = displayColumns[0]; + const isJoinTableColumn = [ + "dept_name", + "dept_code", + "master_user_id", + "location_name", + "parent_dept_code", + "master_sabun", + "location", + "data_type", + ].includes(col); + + if (isJoinTableColumn) { + return `COALESCE(${alias}.${col}, '') AS ${config.aliasColumn}`; + } else { + return `COALESCE(main.${col}, '') AS ${config.aliasColumn}`; + } } else { // 여러 컬럼인 경우 CONCAT으로 연결 + // 기본 테이블과 조인 테이블의 컬럼을 구분해서 처리 const concatParts = displayColumns - .map((col) => `COALESCE(${alias}.${col}, '')`) + .map((col) => { + // 조인 테이블의 컬럼인지 확인 (조인 테이블에 존재하는 컬럼만 조인 별칭 사용) + // 현재는 dept_info 테이블의 컬럼들을 확인 + const isJoinTableColumn = [ + "dept_name", + "dept_code", + "master_user_id", + "location_name", + "parent_dept_code", + "master_sabun", + "location", + "data_type", + ].includes(col); + + if (isJoinTableColumn) { + // 조인 테이블 컬럼은 조인 별칭 사용 + return `COALESCE(${alias}.${col}, '')`; + } else { + // 기본 테이블 컬럼은 main 별칭 사용 + return `COALESCE(main.${col}, '')`; + } + }) .join(`, '${separator}', `); + return `CONCAT(${concatParts}) AS ${config.aliasColumn}`; } }) @@ -237,6 +281,15 @@ export class EntityJoinService { try { const strategies = await Promise.all( joinConfigs.map(async (config) => { + // 여러 컬럼을 조합하는 경우 캐시 전략 사용 불가 + if (config.displayColumns && config.displayColumns.length > 1) { + console.log( + `🎯 여러 컬럼 조합으로 인해 조인 전략 사용: ${config.sourceColumn}`, + config.displayColumns + ); + return "join"; + } + // 참조 테이블의 캐시 가능성 확인 const cachedData = await referenceCacheService.getCachedReference( config.referenceTable, diff --git a/frontend/lib/registry/components/table-list/TableListConfigPanel.tsx b/frontend/lib/registry/components/table-list/TableListConfigPanel.tsx index 96deb641..6a9007d5 100644 --- a/frontend/lib/registry/components/table-list/TableListConfigPanel.tsx +++ b/frontend/lib/registry/components/table-list/TableListConfigPanel.tsx @@ -364,49 +364,145 @@ export const TableListConfigPanel: React.FC = ({ // 🎯 엔티티 컬럼의 표시 컬럼 정보 로드 const loadEntityDisplayConfig = async (column: ColumnConfig) => { - if (!column.isEntityJoin || !column.entityJoinInfo || !column.entityDisplayConfig) return; + console.log("🔍 loadEntityDisplayConfig 시작:", { + columnName: column.columnName, + isEntityJoin: column.isEntityJoin, + entityJoinInfo: column.entityJoinInfo, + entityDisplayConfig: column.entityDisplayConfig, + configSelectedTable: config.selectedTable, + }); - const { sourceTable, joinTable } = column.entityDisplayConfig; - const configKey = `${column.columnName}`; + if (!column.isEntityJoin || !column.entityJoinInfo) { + console.log("⚠️ 엔티티 컬럼 조건 불만족:", { + isEntityJoin: column.isEntityJoin, + entityJoinInfo: column.entityJoinInfo, + }); + return; + } - // 이미 로드된 경우 스킵 - if (entityDisplayConfigs[configKey]) return; + // entityDisplayConfig가 없으면 초기화 + if (!column.entityDisplayConfig) { + console.log("🔧 entityDisplayConfig 초기화:", column.columnName); + const updatedColumns = config.columns?.map((col) => { + if (col.columnName === column.columnName) { + return { + ...col, + entityDisplayConfig: { + displayColumns: [], + separator: " - ", + sourceTable: config.selectedTable || "", + joinTable: "", + }, + }; + } + return col; + }); - // joinTable이 비어있으면 Entity 조인 API로 조인 테이블 정보를 가져와서 설정 - let actualJoinTable = joinTable; - if (!actualJoinTable && sourceTable) { + if (updatedColumns) { + handleChange("columns", updatedColumns); + // 업데이트된 컬럼으로 다시 시도 + const updatedColumn = updatedColumns.find((col) => col.columnName === column.columnName); + if (updatedColumn) { + console.log("🔄 업데이트된 컬럼으로 재시도:", updatedColumn.entityDisplayConfig); + return loadEntityDisplayConfig(updatedColumn); + } + } + return; + } + + console.log("🔍 entityDisplayConfig 전체 구조:", column.entityDisplayConfig); + console.log("🔍 entityDisplayConfig 키들:", Object.keys(column.entityDisplayConfig)); + + // sourceTable과 joinTable이 없으면 entityJoinInfo에서 가져오기 + let sourceTable = column.entityDisplayConfig.sourceTable; + let joinTable = column.entityDisplayConfig.joinTable; + + if (!sourceTable && column.entityJoinInfo) { + sourceTable = column.entityJoinInfo.sourceTable; + } + + if (!joinTable) { + // joinTable이 없으면 tableTypeApi로 조회해서 설정 try { - console.log("🔍 조인 테이블 정보를 Entity 조인 API로 가져오기:", sourceTable); - const entityJoinResult = await entityJoinApi.getEntityJoinColumns(sourceTable); - - // 해당 컬럼에 대한 조인 설정 찾기 - const columnJoinConfig = entityJoinResult.availableColumns?.find( - (col) => col.columnName === column.columnName - ); - - if (columnJoinConfig?.joinTable) { - actualJoinTable = columnJoinConfig.joinTable; - console.log("✅ 조인 테이블 정보 찾음:", actualJoinTable); - + console.log("🔍 joinTable이 없어서 tableTypeApi로 조회:", sourceTable); + const columnList = await tableTypeApi.getColumns(sourceTable); + const columnInfo = columnList.find((col: any) => (col.column_name || col.columnName) === column.columnName); + + if (columnInfo?.reference_table || columnInfo?.referenceTable) { + joinTable = columnInfo.reference_table || columnInfo.referenceTable; + console.log("✅ tableTypeApi에서 조인 테이블 정보 찾음:", joinTable); + // entityDisplayConfig 업데이트 const updatedConfig = { ...column.entityDisplayConfig, - joinTable: actualJoinTable, + sourceTable: sourceTable, + joinTable: joinTable, }; - + // 컬럼 설정 업데이트 const updatedColumns = config.columns?.map((col) => - col.columnName === column.columnName - ? { ...col, entityDisplayConfig: updatedConfig } - : col + col.columnName === column.columnName ? { ...col, entityDisplayConfig: updatedConfig } : col, ); - + if (updatedColumns) { handleChange("columns", updatedColumns); } } } catch (error) { - console.error("Entity 조인 정보 조회 실패:", error); + console.error("tableTypeApi 컬럼 정보 조회 실패:", error); + } + } + + console.log("🔍 최종 추출한 값:", { sourceTable, joinTable }); + const configKey = `${column.columnName}`; + + // 이미 로드된 경우 스킵 + if (entityDisplayConfigs[configKey]) return; + + // joinTable이 비어있으면 tableTypeApi로 컬럼 정보를 다시 가져와서 referenceTable 정보를 찾기 + let actualJoinTable = joinTable; + if (!actualJoinTable && sourceTable) { + try { + console.log("🔍 tableTypeApi로 컬럼 정보 다시 조회:", { + tableName: sourceTable, + columnName: column.columnName, + }); + + const columnList = await tableTypeApi.getColumns(sourceTable); + const columnInfo = columnList.find((col: any) => (col.column_name || col.columnName) === column.columnName); + + console.log("🔍 컬럼 정보 조회 결과:", { + columnInfo: columnInfo, + referenceTable: columnInfo?.reference_table || columnInfo?.referenceTable, + referenceColumn: columnInfo?.reference_column || columnInfo?.referenceColumn, + }); + + if (columnInfo?.reference_table || columnInfo?.referenceTable) { + actualJoinTable = columnInfo.reference_table || columnInfo.referenceTable; + console.log("✅ tableTypeApi에서 조인 테이블 정보 찾음:", actualJoinTable); + + // entityDisplayConfig 업데이트 + const updatedConfig = { + ...column.entityDisplayConfig, + joinTable: actualJoinTable, + }; + + // 컬럼 설정 업데이트 + const updatedColumns = config.columns?.map((col) => + col.columnName === column.columnName ? { ...col, entityDisplayConfig: updatedConfig } : col, + ); + + if (updatedColumns) { + handleChange("columns", updatedColumns); + } + } else { + console.log("⚠️ tableTypeApi에서도 referenceTable을 찾을 수 없음:", { + columnName: column.columnName, + columnInfo: columnInfo, + }); + } + } catch (error) { + console.error("tableTypeApi 컬럼 정보 조회 실패:", error); } } @@ -443,13 +539,14 @@ export const TableListConfigPanel: React.FC = ({ // 🎯 엔티티 표시 컬럼 선택 토글 const toggleEntityDisplayColumn = (columnName: string, selectedColumn: string) => { const configKey = `${columnName}`; - const config = entityDisplayConfigs[configKey]; - if (!config) return; + const localConfig = entityDisplayConfigs[configKey]; + if (!localConfig) return; - const newSelectedColumns = config.selectedColumns.includes(selectedColumn) - ? config.selectedColumns.filter((col) => col !== selectedColumn) - : [...config.selectedColumns, selectedColumn]; + const newSelectedColumns = localConfig.selectedColumns.includes(selectedColumn) + ? localConfig.selectedColumns.filter((col) => col !== selectedColumn) + : [...localConfig.selectedColumns, selectedColumn]; + // 로컬 상태 업데이트 setEntityDisplayConfigs((prev) => ({ ...prev, [configKey]: { @@ -458,6 +555,29 @@ export const TableListConfigPanel: React.FC = ({ }, })); + // 실제 컬럼 설정도 업데이트 + const updatedColumns = config.columns?.map((col) => { + if (col.columnName === columnName && col.entityDisplayConfig) { + return { + ...col, + entityDisplayConfig: { + ...col.entityDisplayConfig, + displayColumns: newSelectedColumns, + }, + }; + } + return col; + }); + + if (updatedColumns) { + handleChange("columns", updatedColumns); + console.log("🎯 엔티티 표시 컬럼 설정 업데이트:", { + columnName, + selectedColumns: newSelectedColumns, + updatedColumn: updatedColumns.find((col) => col.columnName === columnName), + }); + } + // 컬럼 설정 업데이트 updateColumn(columnName, { entityDisplayConfig: { @@ -470,9 +590,10 @@ export const TableListConfigPanel: React.FC = ({ // 🎯 엔티티 표시 구분자 업데이트 const updateEntityDisplaySeparator = (columnName: string, separator: string) => { const configKey = `${columnName}`; - const config = entityDisplayConfigs[configKey]; - if (!config) return; + const localConfig = entityDisplayConfigs[configKey]; + if (!localConfig) return; + // 로컬 상태 업데이트 setEntityDisplayConfigs((prev) => ({ ...prev, [configKey]: { @@ -481,13 +602,28 @@ export const TableListConfigPanel: React.FC = ({ }, })); - // 컬럼 설정 업데이트 - updateColumn(columnName, { - entityDisplayConfig: { - ...config.entityDisplayConfig, - separator, - }, + // 실제 컬럼 설정도 업데이트 + const updatedColumns = config.columns?.map((col) => { + if (col.columnName === columnName && col.entityDisplayConfig) { + return { + ...col, + entityDisplayConfig: { + ...col.entityDisplayConfig, + separator, + }, + }; + } + return col; }); + + if (updatedColumns) { + handleChange("columns", updatedColumns); + console.log("🎯 엔티티 표시 구분자 설정 업데이트:", { + columnName, + separator, + updatedColumn: updatedColumns.find((col) => col.columnName === columnName), + }); + } }; // 컬럼 순서 변경