# 레이아웃 추가 가이드 화면관리 시스템에서 새로운 레이아웃을 추가하는 방법을 설명합니다. ## 📋 목차 1. [CLI를 이용한 자동 생성](#cli를-이용한-자동-생성) 2. [생성된 파일 구조](#생성된-파일-구조) 3. [레이아웃 커스터마이징](#레이아웃-커스터마이징) 4. [고급 설정](#고급-설정) 5. [문제 해결](#문제-해결) --- ## 🚀 CLI를 이용한 자동 생성 ### 기본 사용법 ```bash # 기본 형태 node scripts/create-layout.js <레이아웃이름> [옵션] # 예시 node scripts/create-layout.js card-grid --category=dashboard --zones=6 --description="카드 형태의 그리드 레이아웃" ``` ### 📝 사용 가능한 옵션 | 옵션 | 필수 여부 | 기본값 | 설명 | 예시 | | --------------- | --------- | ----------- | ----------------- | ----------------------------------- | | `--category` | 선택 | `basic` | 레이아웃 카테고리 | `--category=dashboard` | | `--zones` | 선택 | `2` | 영역 개수 | `--zones=4` | | `--description` | 선택 | 자동 생성 | 레이아웃 설명 | `--description="사이드바 레이아웃"` | | `--author` | 선택 | `Developer` | 작성자 이름 | `--author="김개발"` | ### 🏷️ 카테고리 종류 | 카테고리 | 설명 | 예시 레이아웃 | | ------------ | ------------- | ------------------------ | | `basic` | 기본 레이아웃 | 그리드, 플렉스박스, 분할 | | `navigation` | 네비게이션 | 탭, 아코디언, 메뉴 | | `dashboard` | 대시보드 | 카드, 위젯, 차트 | | `content` | 콘텐츠 | 헤더-본문, 영웅 섹션 | | `form` | 폼 | 입력 폼, 설정 패널 | | `table` | 테이블 | 데이터 테이블, 목록 | ### 💡 이름 규칙 레이아웃 이름은 **하이픈(`-`)을 사용한 kebab-case**로 입력하면 자동으로 변환됩니다: ```bash # 입력: hero-section 📁 디렉토리: hero-section/ 🔖 ID: hero-section 📄 클래스명: HeroSection 🔧 변수명: heroSection ``` #### ✅ 올바른 이름 예시 - `card-grid` - `side-navigation` - `data-table` - `hero-section` - `my-awesome-layout` #### ❌ 피해야 할 이름 - `CardGrid` (파스칼케이스) - `card_grid` (스네이크케이스) - `cardGrid` (카멜케이스) --- ## 📂 생성된 파일 구조 CLI로 레이아웃을 생성하면 다음과 같은 파일들이 자동으로 생성됩니다: ``` lib/registry/layouts/your-layout/ ├── index.ts # 레이아웃 정의 및 등록 ├── YourLayoutLayout.tsx # React 컴포넌트 ├── YourLayoutRenderer.tsx # 렌더링 로직 ├── config.ts # 기본 설정 ├── types.ts # 타입 정의 └── README.md # 문서 ``` ### 🔧 각 파일의 역할 #### 1. `index.ts` - 레이아웃 정의 ```typescript export const YourLayoutDefinition = createLayoutDefinition({ id: "your-layout", name: "yourLayout", nameEng: "Your Layout", description: "사용자 정의 레이아웃입니다", category: "basic", component: YourLayoutWrapper, defaultConfig: { /* 기본 설정 */ }, defaultZones: [ /* 기본 영역들 */ ], }); ``` #### 2. `YourLayoutLayout.tsx` - React 컴포넌트 ```typescript export const YourLayoutLayout: React.FC = ({ layout, isDesignMode, renderer, ...props }) => { // 레이아웃 UI 구현 }; ``` #### 3. `YourLayoutRenderer.tsx` - 렌더링 로직 ```typescript export class YourLayoutRenderer extends AutoRegisteringLayoutRenderer { static layoutDefinition = YourLayoutDefinition; render(): React.ReactElement { return ; } } ``` --- ## 🎨 레이아웃 커스터마이징 ### 1. 기본 구조 수정 생성된 `YourLayoutLayout.tsx`에서 레이아웃 구조를 정의합니다: ```typescript export const YourLayoutLayout: React.FC = ({ layout, isDesignMode = false, renderer, }) => { const yourLayoutConfig = layout.layoutConfig.yourLayout; const containerStyle = renderer.getLayoutContainerStyle(); // 레이아웃별 커스텀 스타일 const yourLayoutStyle: React.CSSProperties = { ...containerStyle, display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gridTemplateRows: "repeat(2, 200px)", gap: "16px", padding: "16px", }; return (
{layout.zones.map((zone) => { const zoneChildren = renderer.getZoneChildren(zone.id); return (
{/* 존 렌더링 */} {renderer.renderZone(zone, zoneChildren)}
); })}
); }; ``` ### 2. 설정 옵션 추가 `config.ts`에서 레이아웃별 설정을 정의합니다: ```typescript export const YourLayoutConfig = { defaultConfig: { yourLayout: { columns: 3, // 열 개수 rows: 2, // 행 개수 gap: 16, // 간격 aspectRatio: "16:9", // 비율 backgroundColor: "#ffffff", borderRadius: "8px", }, }, }; ``` ### 3. 타입 정의 `types.ts`에서 설정 타입을 정의합니다: ```typescript export interface YourLayoutConfig { columns?: number; rows?: number; gap?: number; aspectRatio?: string; backgroundColor?: string; borderRadius?: string; } export interface YourLayoutProps extends LayoutRendererProps { renderer: YourLayoutRenderer; } ``` --- ## 🔧 고급 설정 ### 영역(Zone) 커스터마이징 영역별로 다른 스타일을 적용하려면: ```typescript // 영역별 스타일 계산 const getZoneStyle = (zone: LayoutZone, index: number): React.CSSProperties => { const baseStyle = { backgroundColor: "#f8f9fa", border: "1px solid #e9ecef", borderRadius: "4px", padding: "12px", }; // 첫 번째 영역은 다른 스타일 if (index === 0) { return { ...baseStyle, backgroundColor: "#e3f2fd", gridColumn: "1 / -1", // 전체 너비 }; } return baseStyle; }; ``` ### 반응형 레이아웃 미디어 쿼리를 사용한 반응형 구현: ```typescript const getResponsiveStyle = (): React.CSSProperties => { return { display: "grid", gridTemplateColumns: `repeat(auto-fit, minmax(300px, 1fr))`, gap: "16px", // CSS-in-JS에서는 미디어 쿼리를 직접 사용할 수 없으므로 // CSS 클래스나 컨테이너 쿼리 사용 권장 }; }; ``` ### 애니메이션 추가 CSS 애니메이션을 포함한 레이아웃: ```typescript const animatedStyle: React.CSSProperties = { transition: "all 0.3s ease-in-out", opacity: isDesignMode ? 0.9 : 1, transform: isDesignMode ? "scale(0.98)" : "scale(1)", }; ``` --- ## 🔄 자동 등록 시스템 ### Hot Reload 지원 새 레이아웃은 다음과 같이 자동으로 등록됩니다: 1. **파일 저장 시**: Hot Reload로 즉시 반영 2. **자동 등록**: `AutoRegisteringLayoutRenderer` 상속으로 자동 등록 3. **즉시 사용**: 화면편집기에서 바로 사용 가능 ### 수동 등록 (필요한 경우) `lib/registry/layouts/index.ts`에 직접 추가: ```typescript // 새 구조 레이아웃들 (자동 등록) import "./your-layout/YourLayoutRenderer"; ``` --- ## 🛠️ 문제 해결 ### 자주 발생하는 오류 #### 1. "Cannot read properties of undefined" 오류 ```typescript // ❌ 문제: 설정이 없을 때 오류 const config = layout.layoutConfig.yourLayout.someProperty; // ✅ 해결: 안전한 접근 const config = layout.layoutConfig.yourLayout?.someProperty || defaultValue; ``` #### 2. "React does not recognize prop" 경고 ```typescript // ❌ 문제: 모든 props를 DOM에 전달
// ✅ 해결: DOM props만 전달 const { layout, isDesignMode, renderer, ...domProps } = props;
``` #### 3. 레이아웃이 화면편집기에 나타나지 않음 1. **파일 저장 확인**: 모든 파일이 저장되었는지 확인 2. **자동 등록 확인**: `YourLayoutRenderer.registerSelf()` 호출 여부 3. **브라우저 새로고침**: 캐시 문제일 수 있음 4. **개발자 도구**: `window.__LAYOUT_REGISTRY__.list()` 로 등록 상태 확인 ### 디버깅 도구 #### 브라우저 개발자 도구 ```javascript // 등록된 레이아웃 목록 확인 window.__LAYOUT_REGISTRY__.list(); // 특정 레이아웃 정보 확인 window.__LAYOUT_REGISTRY__.get("your-layout"); // 레지스트리 통계 window.__LAYOUT_REGISTRY__.stats(); ``` --- ## 📖 예시: 완전한 레이아웃 생성 ### 1. CLI로 생성 ```bash node scripts/create-layout.js pricing-table --category=content --zones=4 --description="가격표 레이아웃" --author="개발팀" ``` ### 2. 생성 결과 ``` ✅ 레이아웃 생성 완료! 📁 이름: pricingTable 🔖 ID: pricing-table 📂 카테고리: content 🎯 존 개수: 4 ``` ### 3. 커스터마이징 ```typescript // PricingTableLayout.tsx export const PricingTableLayout: React.FC = ({ layout, isDesignMode, renderer, }) => { const pricingTableStyle: React.CSSProperties = { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(250px, 1fr))", gap: "24px", padding: "32px", backgroundColor: "#f8f9fa", }; return (
{layout.zones.map((zone, index) => (
{renderer.renderZone(zone, renderer.getZoneChildren(zone.id))}
))}
); }; ``` ### 4. 즉시 사용 가능 레이아웃이 자동으로 등록되어 화면편집기에서 바로 사용할 수 있습니다! --- ## 🎯 마무리 새로운 CLI 방식으로 레이아웃 추가가 매우 간단해졌습니다: 1. **한 줄 명령어**로 모든 파일 자동 생성 2. **타입 안전성** 보장 3. **자동 등록**으로 즉시 사용 가능 4. **Hot Reload** 지원으로 빠른 개발 더 자세한 정보가 필요하면 각 레이아웃의 `README.md` 파일을 참고하세요! 🚀