fix: 분할패널 수정 버튼 클릭 시 데이터 불러오기 오류 수정

- Primary Key 컬럼명을 프론트엔드에서 백엔드로 전달하도록 개선
- 백엔드 자동 감지 실패 시에도 클라이언트 제공 값 우선 사용
- Primary Key 찾기 로직 개선 (설정값 > id > ID > non-null 필드)
This commit is contained in:
leeheejin 2026-01-21 10:32:37 +09:00
parent 6a0aa87d3b
commit e8fc664352
4 changed files with 66 additions and 23 deletions

View File

@ -606,7 +606,7 @@ router.get(
});
}
const { enableEntityJoin, groupByColumns } = req.query;
const { enableEntityJoin, groupByColumns, primaryKeyColumn } = req.query;
const enableEntityJoinFlag =
enableEntityJoin === "true" ||
(typeof enableEntityJoin === "boolean" && enableEntityJoin);
@ -626,17 +626,22 @@ router.get(
}
}
// 🆕 primaryKeyColumn 파싱
const primaryKeyColumnStr = typeof primaryKeyColumn === "string" ? primaryKeyColumn : undefined;
console.log(`🔍 레코드 상세 조회: ${tableName}/${id}`, {
enableEntityJoin: enableEntityJoinFlag,
groupByColumns: groupByColumnsArray,
primaryKeyColumn: primaryKeyColumnStr,
});
// 레코드 상세 조회 (Entity Join 옵션 + 그룹핑 옵션 포함)
// 레코드 상세 조회 (Entity Join 옵션 + 그룹핑 옵션 + Primary Key 컬럼 포함)
const result = await dataService.getRecordDetail(
tableName,
id,
enableEntityJoinFlag,
groupByColumnsArray
groupByColumnsArray,
primaryKeyColumnStr // 🆕 Primary Key 컬럼명 전달
);
if (!result.success) {

View File

@ -490,7 +490,8 @@ class DataService {
tableName: string,
id: string | number,
enableEntityJoin: boolean = false,
groupByColumns: string[] = []
groupByColumns: string[] = [],
primaryKeyColumn?: string // 🆕 클라이언트에서 전달한 Primary Key 컬럼명
): Promise<ServiceResponse<any>> {
try {
// 테이블 접근 검증
@ -499,20 +500,30 @@ class DataService {
return validation.error!;
}
// Primary Key 컬럼 찾기
const pkResult = await query<{ attname: string }>(
`SELECT a.attname
FROM pg_index i
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
WHERE i.indrelid = $1::regclass AND i.indisprimary`,
[tableName]
);
// 🆕 클라이언트에서 전달한 Primary Key 컬럼이 있으면 우선 사용
let pkColumn = primaryKeyColumn || "";
// Primary Key 컬럼이 없으면 자동 감지
if (!pkColumn) {
const pkResult = await query<{ attname: string }>(
`SELECT a.attname
FROM pg_index i
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
WHERE i.indrelid = $1::regclass AND i.indisprimary`,
[tableName]
);
let pkColumn = "id"; // 기본값
if (pkResult.length > 0) {
pkColumn = pkResult[0].attname;
pkColumn = "id"; // 기본값
if (pkResult.length > 0) {
pkColumn = pkResult[0].attname;
}
console.log(`🔑 [getRecordDetail] 자동 감지된 Primary Key:`, pkResult);
} else {
console.log(`🔑 [getRecordDetail] 클라이언트 제공 Primary Key: ${pkColumn}`);
}
console.log(`🔑 [getRecordDetail] 테이블: ${tableName}, Primary Key 컬럼: ${pkColumn}, 조회 ID: ${id}`);
// 🆕 Entity Join이 활성화된 경우
if (enableEntityJoin) {
const { EntityJoinService } = await import("./entityJoinService");

View File

@ -374,8 +374,9 @@ export const ScreenModal: React.FC<ScreenModalProps> = ({ className }) => {
const editId = urlParams.get("editId");
const tableName = urlParams.get("tableName") || screenInfo.tableName;
const groupByColumnsParam = urlParams.get("groupByColumns");
const primaryKeyColumn = urlParams.get("primaryKeyColumn"); // 🆕 Primary Key 컬럼명
console.log("📋 URL 파라미터 확인:", { mode, editId, tableName, groupByColumnsParam });
console.log("📋 URL 파라미터 확인:", { mode, editId, tableName, groupByColumnsParam, primaryKeyColumn });
// 수정 모드이고 editId가 있으면 해당 레코드 조회
if (mode === "edit" && editId && tableName) {
@ -414,6 +415,11 @@ export const ScreenModal: React.FC<ScreenModalProps> = ({ className }) => {
params.groupByColumns = JSON.stringify(groupByColumns);
console.log("✅ [ScreenModal] groupByColumns를 params에 추가:", params.groupByColumns);
}
// 🆕 Primary Key 컬럼명 전달 (백엔드 자동 감지 실패 시 사용)
if (primaryKeyColumn) {
params.primaryKeyColumn = primaryKeyColumn;
console.log("✅ [ScreenModal] primaryKeyColumn을 params에 추가:", primaryKeyColumn);
}
console.log("📡 [ScreenModal] 실제 API 요청:", {
url: `/data/${tableName}/${editId}`,

View File

@ -1590,21 +1590,40 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
// 커스텀 모달 화면 열기
const rightTableName = componentConfig.rightPanel?.tableName || "";
// Primary Key 찾기 (우선순위: id > ID > 첫 번째 필드)
// Primary Key 찾기 (우선순위: 설정값 > id > ID > non-null 필드)
// 🔧 설정에서 primaryKeyColumn 지정 가능
const configuredPrimaryKey = componentConfig.rightPanel?.editButton?.primaryKeyColumn;
let primaryKeyName = "id";
let primaryKeyValue: any;
if (item.id !== undefined && item.id !== null) {
if (configuredPrimaryKey && item[configuredPrimaryKey] !== undefined && item[configuredPrimaryKey] !== null) {
// 설정된 Primary Key 사용
primaryKeyName = configuredPrimaryKey;
primaryKeyValue = item[configuredPrimaryKey];
} else if (item.id !== undefined && item.id !== null) {
primaryKeyName = "id";
primaryKeyValue = item.id;
} else if (item.ID !== undefined && item.ID !== null) {
primaryKeyName = "ID";
primaryKeyValue = item.ID;
} else {
// 첫 번째 필드를 Primary Key로 간주
const firstKey = Object.keys(item)[0];
primaryKeyName = firstKey;
primaryKeyValue = item[firstKey];
// 🔧 첫 번째 non-null 필드를 Primary Key로 간주
const keys = Object.keys(item);
let found = false;
for (const key of keys) {
if (item[key] !== undefined && item[key] !== null) {
primaryKeyName = key;
primaryKeyValue = item[key];
found = true;
break;
}
}
// 모든 필드가 null이면 첫 번째 필드 사용
if (!found && keys.length > 0) {
primaryKeyName = keys[0];
primaryKeyValue = item[keys[0]];
}
}
console.log("✅ 수정 모달 열기:", {
@ -1629,7 +1648,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
hasGroupByColumns: groupByColumns.length > 0,
});
// ScreenModal 열기 이벤트 발생 (URL 파라미터로 ID + groupByColumns 전달)
// ScreenModal 열기 이벤트 발생 (URL 파라미터로 ID + groupByColumns + primaryKeyColumn 전달)
window.dispatchEvent(
new CustomEvent("openScreenModal", {
detail: {
@ -1638,6 +1657,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
mode: "edit",
editId: primaryKeyValue,
tableName: rightTableName,
primaryKeyColumn: primaryKeyName, // 🆕 Primary Key 컬럼명 전달
...(groupByColumns.length > 0 && {
groupByColumns: JSON.stringify(groupByColumns),
}),
@ -1650,6 +1670,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
screenId: modalScreenId,
editId: primaryKeyValue,
tableName: rightTableName,
primaryKeyColumn: primaryKeyName,
groupByColumns: groupByColumns.length > 0 ? JSON.stringify(groupByColumns) : "없음",
});