# 화면관리 시스템 레이아웃 기능 설계서 ## 1. 개요 ### 1.1 목적 화면관리 시스템에 동적 레이아웃 기능을 추가하여 다양한 화면 구조를 효율적으로 설계할 수 있도록 한다. 레이아웃은 컴포넌트들을 구조화된 영역으로 배치할 수 있는 컨테이너 역할을 하며, 동적으로 생성하고 관리할 수 있도록 설계한다. ### 1.2 범위 - 레이아웃 관리 메뉴 및 기능 개발 - 다양한 레이아웃 타입 및 설정 기능 - 레지스트리 기반 동적 레이아웃 컴포넌트 시스템 - 기존 화면관리 시스템과의 통합 ## 2. 현재 시스템 분석 ### 2.1 기존 데이터베이스 구조 ```sql -- 현재 화면관리 관련 테이블들 screen_definitions -- 화면 정의 screen_layouts -- 화면 레이아웃 (컴포넌트 배치) screen_widgets -- 위젯 설정 screen_templates -- 화면 템플릿 template_standards -- 템플릿 표준 component_standards -- 컴포넌트 표준 ``` ### 2.2 기존 컴포넌트 타입 ```typescript type ComponentType = "container" | "row" | "column" | "widget" | "group" | "datatable" | "file" | "area"; ``` ### 2.3 현재 레지스트리 시스템 - `ComponentRegistry`: 컴포넌트 동적 등록 및 관리 - `WebTypeRegistry`: 웹타입 동적 등록 및 관리 - `DynamicComponentRenderer`: 동적 컴포넌트 렌더링 ## 3. 레이아웃 기능 설계 ### 3.1 레이아웃 타입 정의 #### 3.1.1 기본 레이아웃 타입 ```typescript export type LayoutType = | "grid" // 그리드 레이아웃 (n x m 격자) | "flexbox" // 플렉스박스 레이아웃 | "split" // 분할 레이아웃 (수직/수평) | "card" // 카드 레이아웃 | "tabs" // 탭 레이아웃 | "accordion" // 아코디언 레이아웃 | "sidebar" // 사이드바 레이아웃 | "header-footer" // 헤더-푸터 레이아웃 | "three-column" // 3단 레이아웃 | "dashboard" // 대시보드 레이아웃 | "form" // 폼 레이아웃 | "table" // 테이블 레이아웃 | "custom"; // 커스텀 레이아웃 ``` #### 3.1.2 레이아웃 컴포넌트 인터페이스 ```typescript export interface LayoutComponent extends BaseComponent { type: "layout"; layoutType: LayoutType; layoutConfig: LayoutConfig; children: ComponentData[]; zones: LayoutZone[]; // 레이아웃 영역 정의 allowedComponentTypes?: ComponentType[]; // 허용된 자식 컴포넌트 타입 dropZoneConfig?: DropZoneConfig; // 드롭존 설정 } export interface LayoutZone { id: string; name: string; position: { row?: number; column?: number; x?: number; y?: number; }; size: { width: number | string; height: number | string; minWidth?: number; minHeight?: number; maxWidth?: number; maxHeight?: number; }; style?: ComponentStyle; allowedComponents?: ComponentType[]; isResizable?: boolean; isRequired?: boolean; // 필수 영역 여부 } export interface LayoutConfig { // 그리드 레이아웃 설정 grid?: { rows: number; columns: number; gap: number; rowGap?: number; columnGap?: number; autoRows?: string; autoColumns?: string; }; // 플렉스박스 설정 flexbox?: { direction: "row" | "column" | "row-reverse" | "column-reverse"; justify: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly"; align: "flex-start" | "flex-end" | "center" | "stretch" | "baseline"; wrap: "nowrap" | "wrap" | "wrap-reverse"; gap: number; }; // 분할 레이아웃 설정 split?: { direction: "horizontal" | "vertical"; ratio: number[]; // 각 영역의 비율 [30, 70] minSize: number[]; // 각 영역의 최소 크기 resizable: boolean; // 크기 조절 가능 여부 splitterSize: number; // 분할선 두께 }; // 탭 레이아웃 설정 tabs?: { position: "top" | "bottom" | "left" | "right"; variant: "default" | "pills" | "underline"; size: "sm" | "md" | "lg"; defaultTab: string; // 기본 선택 탭 closable: boolean; // 탭 닫기 가능 여부 }; // 아코디언 설정 accordion?: { multiple: boolean; // 다중 확장 허용 defaultExpanded: string[]; // 기본 확장 항목 collapsible: boolean; // 모두 닫기 허용 }; // 사이드바 설정 sidebar?: { position: "left" | "right"; width: number | string; collapsible: boolean; collapsed: boolean; overlay: boolean; // 오버레이 모드 }; // 헤더-푸터 설정 headerFooter?: { headerHeight: number | string; footerHeight: number | string; stickyHeader: boolean; stickyFooter: boolean; }; // 대시보드 설정 dashboard?: { columns: number; rowHeight: number; margin: [number, number]; padding: [number, number]; isDraggable: boolean; isResizable: boolean; }; // 커스텀 설정 custom?: { cssProperties: Record; className: string; template: string; // HTML 템플릿 }; } export interface DropZoneConfig { showDropZones: boolean; dropZoneStyle?: ComponentStyle; highlightOnDragOver: boolean; allowedTypes?: ComponentType[]; } ``` ### 3.2 데이터베이스 스키마 확장 #### 3.2.1 레이아웃 표준 관리 테이블 ```sql -- 레이아웃 표준 관리 테이블 CREATE TABLE layout_standards ( layout_code VARCHAR(50) PRIMARY KEY, layout_name VARCHAR(100) NOT NULL, layout_name_eng VARCHAR(100), description TEXT, layout_type VARCHAR(50) NOT NULL, category VARCHAR(50) NOT NULL, icon_name VARCHAR(50), default_size JSON, layout_config JSON NOT NULL, zones_config JSON NOT NULL, preview_image VARCHAR(255), sort_order INTEGER DEFAULT 0, is_active CHAR(1) DEFAULT 'Y', is_public CHAR(1) DEFAULT 'Y', company_code VARCHAR(50) NOT NULL, created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by VARCHAR(50), updated_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_by VARCHAR(50) ); -- 인덱스 생성 CREATE INDEX idx_layout_standards_type ON layout_standards(layout_type); CREATE INDEX idx_layout_standards_category ON layout_standards(category); CREATE INDEX idx_layout_standards_company ON layout_standards(company_code); ``` #### 3.2.2 기존 테이블 확장 ```sql -- screen_layouts 테이블에 레이아웃 관련 컬럼 추가 ALTER TABLE screen_layouts ADD COLUMN layout_type VARCHAR(50); ALTER TABLE screen_layouts ADD COLUMN layout_config JSON; ALTER TABLE screen_layouts ADD COLUMN zones_config JSON; ALTER TABLE screen_layouts ADD COLUMN zone_id VARCHAR(100); -- component_standards 테이블에서 레이아웃 타입 지원 -- category에 'layout' 추가 ``` ### 3.3 레이아웃 카테고리 및 사전 정의 레이아웃 #### 3.3.1 레이아웃 카테고리 ```typescript export const LAYOUT_CATEGORIES = { BASIC: "basic", // 기본 레이아웃 FORM: "form", // 폼 레이아웃 TABLE: "table", // 테이블 레이아웃 DASHBOARD: "dashboard", // 대시보드 레이아웃 NAVIGATION: "navigation", // 네비게이션 레이아웃 CONTENT: "content", // 컨텐츠 레이아웃 BUSINESS: "business", // 업무용 레이아웃 }; ``` #### 3.3.2 사전 정의 레이아웃 템플릿 ```typescript export const PREDEFINED_LAYOUTS = [ // 기본 레이아웃 { code: "GRID_2X2", name: "2x2 그리드", type: "grid", category: "basic", config: { grid: { rows: 2, columns: 2, gap: 16 }, }, zones: [ { id: "zone1", name: "상단 좌측", position: { row: 0, column: 0 } }, { id: "zone2", name: "상단 우측", position: { row: 0, column: 1 } }, { id: "zone3", name: "하단 좌측", position: { row: 1, column: 0 } }, { id: "zone4", name: "하단 우측", position: { row: 1, column: 1 } }, ], }, // 폼 레이아웃 { code: "FORM_TWO_COLUMN", name: "2단 폼 레이아웃", type: "grid", category: "form", config: { grid: { rows: 1, columns: 2, gap: 24 }, }, zones: [ { id: "left", name: "좌측 입력 영역", position: { row: 0, column: 0 } }, { id: "right", name: "우측 입력 영역", position: { row: 0, column: 1 } }, ], }, // 대시보드 레이아웃 { code: "DASHBOARD_MAIN", name: "메인 대시보드", type: "grid", category: "dashboard", config: { grid: { rows: 3, columns: 4, gap: 16 }, }, zones: [ { id: "header", name: "헤더", position: { row: 0, column: 0 }, size: { width: "100%", height: "80px" } }, { id: "sidebar", name: "사이드바", position: { row: 1, column: 0 }, size: { width: "250px", height: "100%" } }, { id: "main", name: "메인 컨텐츠", position: { row: 1, column: 1 }, size: { width: "calc(100% - 250px)", height: "100%" }, }, ], }, // 테이블 레이아웃 { code: "TABLE_WITH_FILTERS", name: "필터가 있는 테이블", type: "flexbox", category: "table", config: { flexbox: { direction: "column", gap: 16 }, }, zones: [ { id: "filters", name: "검색 필터", size: { width: "100%", height: "auto" } }, { id: "table", name: "데이터 테이블", size: { width: "100%", height: "1fr" } }, ], }, // 분할 레이아웃 { code: "SPLIT_HORIZONTAL", name: "수평 분할", type: "split", category: "basic", config: { split: { direction: "horizontal", ratio: [50, 50], resizable: true }, }, zones: [ { id: "left", name: "좌측 영역", isResizable: true }, { id: "right", name: "우측 영역", isResizable: true }, ], }, // 탭 레이아웃 { code: "TABS_HORIZONTAL", name: "수평 탭", type: "tabs", category: "navigation", config: { tabs: { position: "top", variant: "default", defaultTab: "tab1" }, }, zones: [ { id: "tab1", name: "첫 번째 탭" }, { id: "tab2", name: "두 번째 탭" }, { id: "tab3", name: "세 번째 탭" }, ], }, ]; ``` ## 4. 구현 계획 ### 4.1 Phase 1: 기본 인프라 구축 #### 4.1.1 데이터베이스 스키마 생성 - `layout_standards` 테이블 생성 - 기존 테이블 확장 - 기본 레이아웃 데이터 삽입 #### 4.1.2 타입 정의 및 인터페이스 - `frontend/types/layout.ts` 생성 - 기존 `screen.ts` 확장 #### 4.1.3 레이아웃 레지스트리 시스템 ```typescript // frontend/lib/registry/LayoutRegistry.ts export class LayoutRegistry { private static layouts = new Map(); static registerLayout(definition: LayoutDefinition): void; static getLayout(layoutType: string): LayoutDefinition | undefined; static getLayoutsByCategory(category: string): LayoutDefinition[]; static getAllLayouts(): LayoutDefinition[]; } ``` ### 4.2 Phase 2: 레이아웃 관리 기능 #### 4.2.1 레이아웃 관리 메뉴 ```typescript // frontend/app/(main)/admin/layouts/page.tsx - 레이아웃 목록 조회 - 레이아웃 생성/수정/삭제 - 레이아웃 미리보기 - 레이아웃 내보내기/가져오기 ``` #### 4.2.2 레이아웃 편집기 ```typescript // frontend/components/layout/LayoutDesigner.tsx - 드래그앤드롭 레이아웃 편집 - 실시간 미리보기 - 존 설정 편집 - 레이아웃 설정 편집 ``` #### 4.2.3 백엔드 API ```typescript // backend-node/src/routes/layoutRoutes.ts GET /api/layouts // 레이아웃 목록 조회 GET /api/layouts/:id // 레이아웃 상세 조회 POST /api/layouts // 레이아웃 생성 PUT /api/layouts/:id // 레이아웃 수정 DELETE /api/layouts/:id // 레이아웃 삭제 POST /api/layouts/:id/duplicate // 레이아웃 복제 ``` ### 4.3 Phase 3: 레이아웃 컴포넌트 구현 #### 4.3.1 기본 레이아웃 컴포넌트들 ```typescript // frontend/lib/registry/layouts/ ├── GridLayoutRenderer.tsx // 그리드 레이아웃 ├── FlexboxLayoutRenderer.tsx // 플렉스박스 레이아웃 ├── SplitLayoutRenderer.tsx // 분할 레이아웃 ├── TabsLayoutRenderer.tsx // 탭 레이아웃 ├── AccordionLayoutRenderer.tsx // 아코디언 레이아웃 ├── SidebarLayoutRenderer.tsx // 사이드바 레이아웃 ├── HeaderFooterLayoutRenderer.tsx // 헤더-푸터 레이아웃 └── CustomLayoutRenderer.tsx // 커스텀 레이아웃 ``` #### 4.3.2 레이아웃 설정 패널 ```typescript // frontend/components/layout/config-panels/ ├── GridConfigPanel.tsx ├── FlexboxConfigPanel.tsx ├── SplitConfigPanel.tsx ├── TabsConfigPanel.tsx └── ... ``` ### 4.4 Phase 4: 화면관리 시스템 통합 #### 4.4.1 화면 디자이너 확장 - 레이아웃 팔레트 추가 - 레이아웃 드래그앤드롭 지원 - 레이아웃 존에 컴포넌트 배치 #### 4.4.2 실시간 미리보기 지원 - 레이아웃 렌더링 지원 - 존별 컴포넌트 렌더링 - 레이아웃 상호작용 지원 ## 5. 기술적 구현 세부사항 ### 5.1 레이아웃 렌더러 기본 구조 ```typescript // frontend/lib/registry/layouts/BaseLayoutRenderer.tsx interface LayoutRendererProps { layout: LayoutComponent; children: ComponentData[]; isDesignMode?: boolean; onZoneClick?: (zoneId: string) => void; onComponentDrop?: (zoneId: string, component: ComponentData) => void; } export abstract class BaseLayoutRenderer extends React.Component { abstract render(): React.ReactElement; protected renderZone(zone: LayoutZone, children: ComponentData[]): React.ReactElement { return (
this.props.onZoneClick?.(zone.id)} onDrop={this.handleDrop} onDragOver={this.handleDragOver} > {children.map(child => ( ))}
); } private handleDrop = (e: React.DragEvent) => { // 드롭 처리 로직 }; private handleDragOver = (e: React.DragEvent) => { // 드래그오버 처리 로직 }; } ``` ### 5.2 동적 레이아웃 등록 시스템 ```typescript // frontend/lib/registry/layouts/index.ts import { LayoutRegistry } from "../LayoutRegistry"; import GridLayoutRenderer from "./GridLayoutRenderer"; import FlexboxLayoutRenderer from "./FlexboxLayoutRenderer"; // ... 다른 레이아웃 import // 레이아웃 컴포넌트들을 레지스트리에 등록 LayoutRegistry.registerLayout({ id: "grid", name: "그리드 레이아웃", component: GridLayoutRenderer, category: "basic", icon: "grid", defaultConfig: { grid: { rows: 2, columns: 2, gap: 16 }, }, }); LayoutRegistry.registerLayout({ id: "flexbox", name: "플렉스박스 레이아웃", component: FlexboxLayoutRenderer, category: "basic", icon: "flex", defaultConfig: { flexbox: { direction: "row", justify: "flex-start", align: "stretch" }, }, }); ``` ### 5.3 레이아웃 팔레트 컴포넌트 ```typescript // frontend/components/screen/panels/LayoutsPanel.tsx export default function LayoutsPanel({ onDragStart }: LayoutsPanelProps) { const [layouts] = useState(() => LayoutRegistry.getAllLayouts()); const [selectedCategory, setSelectedCategory] = useState('all'); const filteredLayouts = useMemo(() => { if (selectedCategory === 'all') return layouts; return layouts.filter(layout => layout.category === selectedCategory); }, [layouts, selectedCategory]); return (
{LAYOUT_CATEGORIES.map(category => ( ))}
{filteredLayouts.map(layout => (
onDragStart(e, layout)} >

{layout.name}

{layout.description}

))}
); } ``` ## 6. 사용자 인터페이스 설계 ### 6.1 레이아웃 관리 화면 - **레이아웃 목록**: 그리드 형태로 레이아웃 목록 표시 - **카테고리 필터**: 카테고리별 레이아웃 필터링 - **검색 기능**: 레이아웃 이름/설명으로 검색 - **미리보기**: 레이아웃 구조 미리보기 - **편집 버튼**: 레이아웃 편집 모드 진입 ### 6.2 레이아웃 편집기 - **캔버스 영역**: 레이아웃 시각적 편집 - **존 편집**: 각 존의 크기/위치 조정 - **속성 패널**: 레이아웃 설정 편집 - **미리보기 모드**: 실제 렌더링 미리보기 ### 6.3 화면 디자이너 확장 - **레이아웃 팔레트**: 사용 가능한 레이아웃 목록 - **드래그앤드롭**: 레이아웃을 캔버스에 배치 - **존 하이라이트**: 컴포넌트 드롭 가능한 존 표시 ## 7. 보안 및 권한 관리 ### 7.1 레이아웃 접근 권한 - **생성 권한**: 레이아웃 생성 권한 - **수정 권한**: 레이아웃 수정 권한 - **삭제 권한**: 레이아웃 삭제 권한 - **공개 설정**: 다른 사용자와 레이아웃 공유 ### 7.2 회사별 레이아웃 관리 - **회사 코드**: 레이아웃의 회사 소속 관리 - **공개 레이아웃**: 모든 회사에서 사용 가능한 레이아웃 - **비공개 레이아웃**: 특정 회사에서만 사용 가능한 레이아웃 ## 8. 성능 최적화 ### 8.1 레이아웃 렌더링 최적화 - **지연 로딩**: 필요한 레이아웃 컴포넌트만 로딩 - **메모이제이션**: 레이아웃 설정 변경 시에만 리렌더링 - **가상화**: 대량의 레이아웃 목록 가상화 ### 8.2 캐싱 전략 - **레이아웃 정의 캐싱**: 자주 사용되는 레이아웃 정의 캐싱 - **렌더링 결과 캐싱**: 동일한 설정의 레이아웃 렌더링 결과 캐싱 ## 9. 테스트 계획 ### 9.1 단위 테스트 - 레이아웃 컴포넌트 렌더링 테스트 - 레이아웃 설정 변경 테스트 - 드래그앤드롭 기능 테스트 ### 9.2 통합 테스트 - 화면관리 시스템과의 통합 테스트 - 데이터베이스 연동 테스트 - API 엔드포인트 테스트 ### 9.3 사용자 테스트 - 레이아웃 생성/편집 시나리오 테스트 - 다양한 브라우저 호환성 테스트 ## 10. 마이그레이션 계획 ### 10.1 기존 화면 마이그레이션 - 기존 컨테이너 컴포넌트를 레이아웃으로 변환 - 기존 화면 구조를 레이아웃 기반으로 재구성 ### 10.2 단계별 배포 1. **Phase 1**: 레이아웃 관리 기능 배포 2. **Phase 2**: 기본 레이아웃 컴포넌트 배포 3. **Phase 3**: 화면관리 시스템 통합 4. **Phase 4**: 기존 화면 마이그레이션 ## 11. 향후 확장 계획 ### 11.1 고급 레이아웃 기능 - **반응형 레이아웃**: 화면 크기에 따른 레이아웃 변경 - **애니메이션**: 레이아웃 전환 애니메이션 - **테마 지원**: 레이아웃별 테마 설정 ### 11.2 AI 기반 레이아웃 추천 - 데이터 타입에 따른 레이아웃 자동 추천 - 사용 패턴 분석을 통한 최적 레이아웃 제안 ### 11.3 협업 기능 - **실시간 편집**: 여러 사용자가 동시에 레이아웃 편집 - **버전 관리**: 레이아웃 변경 이력 관리 - **댓글 시스템**: 레이아웃에 대한 피드백 시스템 ## 12. 결론 이 설계서에 따라 레이아웃 기능을 구현하면, 화면관리 시스템의 유연성과 확장성이 크게 향상될 것입니다. 동적 레지스트리 시스템을 통해 새로운 레이아웃 타입을 쉽게 추가할 수 있으며, 사용자는 다양한 화면 구조를 효율적으로 설계할 수 있게 됩니다. 주요 장점: - **확장성**: 새로운 레이아웃 타입 쉽게 추가 - **재사용성**: 레이아웃 템플릿 재사용으로 개발 효율성 향상 - **유연성**: 다양한 화면 요구사항에 대응 가능 - **일관성**: 표준화된 레이아웃을 통한 UI 일관성 확보