컴포넌트 리뉴얼 1.0
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
# Phase 0: 컴포넌트 사용 현황 분석
|
||||
|
||||
## 분석 일시
|
||||
|
||||
2024-12-19
|
||||
|
||||
## 분석 대상
|
||||
|
||||
- 활성화된 화면 정의 (screen_definitions.is_active = 'Y')
|
||||
- 화면 레이아웃 (screen_layouts)
|
||||
|
||||
---
|
||||
|
||||
## 1. 컴포넌트별 사용량 순위
|
||||
|
||||
### 상위 15개 컴포넌트
|
||||
|
||||
| 순위 | 컴포넌트 | 사용 횟수 | 사용 화면 수 | Unified 매핑 |
|
||||
| :--: | :-------------------------- | :-------: | :----------: | :------------------------------ |
|
||||
| 1 | button-primary | 571 | 364 | UnifiedInput (type: button) |
|
||||
| 2 | text-input | 805 | 166 | **UnifiedInput (type: text)** |
|
||||
| 3 | table-list | 130 | 130 | UnifiedList (viewMode: table) |
|
||||
| 4 | table-search-widget | 127 | 127 | UnifiedList (searchable: true) |
|
||||
| 5 | select-basic | 121 | 76 | **UnifiedSelect** |
|
||||
| 6 | number-input | 86 | 34 | **UnifiedInput (type: number)** |
|
||||
| 7 | date-input | 83 | 51 | **UnifiedDate** |
|
||||
| 8 | file-upload | 41 | 18 | UnifiedMedia (type: file) |
|
||||
| 9 | tabs-widget | 39 | 39 | UnifiedGroup (type: tabs) |
|
||||
| 10 | split-panel-layout | 39 | 39 | UnifiedLayout (type: split) |
|
||||
| 11 | category-manager | 38 | 38 | UnifiedBiz (type: category) |
|
||||
| 12 | numbering-rule | 31 | 31 | UnifiedBiz (type: numbering) |
|
||||
| 13 | selected-items-detail-input | 29 | 29 | 복합 컴포넌트 |
|
||||
| 14 | modal-repeater-table | 25 | 25 | UnifiedList (modal: true) |
|
||||
| 15 | image-widget | 29 | 29 | UnifiedMedia (type: image) |
|
||||
|
||||
---
|
||||
|
||||
## 2. Unified 컴포넌트별 통합 대상 분석
|
||||
|
||||
### UnifiedInput (예상 통합 대상: 891개)
|
||||
|
||||
| 기존 컴포넌트 | 사용 횟수 | 비율 |
|
||||
| :------------ | :-------: | :---: |
|
||||
| text-input | 805 | 90.3% |
|
||||
| number-input | 86 | 9.7% |
|
||||
|
||||
**우선순위: 1위** - 가장 많이 사용되는 컴포넌트
|
||||
|
||||
### UnifiedSelect (예상 통합 대상: 140개)
|
||||
|
||||
| 기존 컴포넌트 | 사용 횟수 | widgetType |
|
||||
| :------------------------ | :-------: | :--------- |
|
||||
| select-basic (category) | 65 | category |
|
||||
| select-basic (null) | 50 | - |
|
||||
| autocomplete-search-input | 19 | entity |
|
||||
| entity-search-input | 20 | entity |
|
||||
| checkbox-basic | 7 | checkbox |
|
||||
| radio-basic | 5 | radio |
|
||||
|
||||
**우선순위: 2위** - 다양한 모드 지원 필요
|
||||
|
||||
### UnifiedDate (예상 통합 대상: 83개)
|
||||
|
||||
| 기존 컴포넌트 | 사용 횟수 |
|
||||
| :---------------- | :-------: |
|
||||
| date-input (null) | 58 |
|
||||
| date-input (date) | 23 |
|
||||
| date-input (text) | 2 |
|
||||
|
||||
**우선순위: 3위**
|
||||
|
||||
### UnifiedList (예상 통합 대상: 283개)
|
||||
|
||||
| 기존 컴포넌트 | 사용 횟수 | 비고 |
|
||||
| :-------------------- | :-------: | :---------- |
|
||||
| table-list | 130 | 기본 테이블 |
|
||||
| table-search-widget | 127 | 검색 테이블 |
|
||||
| modal-repeater-table | 25 | 모달 반복 |
|
||||
| repeater-field-group | 15 | 반복 필드 |
|
||||
| card-display | 11 | 카드 표시 |
|
||||
| simple-repeater-table | 1 | 단순 반복 |
|
||||
|
||||
**우선순위: 4위** - 핵심 데이터 표시 컴포넌트
|
||||
|
||||
### UnifiedMedia (예상 통합 대상: 70개)
|
||||
|
||||
| 기존 컴포넌트 | 사용 횟수 |
|
||||
| :------------ | :-------: |
|
||||
| file-upload | 41 |
|
||||
| image-widget | 29 |
|
||||
|
||||
### UnifiedLayout (예상 통합 대상: 62개)
|
||||
|
||||
| 기존 컴포넌트 | 사용 횟수 |
|
||||
| :------------------ | :-------: |
|
||||
| split-panel-layout | 39 |
|
||||
| screen-split-panel | 21 |
|
||||
| split-panel-layout2 | 2 |
|
||||
|
||||
### UnifiedGroup (예상 통합 대상: 99개)
|
||||
|
||||
| 기존 컴포넌트 | 사용 횟수 |
|
||||
| :-------------------- | :-------: |
|
||||
| tabs-widget | 39 |
|
||||
| conditional-container | 23 |
|
||||
| section-paper | 11 |
|
||||
| section-card | 10 |
|
||||
| text-display | 13 |
|
||||
| universal-form-modal | 7 |
|
||||
| repeat-screen-modal | 5 |
|
||||
|
||||
### UnifiedBiz (예상 통합 대상: 79개)
|
||||
|
||||
| 기존 컴포넌트 | 사용 횟수 |
|
||||
| :--------------------- | :-------: |
|
||||
| category-manager | 38 |
|
||||
| numbering-rule | 31 |
|
||||
| flow-widget | 8 |
|
||||
| rack-structure | 2 |
|
||||
| related-data-buttons | 2 |
|
||||
| location-swap-selector | 2 |
|
||||
| tax-invoice-list | 1 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 구현 우선순위 결정
|
||||
|
||||
### Phase 1 우선순위 (즉시 효과가 큰 컴포넌트)
|
||||
|
||||
| 순위 | Unified 컴포넌트 | 통합 대상 수 | 영향 화면 수 | 이유 |
|
||||
| :---: | :---------------- | :----------: | :----------: | :--------------- |
|
||||
| **1** | **UnifiedInput** | 891개 | 200+ | 가장 많이 사용 |
|
||||
| **2** | **UnifiedSelect** | 140개 | 100+ | 다양한 모드 필요 |
|
||||
| **3** | **UnifiedDate** | 83개 | 51 | 비교적 단순 |
|
||||
|
||||
### Phase 2 우선순위 (데이터 표시 컴포넌트)
|
||||
|
||||
| 순위 | Unified 컴포넌트 | 통합 대상 수 | 이유 |
|
||||
| :---: | :---------------- | :----------: | :--------------- |
|
||||
| **4** | **UnifiedList** | 283개 | 핵심 데이터 표시 |
|
||||
| **5** | **UnifiedLayout** | 62개 | 레이아웃 구조 |
|
||||
| **6** | **UnifiedGroup** | 99개 | 콘텐츠 그룹화 |
|
||||
|
||||
### Phase 3 우선순위 (특수 컴포넌트)
|
||||
|
||||
| 순위 | Unified 컴포넌트 | 통합 대상 수 | 이유 |
|
||||
| :---: | :------------------- | :----------: | :------------ |
|
||||
| **7** | **UnifiedMedia** | 70개 | 파일/이미지 |
|
||||
| **8** | **UnifiedBiz** | 79개 | 비즈니스 특화 |
|
||||
| **9** | **UnifiedHierarchy** | 0개 | 신규 기능 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 주요 발견 사항
|
||||
|
||||
### 4.1 button-primary 분리 검토
|
||||
|
||||
- 사용량: 571개 (1위)
|
||||
- 현재 계획: UnifiedInput에 포함
|
||||
- **제안**: 별도 `UnifiedButton` 컴포넌트로 분리 검토
|
||||
- 버튼은 입력과 성격이 다름
|
||||
- 액션 타입, 스타일, 권한 등 복잡한 설정 필요
|
||||
|
||||
### 4.2 conditional-container 처리
|
||||
|
||||
- 사용량: 23개
|
||||
- 현재 계획: 공통 conditional 속성으로 통합
|
||||
- **확인 필요**: 기존 화면에서 어떻게 마이그레이션할지
|
||||
|
||||
### 4.3 category 관련 컴포넌트
|
||||
|
||||
- select-basic (category): 65개
|
||||
- category-manager: 38개
|
||||
- **총 103개**의 카테고리 관련 컴포넌트
|
||||
- 카테고리 시스템 통합 중요
|
||||
|
||||
---
|
||||
|
||||
## 5. 다음 단계
|
||||
|
||||
1. [ ] 데이터 마이그레이션 전략 설계 (Phase 0-2)
|
||||
2. [ ] sys_input_type JSON Schema 설계 (Phase 0-3)
|
||||
3. [ ] DynamicConfigPanel 프로토타입 (Phase 0-4)
|
||||
4. [ ] UnifiedInput 구현 시작 (Phase 1-1)
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
# Phase 0: 데이터 마이그레이션 전략
|
||||
|
||||
## 1. 현재 데이터 구조 분석
|
||||
|
||||
### screen_layouts.properties 구조
|
||||
|
||||
```jsonc
|
||||
{
|
||||
// 기본 정보
|
||||
"type": "component",
|
||||
"componentType": "text-input", // 기존 컴포넌트 타입
|
||||
|
||||
// 위치/크기
|
||||
"position": { "x": 68, "y": 80, "z": 1 },
|
||||
"size": { "width": 324, "height": 40 },
|
||||
|
||||
// 라벨 및 스타일
|
||||
"label": "품목코드",
|
||||
"style": {
|
||||
"labelColor": "#000000",
|
||||
"labelDisplay": true,
|
||||
"labelFontSize": "14px",
|
||||
"labelFontWeight": "500",
|
||||
"labelMarginBottom": "8px"
|
||||
},
|
||||
|
||||
// 데이터 바인딩
|
||||
"tableName": "order_table",
|
||||
"columnName": "part_code",
|
||||
|
||||
// 필드 속성
|
||||
"required": true,
|
||||
"readonly": false,
|
||||
|
||||
// 컴포넌트별 설정
|
||||
"componentConfig": {
|
||||
"type": "text-input",
|
||||
"format": "none",
|
||||
"webType": "text",
|
||||
"multiline": false,
|
||||
"placeholder": "텍스트를 입력하세요"
|
||||
},
|
||||
|
||||
// 그리드 레이아웃
|
||||
"gridColumns": 5,
|
||||
"gridRowIndex": 0,
|
||||
"gridColumnStart": 1,
|
||||
"gridColumnSpan": "third",
|
||||
|
||||
// 기타
|
||||
"parentId": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 마이그레이션 전략: 하이브리드 방식
|
||||
|
||||
### 2.1 비파괴적 전환 (권장)
|
||||
|
||||
기존 필드를 유지하면서 새로운 필드를 추가하는 방식
|
||||
|
||||
```jsonc
|
||||
{
|
||||
// 기존 필드 유지 (하위 호환성)
|
||||
"componentType": "text-input",
|
||||
"componentConfig": { ... },
|
||||
|
||||
// 신규 필드 추가
|
||||
"unifiedType": "UnifiedInput", // 새로운 통합 컴포넌트 타입
|
||||
"unifiedConfig": { // 새로운 설정 구조
|
||||
"type": "text",
|
||||
"format": "none",
|
||||
"placeholder": "텍스트를 입력하세요"
|
||||
},
|
||||
|
||||
// 마이그레이션 메타데이터
|
||||
"_migration": {
|
||||
"version": "2.0",
|
||||
"migratedAt": "2024-12-19T00:00:00Z",
|
||||
"migratedBy": "system",
|
||||
"originalType": "text-input"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 렌더링 로직 수정
|
||||
|
||||
```typescript
|
||||
// 렌더러에서 unifiedType 우선 사용
|
||||
function renderComponent(props: ComponentProps) {
|
||||
// 신규 타입이 있으면 Unified 컴포넌트 사용
|
||||
if (props.unifiedType) {
|
||||
return <UnifiedComponentRenderer
|
||||
type={props.unifiedType}
|
||||
config={props.unifiedConfig}
|
||||
/>;
|
||||
}
|
||||
|
||||
// 없으면 기존 레거시 컴포넌트 사용
|
||||
return <LegacyComponentRenderer
|
||||
type={props.componentType}
|
||||
config={props.componentConfig}
|
||||
/>;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 컴포넌트별 매핑 규칙
|
||||
|
||||
### 3.1 text-input → UnifiedInput
|
||||
|
||||
```typescript
|
||||
// AS-IS
|
||||
{
|
||||
"componentType": "text-input",
|
||||
"componentConfig": {
|
||||
"type": "text-input",
|
||||
"format": "none",
|
||||
"webType": "text",
|
||||
"multiline": false,
|
||||
"placeholder": "텍스트를 입력하세요"
|
||||
}
|
||||
}
|
||||
|
||||
// TO-BE
|
||||
{
|
||||
"unifiedType": "UnifiedInput",
|
||||
"unifiedConfig": {
|
||||
"type": "text", // componentConfig.webType 또는 "text"
|
||||
"format": "none", // componentConfig.format
|
||||
"placeholder": "..." // componentConfig.placeholder
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 number-input → UnifiedInput
|
||||
|
||||
```typescript
|
||||
// AS-IS
|
||||
{
|
||||
"componentType": "number-input",
|
||||
"componentConfig": {
|
||||
"type": "number-input",
|
||||
"webType": "number",
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"step": 1
|
||||
}
|
||||
}
|
||||
|
||||
// TO-BE
|
||||
{
|
||||
"unifiedType": "UnifiedInput",
|
||||
"unifiedConfig": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"step": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 select-basic → UnifiedSelect
|
||||
|
||||
```typescript
|
||||
// AS-IS (code 타입)
|
||||
{
|
||||
"componentType": "select-basic",
|
||||
"codeCategory": "ORDER_STATUS",
|
||||
"componentConfig": {
|
||||
"type": "select-basic",
|
||||
"webType": "code",
|
||||
"codeCategory": "ORDER_STATUS"
|
||||
}
|
||||
}
|
||||
|
||||
// TO-BE
|
||||
{
|
||||
"unifiedType": "UnifiedSelect",
|
||||
"unifiedConfig": {
|
||||
"mode": "dropdown",
|
||||
"source": "code",
|
||||
"codeGroup": "ORDER_STATUS"
|
||||
}
|
||||
}
|
||||
|
||||
// AS-IS (entity 타입)
|
||||
{
|
||||
"componentType": "select-basic",
|
||||
"componentConfig": {
|
||||
"type": "select-basic",
|
||||
"webType": "entity",
|
||||
"searchable": true,
|
||||
"valueField": "id",
|
||||
"displayField": "name"
|
||||
}
|
||||
}
|
||||
|
||||
// TO-BE
|
||||
{
|
||||
"unifiedType": "UnifiedSelect",
|
||||
"unifiedConfig": {
|
||||
"mode": "dropdown",
|
||||
"source": "entity",
|
||||
"searchable": true,
|
||||
"valueField": "id",
|
||||
"displayField": "name"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.4 date-input → UnifiedDate
|
||||
|
||||
```typescript
|
||||
// AS-IS
|
||||
{
|
||||
"componentType": "date-input",
|
||||
"componentConfig": {
|
||||
"type": "date-input",
|
||||
"webType": "date",
|
||||
"format": "YYYY-MM-DD"
|
||||
}
|
||||
}
|
||||
|
||||
// TO-BE
|
||||
{
|
||||
"unifiedType": "UnifiedDate",
|
||||
"unifiedConfig": {
|
||||
"type": "date",
|
||||
"format": "YYYY-MM-DD"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 마이그레이션 스크립트
|
||||
|
||||
### 4.1 자동 마이그레이션 함수
|
||||
|
||||
```typescript
|
||||
// lib/migration/componentMigration.ts
|
||||
|
||||
interface MigrationResult {
|
||||
success: boolean;
|
||||
unifiedType: string;
|
||||
unifiedConfig: Record<string, any>;
|
||||
}
|
||||
|
||||
export function migrateToUnified(
|
||||
componentType: string,
|
||||
componentConfig: Record<string, any>
|
||||
): MigrationResult {
|
||||
|
||||
switch (componentType) {
|
||||
case 'text-input':
|
||||
return {
|
||||
success: true,
|
||||
unifiedType: 'UnifiedInput',
|
||||
unifiedConfig: {
|
||||
type: componentConfig.webType || 'text',
|
||||
format: componentConfig.format || 'none',
|
||||
placeholder: componentConfig.placeholder
|
||||
}
|
||||
};
|
||||
|
||||
case 'number-input':
|
||||
return {
|
||||
success: true,
|
||||
unifiedType: 'UnifiedInput',
|
||||
unifiedConfig: {
|
||||
type: 'number',
|
||||
min: componentConfig.min,
|
||||
max: componentConfig.max,
|
||||
step: componentConfig.step
|
||||
}
|
||||
};
|
||||
|
||||
case 'select-basic':
|
||||
return {
|
||||
success: true,
|
||||
unifiedType: 'UnifiedSelect',
|
||||
unifiedConfig: {
|
||||
mode: 'dropdown',
|
||||
source: componentConfig.webType || 'static',
|
||||
codeGroup: componentConfig.codeCategory,
|
||||
searchable: componentConfig.searchable,
|
||||
valueField: componentConfig.valueField,
|
||||
displayField: componentConfig.displayField
|
||||
}
|
||||
};
|
||||
|
||||
case 'date-input':
|
||||
return {
|
||||
success: true,
|
||||
unifiedType: 'UnifiedDate',
|
||||
unifiedConfig: {
|
||||
type: componentConfig.webType || 'date',
|
||||
format: componentConfig.format
|
||||
}
|
||||
};
|
||||
|
||||
default:
|
||||
return {
|
||||
success: false,
|
||||
unifiedType: '',
|
||||
unifiedConfig: {}
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 DB 마이그레이션 스크립트
|
||||
|
||||
```sql
|
||||
-- 마이그레이션 백업 테이블 생성
|
||||
CREATE TABLE screen_layouts_backup_v2 AS
|
||||
SELECT * FROM screen_layouts;
|
||||
|
||||
-- 마이그레이션 실행 (text-input 예시)
|
||||
UPDATE screen_layouts
|
||||
SET properties = properties || jsonb_build_object(
|
||||
'unifiedType', 'UnifiedInput',
|
||||
'unifiedConfig', jsonb_build_object(
|
||||
'type', COALESCE(properties->'componentConfig'->>'webType', 'text'),
|
||||
'format', COALESCE(properties->'componentConfig'->>'format', 'none'),
|
||||
'placeholder', properties->'componentConfig'->>'placeholder'
|
||||
),
|
||||
'_migration', jsonb_build_object(
|
||||
'version', '2.0',
|
||||
'migratedAt', NOW(),
|
||||
'originalType', 'text-input'
|
||||
)
|
||||
)
|
||||
WHERE properties->>'componentType' = 'text-input';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 롤백 전략
|
||||
|
||||
### 5.1 롤백 스크립트
|
||||
|
||||
```sql
|
||||
-- 마이그레이션 전 상태로 복원
|
||||
UPDATE screen_layouts sl
|
||||
SET properties = slb.properties
|
||||
FROM screen_layouts_backup_v2 slb
|
||||
WHERE sl.layout_id = slb.layout_id;
|
||||
|
||||
-- 또는 신규 필드만 제거
|
||||
UPDATE screen_layouts
|
||||
SET properties = properties - 'unifiedType' - 'unifiedConfig' - '_migration';
|
||||
```
|
||||
|
||||
### 5.2 단계적 롤백
|
||||
|
||||
```typescript
|
||||
// 특정 화면만 롤백
|
||||
async function rollbackScreen(screenId: number) {
|
||||
await db.query(`
|
||||
UPDATE screen_layouts sl
|
||||
SET properties = properties - 'unifiedType' - 'unifiedConfig' - '_migration'
|
||||
WHERE screen_id = $1
|
||||
`, [screenId]);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 마이그레이션 일정
|
||||
|
||||
| 단계 | 작업 | 대상 | 시점 |
|
||||
|:---:|:---|:---|:---|
|
||||
| 1 | 백업 테이블 생성 | 전체 | Phase 1 시작 전 |
|
||||
| 2 | UnifiedInput 마이그레이션 | text-input, number-input | Phase 1 중 |
|
||||
| 3 | UnifiedSelect 마이그레이션 | select-basic | Phase 1 중 |
|
||||
| 4 | UnifiedDate 마이그레이션 | date-input | Phase 1 중 |
|
||||
| 5 | 검증 및 테스트 | 전체 | Phase 1 완료 후 |
|
||||
| 6 | 레거시 필드 제거 | 전체 | Phase 5 (추후) |
|
||||
|
||||
---
|
||||
|
||||
## 7. 주의사항
|
||||
|
||||
1. **항상 백업 먼저**: 마이그레이션 전 반드시 백업 테이블 생성
|
||||
2. **점진적 전환**: 한 번에 모든 컴포넌트를 마이그레이션하지 않음
|
||||
3. **하위 호환성**: 기존 필드 유지로 롤백 가능하게
|
||||
4. **테스트 필수**: 각 마이그레이션 단계별 화면 테스트
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
# Unified Components 구현 완료 보고서
|
||||
|
||||
## 구현 일시
|
||||
|
||||
2024-12-19
|
||||
|
||||
## 구현된 컴포넌트 목록 (10개)
|
||||
|
||||
### Phase 1: 핵심 입력 컴포넌트
|
||||
|
||||
| 컴포넌트 | 파일 | 모드/타입 | 설명 |
|
||||
| :---------------- | :------------------ | :-------------------------------------------- | :---------------------- |
|
||||
| **UnifiedInput** | `UnifiedInput.tsx` | text, number, password, slider, color, button | 통합 입력 컴포넌트 |
|
||||
| **UnifiedSelect** | `UnifiedSelect.tsx` | dropdown, radio, check, tag, toggle, swap | 통합 선택 컴포넌트 |
|
||||
| **UnifiedDate** | `UnifiedDate.tsx` | date, time, datetime + range | 통합 날짜/시간 컴포넌트 |
|
||||
|
||||
### Phase 2: 레이아웃 및 그룹 컴포넌트
|
||||
|
||||
| 컴포넌트 | 파일 | 모드/타입 | 설명 |
|
||||
| :---------------- | :------------------ | :-------------------------------------------------------- | :--------------------- |
|
||||
| **UnifiedList** | `UnifiedList.tsx` | table, card, kanban, list | 통합 리스트 컴포넌트 |
|
||||
| **UnifiedLayout** | `UnifiedLayout.tsx` | grid, split, flex, divider, screen-embed | 통합 레이아웃 컴포넌트 |
|
||||
| **UnifiedGroup** | `UnifiedGroup.tsx` | tabs, accordion, section, card-section, modal, form-modal | 통합 그룹 컴포넌트 |
|
||||
|
||||
### Phase 3: 미디어 및 비즈니스 컴포넌트
|
||||
|
||||
| 컴포넌트 | 파일 | 모드/타입 | 설명 |
|
||||
| :------------------- | :--------------------- | :------------------------------------------------------------- | :---------------------- |
|
||||
| **UnifiedMedia** | `UnifiedMedia.tsx` | file, image, video, audio | 통합 미디어 컴포넌트 |
|
||||
| **UnifiedBiz** | `UnifiedBiz.tsx` | flow, rack, map, numbering, category, mapping, related-buttons | 통합 비즈니스 컴포넌트 |
|
||||
| **UnifiedHierarchy** | `UnifiedHierarchy.tsx` | tree, org, bom, cascading | 통합 계층 구조 컴포넌트 |
|
||||
|
||||
---
|
||||
|
||||
## 공통 인프라
|
||||
|
||||
### 설정 패널
|
||||
|
||||
- **DynamicConfigPanel**: JSON Schema 기반 동적 설정 UI 생성
|
||||
|
||||
### 렌더러
|
||||
|
||||
- **UnifiedComponentRenderer**: unifiedType에 따른 동적 컴포넌트 렌더링
|
||||
|
||||
---
|
||||
|
||||
## 파일 구조
|
||||
|
||||
```
|
||||
frontend/components/unified/
|
||||
├── index.ts # 모듈 인덱스
|
||||
├── UnifiedComponentRenderer.tsx # 동적 렌더러
|
||||
├── DynamicConfigPanel.tsx # JSON Schema 설정 패널
|
||||
├── UnifiedInput.tsx # 통합 입력
|
||||
├── UnifiedSelect.tsx # 통합 선택
|
||||
├── UnifiedDate.tsx # 통합 날짜
|
||||
├── UnifiedList.tsx # 통합 리스트
|
||||
├── UnifiedLayout.tsx # 통합 레이아웃
|
||||
├── UnifiedGroup.tsx # 통합 그룹
|
||||
├── UnifiedMedia.tsx # 통합 미디어
|
||||
├── UnifiedBiz.tsx # 통합 비즈니스
|
||||
└── UnifiedHierarchy.tsx # 통합 계층
|
||||
|
||||
frontend/types/
|
||||
└── unified-components.ts # 타입 정의
|
||||
|
||||
db/migrations/
|
||||
└── unified_component_schema.sql # DB 스키마 (미실행)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 사용 예시
|
||||
|
||||
### 기본 사용법
|
||||
|
||||
```tsx
|
||||
import {
|
||||
UnifiedInput,
|
||||
UnifiedSelect,
|
||||
UnifiedDate,
|
||||
UnifiedList,
|
||||
UnifiedComponentRenderer
|
||||
} from "@/components/unified";
|
||||
|
||||
// UnifiedInput 사용
|
||||
<UnifiedInput
|
||||
id="name"
|
||||
label="이름"
|
||||
required
|
||||
config={{ type: "text", placeholder: "이름을 입력하세요" }}
|
||||
value={name}
|
||||
onChange={setName}
|
||||
/>
|
||||
|
||||
// UnifiedSelect 사용
|
||||
<UnifiedSelect
|
||||
id="status"
|
||||
label="상태"
|
||||
config={{
|
||||
mode: "dropdown",
|
||||
source: "code",
|
||||
codeGroup: "ORDER_STATUS",
|
||||
searchable: true
|
||||
}}
|
||||
value={status}
|
||||
onChange={setStatus}
|
||||
/>
|
||||
|
||||
// UnifiedDate 사용
|
||||
<UnifiedDate
|
||||
id="orderDate"
|
||||
label="주문일"
|
||||
config={{ type: "date", format: "YYYY-MM-DD" }}
|
||||
value={orderDate}
|
||||
onChange={setOrderDate}
|
||||
/>
|
||||
|
||||
// UnifiedList 사용
|
||||
<UnifiedList
|
||||
id="orderList"
|
||||
label="주문 목록"
|
||||
config={{
|
||||
viewMode: "table",
|
||||
searchable: true,
|
||||
pageable: true,
|
||||
pageSize: 10,
|
||||
columns: [
|
||||
{ field: "orderId", header: "주문번호", sortable: true },
|
||||
{ field: "customerName", header: "고객명" },
|
||||
{ field: "orderDate", header: "주문일", format: "date" },
|
||||
]
|
||||
}}
|
||||
data={orders}
|
||||
onRowClick={handleRowClick}
|
||||
/>
|
||||
```
|
||||
|
||||
### 동적 렌더링
|
||||
|
||||
```tsx
|
||||
import { UnifiedComponentRenderer } from "@/components/unified";
|
||||
|
||||
// unifiedType에 따라 자동으로 적절한 컴포넌트 렌더링
|
||||
<UnifiedComponentRenderer
|
||||
props={{
|
||||
unifiedType: "UnifiedInput",
|
||||
id: "dynamicField",
|
||||
label: "동적 필드",
|
||||
config: { type: "text" },
|
||||
value: fieldValue,
|
||||
onChange: setFieldValue,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 주의사항
|
||||
|
||||
### 기존 컴포넌트와의 공존
|
||||
|
||||
1. **기존 컴포넌트는 그대로 유지**: 모든 레거시 컴포넌트는 정상 동작
|
||||
2. **신규 화면에서만 Unified 컴포넌트 사용**: 기존 화면에 영향 없음
|
||||
3. **마이그레이션 없음**: 자동 마이그레이션 진행하지 않음
|
||||
|
||||
### 데이터베이스 마이그레이션
|
||||
|
||||
`db/migrations/unified_component_schema.sql` 파일은 아직 실행되지 않았습니다.
|
||||
필요시 수동으로 실행해야 합니다:
|
||||
|
||||
```bash
|
||||
psql -h localhost -U postgres -d plm_db -f db/migrations/unified_component_schema.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 다음 단계 (선택)
|
||||
|
||||
1. **화면 관리 에디터 통합**: Unified 컴포넌트를 화면 에디터의 컴포넌트 팔레트에 추가
|
||||
2. **기존 비즈니스 컴포넌트 연동**: UnifiedBiz의 플레이스홀더를 실제 구현으로 교체
|
||||
3. **테스트 페이지 작성**: 모든 Unified 컴포넌트 데모 페이지
|
||||
4. **문서화**: 각 컴포넌트별 상세 사용 가이드
|
||||
|
||||
---
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- `PLAN_RENEWAL.md`: 리뉴얼 계획서
|
||||
- `docs/phase0-component-usage-analysis.md`: 컴포넌트 사용 현황 분석
|
||||
- `docs/phase0-migration-strategy.md`: 마이그레이션 전략 (참고용)
|
||||
|
||||
@@ -586,3 +586,4 @@ const result = await executeNodeFlow(flowId, {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -359,3 +359,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -345,3 +345,4 @@ const getComponentValue = (componentId: string) => {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user