diff --git a/backend-node/src/services/screenManagementService.ts b/backend-node/src/services/screenManagementService.ts index 9d5d56a5..e54b2cfa 100644 --- a/backend-node/src/services/screenManagementService.ts +++ b/backend-node/src/services/screenManagementService.ts @@ -5957,7 +5957,21 @@ export class ScreenManagementService { return null; } - const layoutData = layout.layout_data; + let layoutData = layout.layout_data; + + // 이중 래핑 감지 및 자동 언래핑 + // layout_data 컬럼에 { version, layout_data: { components, ... } } 형태로 저장된 경우 + // 실제 레이아웃은 내부 layout_data에 있으므로 언래핑한다 + if ( + layoutData && + layoutData.layout_data && + typeof layoutData.layout_data === "object" && + !layoutData.components && + layoutData.layout_data.components + ) { + console.log(`POP 레이아웃 이중 래핑 감지 (screen_id=${screenId}), 자동 언래핑`); + layoutData = layoutData.layout_data; + } // v1 → v2 자동 마이그레이션 if (layoutData && layoutData.version === "pop-1.0") { @@ -5994,10 +6008,22 @@ export class ScreenManagementService { console.log(`=== POP 레이아웃 저장 (v5 그리드 시스템) ===`); console.log(`화면 ID: ${screenId}, 회사: ${companyCode}`); + // 이중 래핑 방지: { version, layout_data: { components, ... } } 형태로 전달된 경우 언래핑 + if ( + layoutData && + layoutData.layout_data && + typeof layoutData.layout_data === "object" && + !layoutData.components && + layoutData.layout_data.components + ) { + console.log(`저장 시 이중 래핑 감지 (screen_id=${screenId}), 자동 언래핑`); + layoutData = layoutData.layout_data; + } + // v5 그리드 레이아웃만 지원 const componentCount = Object.keys(layoutData.components || {}).length; console.log(`컴포넌트: ${componentCount}개`); - + // v5 형식 검증 if (layoutData.version && layoutData.version !== "pop-5.0") { console.warn(`레거시 버전 감지 (${layoutData.version}), v5로 변환 필요`);