docs: 다양한 문서 및 가이드 업데이트
- 여러 문서의 내용을 업데이트하여 최신 정보를 반영하였습니다. - 컴포넌트 개발 가이드와 관련된 문서의 목차를 재구성하고, V2 및 Zod 레이아웃 시스템에 대한 내용을 추가하였습니다. - 화면 컴포넌트 개발 가이드를 개선하여 핵심 원칙과 패턴을 명확히 설명하였습니다. - 불필요한 문서 및 가이드를 삭제하고, 통합된 가이드를 통해 개발자들이 쉽게 참고할 수 있도록 하였습니다.
This commit is contained in:
233
docs/DDD1542/COMPONENT_URL_SYSTEM_IMPLEMENTATION.md
Normal file
233
docs/DDD1542/COMPONENT_URL_SYSTEM_IMPLEMENTATION.md
Normal file
@@ -0,0 +1,233 @@
|
||||
ㅡㄹ ㅣ # 컴포넌트 URL 시스템 구현 완료
|
||||
|
||||
## 실행 일시: 2026-01-27
|
||||
|
||||
## 1. 목표
|
||||
|
||||
- 컴포넌트 코드 수정 시 **모든 회사에 즉시 반영** ✅
|
||||
- 회사별 고유 설정은 **JSON으로 안전하게 관리** (Zod 검증) ✅
|
||||
- 기존 화면 **100% 동일하게 렌더링** 보장 ✅
|
||||
|
||||
---
|
||||
|
||||
## 2. 완료된 작업
|
||||
|
||||
### 2.1 DB 테이블 생성
|
||||
- `screen_layouts_v3` 테이블 생성 완료
|
||||
- 4,414개 레코드 마이그레이션 완료
|
||||
|
||||
### 2.2 파일 생성/수정
|
||||
| 파일 | 상태 |
|
||||
|-----|-----|
|
||||
| `frontend/lib/schemas/componentConfig.ts` | ✅ 신규 생성 |
|
||||
| `backend-node/src/services/screenManagementService.ts` | ✅ getLayoutV3 추가 |
|
||||
| `backend-node/src/controllers/screenManagementController.ts` | ✅ getLayoutV3 추가 |
|
||||
| `backend-node/src/routes/screenManagementRoutes.ts` | ✅ 라우트 추가 |
|
||||
|
||||
### 2.3 API 엔드포인트
|
||||
```
|
||||
GET /api/screen-management/screens/:screenId/layout-v3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 핵심 구조
|
||||
|
||||
### 2.1 컴포넌트 코드 (파일 시스템)
|
||||
|
||||
```
|
||||
frontend/lib/registry/components/{component-name}/
|
||||
├── index.ts # 렌더링 로직, UI
|
||||
├── schema.ts # Zod 스키마 + 기본값
|
||||
└── types.ts # 타입 정의
|
||||
```
|
||||
|
||||
### 2.2 DB 구조
|
||||
|
||||
```sql
|
||||
screen_layouts_v3 (
|
||||
layout_id SERIAL PRIMARY KEY,
|
||||
screen_id INTEGER REFERENCES screen_definitions(screen_id),
|
||||
component_id VARCHAR(100) UNIQUE NOT NULL,
|
||||
|
||||
-- 컴포넌트 URL (파일 경로)
|
||||
component_url VARCHAR(200) NOT NULL,
|
||||
-- 예: "@/lib/registry/components/split-panel-layout"
|
||||
|
||||
-- 회사별 커스텀 설정 (비즈니스 데이터만)
|
||||
custom_config JSONB NOT NULL DEFAULT '{}',
|
||||
|
||||
-- 레이아웃 정보
|
||||
parent_id VARCHAR(100),
|
||||
position_x INTEGER NOT NULL DEFAULT 0,
|
||||
position_y INTEGER NOT NULL DEFAULT 0,
|
||||
width INTEGER NOT NULL DEFAULT 100,
|
||||
height INTEGER NOT NULL DEFAULT 100,
|
||||
display_order INTEGER DEFAULT 0,
|
||||
|
||||
-- 기타
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 대상 컴포넌트 (고수준)
|
||||
|
||||
| 컴포넌트 | 개수 | 우선순위 |
|
||||
|---------|-----|---------|
|
||||
| split-panel-layout | 129 | 높음 |
|
||||
| tabs-widget | 74 | 높음 |
|
||||
| modal-repeater-table | 68 | 높음 |
|
||||
| category-manager | 69 | 중간 |
|
||||
| flow-widget | 11 | 중간 |
|
||||
| table-list | 280 | 높음 |
|
||||
| table-search-widget | 353 | 높음 |
|
||||
| conditional-container | 53 | 중간 |
|
||||
| selected-items-detail-input | 83 | 중간 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 작업 단계
|
||||
|
||||
### Phase 1: 스키마 정의
|
||||
- [ ] split-panel-layout/schema.ts
|
||||
- [ ] tabs-widget/schema.ts
|
||||
- [ ] modal-repeater-table/schema.ts
|
||||
- [ ] table-list/schema.ts
|
||||
- [ ] table-search-widget/schema.ts
|
||||
- [ ] 기타 컴포넌트들
|
||||
|
||||
### Phase 2: DB 테이블 생성
|
||||
- [ ] screen_layouts_v3 테이블 생성
|
||||
- [ ] 인덱스 생성
|
||||
|
||||
### Phase 3: 마이그레이션
|
||||
- [ ] 기존 데이터에서 component_url 추출
|
||||
- [ ] 기존 데이터에서 custom_config 분리
|
||||
- [ ] 검증 (기존 화면과 동일 렌더링)
|
||||
|
||||
### Phase 4: 백엔드 수정
|
||||
- [ ] getLayoutV3 API 추가
|
||||
- [ ] saveLayoutV3 API 추가
|
||||
|
||||
### Phase 5: 프론트엔드 수정
|
||||
- [ ] 렌더링 로직에 스키마 병합 적용
|
||||
- [ ] 화면 디자이너 저장 로직 수정
|
||||
|
||||
---
|
||||
|
||||
## 5. Zod 스키마 설계 원칙
|
||||
|
||||
### 5.1 기본값 (코드에서 관리)
|
||||
```typescript
|
||||
// 컴포넌트 UI/동작 관련 - 코드 수정 시 전체 반영
|
||||
const baseDefaults = {
|
||||
resizable: true,
|
||||
splitRatio: 30,
|
||||
syncSelection: true,
|
||||
};
|
||||
```
|
||||
|
||||
### 5.2 커스텀 설정 (DB에서 관리)
|
||||
```typescript
|
||||
// 비즈니스 데이터 - 회사별 개별 관리
|
||||
const customConfigSchema = z.object({
|
||||
leftPanel: z.object({
|
||||
title: z.string().optional(),
|
||||
tableName: z.string(),
|
||||
columns: z.array(z.any()).default([]),
|
||||
}).passthrough(),
|
||||
rightPanel: z.object({
|
||||
title: z.string().optional(),
|
||||
tableName: z.string(),
|
||||
relation: z.any().optional(),
|
||||
}).passthrough(),
|
||||
}).passthrough();
|
||||
```
|
||||
|
||||
### 5.3 병합 로직
|
||||
```typescript
|
||||
function mergeConfig(baseDefaults: any, customConfig: any) {
|
||||
// 1. 스키마로 customConfig 파싱 (없는 필드는 기본값)
|
||||
const parsed = customConfigSchema.parse(customConfig);
|
||||
|
||||
// 2. 기본값과 병합
|
||||
return { ...baseDefaults, ...parsed };
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 렌더링 흐름
|
||||
|
||||
```
|
||||
1. DB 조회
|
||||
├─ component_url: "@/lib/registry/components/split-panel-layout"
|
||||
└─ custom_config: { leftPanel: { tableName: "sales_order_mng", ... } }
|
||||
|
||||
2. 컴포넌트 로드
|
||||
└─ ComponentRegistry.get("split-panel-layout")
|
||||
|
||||
3. 스키마 로드
|
||||
└─ import { schema, baseDefaults } from "./schema"
|
||||
|
||||
4. 설정 병합
|
||||
└─ baseDefaults + schema.parse(custom_config)
|
||||
|
||||
5. 렌더링
|
||||
└─ <SplitPanelLayout config={mergedConfig} />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 마이그레이션 전략
|
||||
|
||||
### 7.1 component_url 추출
|
||||
```sql
|
||||
-- properties.componentType → component_url 변환
|
||||
UPDATE screen_layouts_v3
|
||||
SET component_url = '@/lib/registry/components/' || (properties->>'componentType')
|
||||
WHERE properties->>'componentType' IS NOT NULL;
|
||||
```
|
||||
|
||||
### 7.2 custom_config 분리
|
||||
```javascript
|
||||
// 기존 componentConfig에서 비즈니스 데이터만 추출
|
||||
function extractCustomConfig(componentType, componentConfig) {
|
||||
const baseKeys = getBaseKeys(componentType); // 코드 기본값 키들
|
||||
const customConfig = {};
|
||||
|
||||
for (const key of Object.keys(componentConfig)) {
|
||||
if (!baseKeys.includes(key)) {
|
||||
customConfig[key] = componentConfig[key];
|
||||
}
|
||||
}
|
||||
|
||||
return customConfig;
|
||||
}
|
||||
```
|
||||
|
||||
### 7.3 검증
|
||||
```javascript
|
||||
// 기존 렌더링과 동일한지 확인
|
||||
function verify(original, migrated) {
|
||||
const originalRender = renderWithConfig(original.componentConfig);
|
||||
const migratedRender = renderWithConfig(
|
||||
merge(baseDefaults, migrated.custom_config)
|
||||
);
|
||||
|
||||
return deepEqual(originalRender, migratedRender);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 체크리스트
|
||||
|
||||
- [ ] 컴포넌트 코드 수정 → 전체 회사 즉시 반영 확인
|
||||
- [ ] 기존 고유 설정 100% 유지 확인
|
||||
- [ ] 새 필드 추가 시 기본값 자동 적용 확인
|
||||
- [ ] 기존 화면 렌더링 동일성 확인
|
||||
- [ ] 화면 디자이너 저장/로드 정상 동작 확인
|
||||
Reference in New Issue
Block a user