docs: 다양한 문서 및 가이드 업데이트
- 여러 문서의 내용을 업데이트하여 최신 정보를 반영하였습니다. - 컴포넌트 개발 가이드와 관련된 문서의 목차를 재구성하고, V2 및 Zod 레이아웃 시스템에 대한 내용을 추가하였습니다. - 화면 컴포넌트 개발 가이드를 개선하여 핵심 원칙과 패턴을 명확히 설명하였습니다. - 불필요한 문서 및 가이드를 삭제하고, 통합된 가이드를 통해 개발자들이 쉽게 참고할 수 있도록 하였습니다.
This commit is contained in:
parent
e0ee375f01
commit
95bef976a5
|
|
@ -51,7 +51,7 @@ alwaysApply: false
|
||||||
| `v2-split-panel-layout` | 분할 패널 | 좌우/상하 분할 |
|
| `v2-split-panel-layout` | 분할 패널 | 좌우/상하 분할 |
|
||||||
| `v2-numbering-rule` | 채번 규칙 | 자동 채번 생성 |
|
| `v2-numbering-rule` | 채번 규칙 | 자동 채번 생성 |
|
||||||
| `v2-tabs-widget` | 탭 위젯 | 탭 레이아웃 |
|
| `v2-tabs-widget` | 탭 위젯 | 탭 레이아웃 |
|
||||||
| `v2-unified-repeater` | 통합 리피터 | 행 단위 입력/저장 |
|
| `v2-repeater` | 통합 리피터 | 행 단위 입력/저장 |
|
||||||
| `v2-rack-structure` | 렉 구조 | 창고 렉 위치 생성 |
|
| `v2-rack-structure` | 렉 구조 | 창고 렉 위치 생성 |
|
||||||
| `v2-section-paper` | 섹션 페이퍼 | 섹션 컨테이너 |
|
| `v2-section-paper` | 섹션 페이퍼 | 섹션 컨테이너 |
|
||||||
| `v2-section-card` | 섹션 카드 | 카드 컨테이너 |
|
| `v2-section-card` | 섹션 카드 | 카드 컨테이너 |
|
||||||
|
|
@ -118,7 +118,7 @@ export const V2TableListDefinition = createComponentDefinition({
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"id": "comp_xxx",
|
"id": "comp_xxx",
|
||||||
"url": "@/lib/registry/components/unified-select",
|
"url": "@/lib/registry/components/v2-select",
|
||||||
"position": { "x": 100, "y": 50 },
|
"position": { "x": 100, "y": 50 },
|
||||||
"size": { "width": 180, "height": 30 },
|
"size": { "width": 180, "height": 30 },
|
||||||
"displayOrder": 0,
|
"displayOrder": 0,
|
||||||
|
|
@ -226,7 +226,7 @@ export function convertV2ToLegacy(v2Layout: LayoutV2): LegacyLayoutData {
|
||||||
// frontend/lib/schemas/componentConfig.ts
|
// frontend/lib/schemas/componentConfig.ts
|
||||||
|
|
||||||
// 컴포넌트별 overrides 스키마
|
// 컴포넌트별 overrides 스키마
|
||||||
export const unifiedSelectOverridesSchema = z.object({
|
export const v2SelectOverridesSchema = z.object({
|
||||||
mode: z.enum(["dropdown", "combobox", "radio", "checkbox"]).default("dropdown"),
|
mode: z.enum(["dropdown", "combobox", "radio", "checkbox"]).default("dropdown"),
|
||||||
source: z.enum(["static", "code", "entity", "db", "distinct"]).default("distinct"),
|
source: z.enum(["static", "code", "entity", "db", "distinct"]).default("distinct"),
|
||||||
multiple: z.boolean().default(false),
|
multiple: z.boolean().default(false),
|
||||||
|
|
@ -236,15 +236,15 @@ export const unifiedSelectOverridesSchema = z.object({
|
||||||
|
|
||||||
// 스키마 레지스트리
|
// 스키마 레지스트리
|
||||||
export const componentOverridesSchemaRegistry: Record<string, z.ZodType<any>> = {
|
export const componentOverridesSchemaRegistry: Record<string, z.ZodType<any>> = {
|
||||||
"unified-select": unifiedSelectOverridesSchema,
|
"v2-select": v2SelectOverridesSchema,
|
||||||
"unified-input": unifiedInputOverridesSchema,
|
"v2-input": v2InputOverridesSchema,
|
||||||
"v2-table-list": v2TableListOverridesSchema,
|
"v2-table-list": v2TableListOverridesSchema,
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
|
|
||||||
// 기본값 레지스트리
|
// 기본값 레지스트리
|
||||||
export const componentDefaultsRegistry: Record<string, any> = {
|
export const componentDefaultsRegistry: Record<string, any> = {
|
||||||
"unified-select": {
|
"v2-select": {
|
||||||
mode: "dropdown",
|
mode: "dropdown",
|
||||||
source: "distinct", // 기본: 테이블 컬럼에서 자동 로드
|
source: "distinct", // 기본: 테이블 컬럼에서 자동 로드
|
||||||
multiple: false,
|
multiple: false,
|
||||||
|
|
@ -254,7 +254,7 @@ export const componentDefaultsRegistry: Record<string, any> = {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### unified-select 자동 옵션 로드
|
### v2-select 자동 옵션 로드
|
||||||
|
|
||||||
`webType`이 `"select"`인 컬럼을 드래그하면:
|
`webType`이 `"select"`인 컬럼을 드래그하면:
|
||||||
|
|
||||||
|
|
@ -265,9 +265,9 @@ export const componentDefaultsRegistry: Record<string, any> = {
|
||||||
```typescript
|
```typescript
|
||||||
// DynamicComponentRenderer.tsx
|
// DynamicComponentRenderer.tsx
|
||||||
|
|
||||||
case "unified-select":
|
case "v2-select":
|
||||||
return (
|
return (
|
||||||
<UnifiedSelect
|
<V2Select
|
||||||
{...commonProps}
|
{...commonProps}
|
||||||
config={{
|
config={{
|
||||||
mode: config.mode || "dropdown",
|
mode: config.mode || "dropdown",
|
||||||
|
|
@ -604,26 +604,26 @@ if (!silentActions.includes(actionType)) {
|
||||||
|
|
||||||
| inputType | 생성 위젯 | 설명 |
|
| inputType | 생성 위젯 | 설명 |
|
||||||
|-----------|----------|------|
|
|-----------|----------|------|
|
||||||
| `text`, `textarea` | UnifiedInput | 텍스트 입력 |
|
| `text`, `textarea` | V2Input | 텍스트 입력 |
|
||||||
| `number` | UnifiedInput | 숫자 입력 |
|
| `number` | V2Input | 숫자 입력 |
|
||||||
| `date`, `datetime` | UnifiedDate | 날짜/시간 선택 |
|
| `date`, `datetime` | V2Date | 날짜/시간 선택 |
|
||||||
| `code`, `category`, `entity` | UnifiedSelect | 선택박스 |
|
| `code`, `category`, `entity` | V2Select | 선택박스 |
|
||||||
| `checkbox`, `radio` | 체크박스/라디오 | 선택 |
|
| `checkbox`, `radio` | 체크박스/라디오 | 선택 |
|
||||||
| `image`, `file` | UnifiedMedia | 파일 업로드 |
|
| `image`, `file` | V2Media | 파일 업로드 |
|
||||||
|
|
||||||
### 핵심 Unified 컴포넌트 (3개)
|
### 핵심 V2 컴포넌트 (3개)
|
||||||
|
|
||||||
| 컴포넌트 | 담당 inputType | 파일 경로 |
|
| 컴포넌트 | 담당 inputType | 파일 경로 |
|
||||||
|----------|---------------|-----------|
|
|----------|---------------|-----------|
|
||||||
| `UnifiedInput` | text, textarea, number, password | `components/unified/UnifiedInput.tsx` |
|
| `V2Input` | text, textarea, number, password | `components/v2/V2Input.tsx` |
|
||||||
| `UnifiedSelect` | code, category, entity, select | `components/unified/UnifiedSelect.tsx` |
|
| `V2Select` | code, category, entity, select | `components/v2/V2Select.tsx` |
|
||||||
| `UnifiedDate` | date, datetime, time, daterange | `components/unified/UnifiedDate.tsx` |
|
| `V2Date` | date, datetime, time, daterange | `components/v2/V2Date.tsx` |
|
||||||
|
|
||||||
### 컴포넌트 패널에서 직접 드래그 가능한 컴포넌트
|
### 컴포넌트 패널에서 직접 드래그 가능한 컴포넌트
|
||||||
|
|
||||||
| 컴포넌트 ID | 이름 | 설명 |
|
| 컴포넌트 ID | 이름 | 설명 |
|
||||||
|-------------|------|------|
|
|-------------|------|------|
|
||||||
| `v2-unified-repeater` | 리피터 그리드 | 행 단위 데이터 추가/수정/삭제 |
|
| `v2-repeater` | 리피터 그리드 | 행 단위 데이터 추가/수정/삭제 |
|
||||||
| `v2-table-list` | 테이블 리스트 | 데이터 목록 조회/필터/정렬 |
|
| `v2-table-list` | 테이블 리스트 | 데이터 목록 조회/필터/정렬 |
|
||||||
| `v2-table-search-widget` | 검색 필터 | 테이블 검색 조건 입력 |
|
| `v2-table-search-widget` | 검색 필터 | 테이블 검색 조건 입력 |
|
||||||
| `v2-button-primary` | 버튼 | 저장, 삭제, 조회 등 액션 |
|
| `v2-button-primary` | 버튼 | 저장, 삭제, 조회 등 액션 |
|
||||||
|
|
@ -725,7 +725,7 @@ interface TableListConfig {
|
||||||
#### 저장용 (리피터)
|
#### 저장용 (리피터)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface UnifiedRepeaterConfig {
|
interface V2RepeaterConfig {
|
||||||
mainTableName?: string; // 저장할 테이블명
|
mainTableName?: string; // 저장할 테이블명
|
||||||
useCustomTable?: boolean; // true: mainTableName 사용
|
useCustomTable?: boolean; // true: mainTableName 사용
|
||||||
foreignKeyColumn?: string; // FK 컬럼 (예: receiving_id)
|
foreignKeyColumn?: string; // FK 컬럼 (예: receiving_id)
|
||||||
|
|
@ -920,7 +920,7 @@ const getEntityJoinValue = (item: any, columnName: string): any => {
|
||||||
|
|
||||||
## 10. 폼 데이터 관리
|
## 10. 폼 데이터 관리
|
||||||
|
|
||||||
### 통합 폼 시스템 (UnifiedFormContext)
|
### 통합 폼 시스템 (V2FormContext)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { useFormCompatibility } from "@/hooks/useFormCompatibility";
|
import { useFormCompatibility } from "@/hooks/useFormCompatibility";
|
||||||
|
|
@ -949,15 +949,15 @@ const MyComponent = ({ onFormDataChange, formData }) => {
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const handleChange = useCallback((value: any) => {
|
const handleChange = useCallback((value: any) => {
|
||||||
// 1. UnifiedFormContext
|
// 1. V2FormContext
|
||||||
unifiedContext?.setValue(fieldName, value);
|
v2Context?.setValue(fieldName, value);
|
||||||
|
|
||||||
// 2. ScreenContext
|
// 2. ScreenContext
|
||||||
screenContext?.updateFormData?.(fieldName, value);
|
screenContext?.updateFormData?.(fieldName, value);
|
||||||
|
|
||||||
// 3. 레거시 콜백
|
// 3. 레거시 콜백
|
||||||
onFormDataChange?.(fieldName, value);
|
onFormDataChange?.(fieldName, value);
|
||||||
}, [fieldName, unifiedContext, screenContext, onFormDataChange]);
|
}, [fieldName, v2Context, screenContext, onFormDataChange]);
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -1120,7 +1120,7 @@ const MyFormComponent = ({ formData, onFormDataChange }) => {
|
||||||
|
|
||||||
## 13. 표준 코드 스타일 가이드
|
## 13. 표준 코드 스타일 가이드
|
||||||
|
|
||||||
**`v2-unified-repeater`** 컴포넌트를 표준으로 삼아 동일한 구조로 작성합니다.
|
**`v2-repeater`** 컴포넌트를 표준으로 삼아 동일한 구조로 작성합니다.
|
||||||
|
|
||||||
### 핵심 원칙: 느슨한 결합도 (Loose Coupling)
|
### 핵심 원칙: 느슨한 결합도 (Loose Coupling)
|
||||||
|
|
||||||
|
|
@ -1675,7 +1675,7 @@ const derivedValue = useMemo(() => data.map(x => x.value), [data]);
|
||||||
- [ ] 테이블 컬럼 드래그 시 `tableName`, `columnName` 저장 확인
|
- [ ] 테이블 컬럼 드래그 시 `tableName`, `columnName` 저장 확인
|
||||||
- [ ] `convertLegacyToV2`에서 상위 레벨 속성 포함 확인
|
- [ ] `convertLegacyToV2`에서 상위 레벨 속성 포함 확인
|
||||||
- [ ] `convertV2ToLegacy`에서 상위 레벨 속성 복원 확인
|
- [ ] `convertV2ToLegacy`에서 상위 레벨 속성 복원 확인
|
||||||
- [ ] unified-select는 `source: "distinct"` 기본값 확인
|
- [ ] v2-select는 `source: "distinct"` 기본값 확인
|
||||||
|
|
||||||
### 표준 Props
|
### 표준 Props
|
||||||
|
|
||||||
|
|
@ -1749,7 +1749,7 @@ const derivedValue = useMemo(() => data.map(x => x.value), [data]);
|
||||||
|
|
||||||
### 코드 스타일
|
### 코드 스타일
|
||||||
|
|
||||||
- [ ] `v2-unified-repeater` 구조 참고
|
- [ ] `v2-repeater` 구조 참고
|
||||||
- [ ] 느슨한 결합도 유지 (이벤트 기반 통신)
|
- [ ] 느슨한 결합도 유지 (이벤트 기반 통신)
|
||||||
|
|
||||||
### 성능 최적화
|
### 성능 최적화
|
||||||
|
|
@ -1769,9 +1769,9 @@ const derivedValue = useMemo(() => data.map(x => x.value), [data]);
|
||||||
|
|
||||||
| 파일 | 역할 |
|
| 파일 | 역할 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `components/unified/UnifiedInput.tsx` | text, number 입력 |
|
| `components/v2/V2Input.tsx` | text, number 입력 |
|
||||||
| `components/unified/UnifiedSelect.tsx` | code, entity 선택 |
|
| `components/v2/V2Select.tsx` | code, entity 선택 |
|
||||||
| `components/unified/UnifiedDate.tsx` | date, datetime 선택 |
|
| `components/v2/V2Date.tsx` | date, datetime 선택 |
|
||||||
| `lib/registry/components/v2-*/` | V2 컴포넌트 폴더 |
|
| `lib/registry/components/v2-*/` | V2 컴포넌트 폴더 |
|
||||||
| `lib/api/entityJoin.ts` | 엔티티 조인 API |
|
| `lib/api/entityJoin.ts` | 엔티티 조인 API |
|
||||||
| `hooks/useFormCompatibility.ts` | 폼 호환성 브릿지 |
|
| `hooks/useFormCompatibility.ts` | 폼 호환성 브릿지 |
|
||||||
|
|
@ -1783,6 +1783,6 @@ const derivedValue = useMemo(() => data.map(x => x.value), [data]);
|
||||||
|
|
||||||
| 컴포넌트 | 경로 | 참고 사항 |
|
| 컴포넌트 | 경로 | 참고 사항 |
|
||||||
|----------|------|-----------|
|
|----------|------|-----------|
|
||||||
| `v2-unified-repeater` | `lib/registry/components/v2-unified-repeater/` | **표준 참조 컴포넌트** |
|
| `v2-repeater` | `lib/registry/components/v2-repeater/` | **표준 참조 컴포넌트** |
|
||||||
| `v2-table-list` | `lib/registry/components/v2-table-list/` | 조회 컴포넌트 참조 |
|
| `v2-table-list` | `lib/registry/components/v2-table-list/` | 조회 컴포넌트 참조 |
|
||||||
| `v2-table-search-widget` | `lib/registry/components/v2-table-search-widget/` | 검색 필터 참조 |
|
| `v2-table-search-widget` | `lib/registry/components/v2-table-search-widget/` | 검색 필터 참조 |
|
||||||
|
|
|
||||||
20
PLAN.MD
20
PLAN.MD
|
|
@ -1,12 +1,12 @@
|
||||||
# 프로젝트: V2/Unified 컴포넌트 설정 스키마 정비
|
# 프로젝트: V2/V2 컴포넌트 설정 스키마 정비
|
||||||
|
|
||||||
## 개요
|
## 개요
|
||||||
레거시 컴포넌트를 제거하고, V2/Unified 컴포넌트 전용 Zod 스키마와 기본값 레지스트리를 한 곳에서 관리한다.
|
레거시 컴포넌트를 제거하고, V2/V2 컴포넌트 전용 Zod 스키마와 기본값 레지스트리를 한 곳에서 관리한다.
|
||||||
|
|
||||||
## 핵심 기능
|
## 핵심 기능
|
||||||
1. [x] 레거시 컴포넌트 스키마 제거
|
1. [x] 레거시 컴포넌트 스키마 제거
|
||||||
2. [x] V2 컴포넌트 overrides 스키마 정의 (16개)
|
2. [x] V2 컴포넌트 overrides 스키마 정의 (16개)
|
||||||
3. [x] Unified 컴포넌트 overrides 스키마 정의 (9개)
|
3. [x] V2 컴포넌트 overrides 스키마 정의 (9개)
|
||||||
4. [x] componentConfig.ts 한 파일에서 통합 관리
|
4. [x] componentConfig.ts 한 파일에서 통합 관리
|
||||||
|
|
||||||
## 정의된 V2 컴포넌트 (18개)
|
## 정의된 V2 컴포넌트 (18개)
|
||||||
|
|
@ -16,17 +16,17 @@
|
||||||
- v2-numbering-rule, v2-category-manager, v2-pivot-grid
|
- v2-numbering-rule, v2-category-manager, v2-pivot-grid
|
||||||
- v2-location-swap-selector, v2-aggregation-widget
|
- v2-location-swap-selector, v2-aggregation-widget
|
||||||
- v2-card-display, v2-table-search-widget, v2-tabs-widget
|
- v2-card-display, v2-table-search-widget, v2-tabs-widget
|
||||||
- v2-unified-repeater
|
- v2-v2-repeater
|
||||||
|
|
||||||
## 정의된 Unified 컴포넌트 (9개)
|
## 정의된 V2 컴포넌트 (9개)
|
||||||
- unified-input, unified-select, unified-date
|
- v2-input, v2-select, v2-date
|
||||||
- unified-list, unified-layout, unified-group
|
- v2-list, v2-layout, v2-group
|
||||||
- unified-media, unified-biz, unified-hierarchy
|
- v2-media, v2-biz, v2-hierarchy
|
||||||
|
|
||||||
## 테스트 계획
|
## 테스트 계획
|
||||||
### 1단계: 기본 기능
|
### 1단계: 기본 기능
|
||||||
- [x] V2 레이아웃 저장 시 컴포넌트별 overrides 스키마 검증 통과
|
- [x] V2 레이아웃 저장 시 컴포넌트별 overrides 스키마 검증 통과
|
||||||
- [x] Unified 컴포넌트 기본값과 스키마가 매칭됨
|
- [x] V2 컴포넌트 기본값과 스키마가 매칭됨
|
||||||
|
|
||||||
### 2단계: 에러 케이스
|
### 2단계: 에러 케이스
|
||||||
- [x] 잘못된 overrides 입력 시 Zod 검증 실패 처리 (safeParse + console.warn + graceful fallback)
|
- [x] 잘못된 overrides 입력 시 Zod 검증 실패 처리 (safeParse + console.warn + graceful fallback)
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
## 진행 상태
|
## 진행 상태
|
||||||
- [x] 레거시 컴포넌트 제거 완료
|
- [x] 레거시 컴포넌트 제거 완료
|
||||||
- [x] V2/Unified 스키마 정의 완료
|
- [x] V2/V2 스키마 정의 완료
|
||||||
- [x] 한 파일 통합 관리 완료
|
- [x] 한 파일 통합 관리 완료
|
||||||
# 프로젝트: 화면 복제 기능 개선 (DB 구조 개편 후)
|
# 프로젝트: 화면 복제 기능 개선 (DB 구조 개편 후)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ app.use("/api/table-categories", tableCategoryValueRoutes); // 카테고리 값
|
||||||
app.use("/api/code-merge", codeMergeRoutes); // 코드 병합
|
app.use("/api/code-merge", codeMergeRoutes); // 코드 병합
|
||||||
app.use("/api/numbering-rules", numberingRuleRoutes); // 채번 규칙 관리
|
app.use("/api/numbering-rules", numberingRuleRoutes); // 채번 규칙 관리
|
||||||
app.use("/api/entity-search", entitySearchRoutes); // 엔티티 검색
|
app.use("/api/entity-search", entitySearchRoutes); // 엔티티 검색
|
||||||
app.use("/api/entity", entityOptionsRouter); // 엔티티 옵션 (UnifiedSelect용)
|
app.use("/api/entity", entityOptionsRouter); // 엔티티 옵션 (V2Select용)
|
||||||
app.use("/api/driver", driverRoutes); // 공차중계 운전자 관리
|
app.use("/api/driver", driverRoutes); // 공차중계 운전자 관리
|
||||||
app.use("/api/tax-invoice", taxInvoiceRoutes); // 세금계산서 관리
|
app.use("/api/tax-invoice", taxInvoiceRoutes); // 세금계산서 관리
|
||||||
app.use("/api/cascading-relations", cascadingRelationRoutes); // 연쇄 드롭다운 관계 관리
|
app.use("/api/cascading-relations", cascadingRelationRoutes); // 연쇄 드롭다운 관계 관리
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,7 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||||
// 검색 조건 처리
|
// 검색 조건 처리
|
||||||
if (search && typeof search === "string" && search.trim()) {
|
if (search && typeof search === "string" && search.trim()) {
|
||||||
// 통합 검색
|
// 통합 검색
|
||||||
searchType = "unified";
|
searchType = "v2";
|
||||||
const searchTerm = search.trim();
|
const searchTerm = search.trim();
|
||||||
|
|
||||||
whereConditions.push(`(
|
whereConditions.push(`(
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ export async function getDistinctColumnValues(req: AuthenticatedRequest, res: Re
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 엔티티 옵션 조회 API (UnifiedSelect용)
|
* 엔티티 옵션 조회 API (V2Select용)
|
||||||
* GET /api/entity/:tableName/options
|
* GET /api/entity/:tableName/options
|
||||||
*
|
*
|
||||||
* Query Params:
|
* Query Params:
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ router.get("/:tableName", authenticateToken, searchEntity);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
||||||
// 엔티티 옵션 라우터 (UnifiedSelect용)
|
// 엔티티 옵션 라우터 (V2Select용)
|
||||||
export const entityOptionsRouter = Router();
|
export const entityOptionsRouter = Router();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import {
|
||||||
isValidWebType,
|
isValidWebType,
|
||||||
WEB_TYPE_TO_POSTGRES_CONVERTER,
|
WEB_TYPE_TO_POSTGRES_CONVERTER,
|
||||||
WEB_TYPE_VALIDATION_PATTERNS,
|
WEB_TYPE_VALIDATION_PATTERNS,
|
||||||
} from "../types/unified-web-types";
|
} from "../types/v2-web-types";
|
||||||
import { DataflowControlService } from "./dataflowControlService";
|
import { DataflowControlService } from "./dataflowControlService";
|
||||||
|
|
||||||
// 테이블 컬럼 정보
|
// 테이블 컬럼 정보
|
||||||
|
|
|
||||||
|
|
@ -987,7 +987,7 @@ class NumberingRuleService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 카테고리 매핑에서 해당 값에 대한 형식 찾기
|
// 카테고리 매핑에서 해당 값에 대한 형식 찾기
|
||||||
// selectedValue는 valueCode일 수 있음 (UnifiedSelect에서 valueCode를 value로 사용)
|
// selectedValue는 valueCode일 수 있음 (V2Select에서 valueCode를 value로 사용)
|
||||||
const selectedValueStr = String(selectedValue);
|
const selectedValueStr = String(selectedValue);
|
||||||
const mapping = categoryMappings.find(
|
const mapping = categoryMappings.find(
|
||||||
(m: any) => {
|
(m: any) => {
|
||||||
|
|
|
||||||
|
|
@ -1406,7 +1406,7 @@ export class ScreenManagementService {
|
||||||
*/
|
*/
|
||||||
private inferWebType(dataType: string): WebType {
|
private inferWebType(dataType: string): WebType {
|
||||||
// 통합 타입 매핑에서 import
|
// 통합 타입 매핑에서 import
|
||||||
const { DB_TYPE_TO_WEB_TYPE } = require("../types/unified-web-types");
|
const { DB_TYPE_TO_WEB_TYPE } = require("../types/v2-web-types");
|
||||||
|
|
||||||
const lowerType = dataType.toLowerCase();
|
const lowerType = dataType.toLowerCase();
|
||||||
|
|
||||||
|
|
@ -1741,15 +1741,15 @@ export class ScreenManagementService {
|
||||||
? inputTypeMap.get(`${tableName}.${columnName}`)
|
? inputTypeMap.get(`${tableName}.${columnName}`)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
// 🆕 Unified 컴포넌트는 덮어쓰지 않음 (새로운 컴포넌트 시스템 보호)
|
// 🆕 V2 컴포넌트는 덮어쓰지 않음 (새로운 컴포넌트 시스템 보호)
|
||||||
const savedComponentType = properties?.componentType;
|
const savedComponentType = properties?.componentType;
|
||||||
const isUnifiedComponent = savedComponentType?.startsWith("unified-");
|
const isV2Component = savedComponentType?.startsWith("v2-");
|
||||||
|
|
||||||
const component = {
|
const component = {
|
||||||
id: layout.component_id,
|
id: layout.component_id,
|
||||||
// 🔥 최신 componentType이 있으면 type 덮어쓰기 (단, Unified 컴포넌트는 제외)
|
// 🔥 최신 componentType이 있으면 type 덮어쓰기 (단, V2 컴포넌트는 제외)
|
||||||
type: isUnifiedComponent
|
type: isV2Component
|
||||||
? layout.component_type as any // Unified는 저장된 값 유지
|
? layout.component_type as any // V2는 저장된 값 유지
|
||||||
: (latestTypeInfo?.componentType || layout.component_type as any),
|
: (latestTypeInfo?.componentType || layout.component_type as any),
|
||||||
position: {
|
position: {
|
||||||
x: layout.position_x,
|
x: layout.position_x,
|
||||||
|
|
@ -1759,8 +1759,8 @@ export class ScreenManagementService {
|
||||||
size: { width: layout.width, height: layout.height },
|
size: { width: layout.width, height: layout.height },
|
||||||
parentId: layout.parent_id,
|
parentId: layout.parent_id,
|
||||||
...properties,
|
...properties,
|
||||||
// 🔥 최신 inputType이 있으면 widgetType, componentType 덮어쓰기 (단, Unified 컴포넌트는 제외)
|
// 🔥 최신 inputType이 있으면 widgetType, componentType 덮어쓰기 (단, V2 컴포넌트는 제외)
|
||||||
...(!isUnifiedComponent && latestTypeInfo && {
|
...(!isV2Component && latestTypeInfo && {
|
||||||
widgetType: latestTypeInfo.inputType,
|
widgetType: latestTypeInfo.inputType,
|
||||||
inputType: latestTypeInfo.inputType,
|
inputType: latestTypeInfo.inputType,
|
||||||
componentType: latestTypeInfo.componentType,
|
componentType: latestTypeInfo.componentType,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import {
|
||||||
EntityJoinResponse,
|
EntityJoinResponse,
|
||||||
EntityJoinConfig,
|
EntityJoinConfig,
|
||||||
} from "../types/tableManagement";
|
} from "../types/tableManagement";
|
||||||
import { WebType } from "../types/unified-web-types";
|
import { WebType } from "../types/v2-web-types";
|
||||||
import { entityJoinService } from "./entityJoinService";
|
import { entityJoinService } from "./entityJoinService";
|
||||||
import { referenceCacheService } from "./referenceCacheService";
|
import { referenceCacheService } from "./referenceCacheService";
|
||||||
|
|
||||||
|
|
@ -4301,7 +4301,7 @@ export class TableManagementService {
|
||||||
*/
|
*/
|
||||||
private inferWebType(dataType: string): WebType {
|
private inferWebType(dataType: string): WebType {
|
||||||
// 통합 타입 매핑에서 import
|
// 통합 타입 매핑에서 import
|
||||||
const { DB_TYPE_TO_WEB_TYPE } = require("../types/unified-web-types");
|
const { DB_TYPE_TO_WEB_TYPE } = require("../types/v2-web-types");
|
||||||
|
|
||||||
const lowerType = dataType.toLowerCase();
|
const lowerType = dataType.toLowerCase();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ export type ComponentType = "container" | "row" | "column" | "widget" | "group";
|
||||||
|
|
||||||
// 웹 타입 정의
|
// 웹 타입 정의
|
||||||
// WebType은 통합 타입에서 import (중복 정의 제거)
|
// WebType은 통합 타입에서 import (중복 정의 제거)
|
||||||
import { WebType } from "./unified-web-types";
|
import { WebType } from "./v2-web-types";
|
||||||
export { WebType };
|
export { WebType };
|
||||||
|
|
||||||
// 위치 정보
|
// 위치 정보
|
||||||
|
|
|
||||||
|
|
@ -264,7 +264,7 @@ export const WEB_TYPE_VALIDATION_PATTERNS: Record<WebType, RegExp | null> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 업데이트된 웹 타입 옵션 (기존 WEB_TYPE_OPTIONS 대체)
|
// 업데이트된 웹 타입 옵션 (기존 WEB_TYPE_OPTIONS 대체)
|
||||||
export const UNIFIED_WEB_TYPE_OPTIONS = [
|
export const V2_WEB_TYPE_OPTIONS = [
|
||||||
{
|
{
|
||||||
value: "text",
|
value: "text",
|
||||||
label: "text",
|
label: "text",
|
||||||
|
|
@ -134,7 +134,7 @@ export const componentDefaults: Record<string, any> = {
|
||||||
"flow-widget": { type: "flow-widget", webType: "text", displayMode: "horizontal", allowDataMove: false, showStepCount: true },
|
"flow-widget": { type: "flow-widget", webType: "text", displayMode: "horizontal", allowDataMove: false, showStepCount: true },
|
||||||
"entity-search-input": { type: "entity-search-input", webType: "entity" },
|
"entity-search-input": { type: "entity-search-input", webType: "entity" },
|
||||||
"autocomplete-search-input": { type: "autocomplete-search-input", webType: "entity" },
|
"autocomplete-search-input": { type: "autocomplete-search-input", webType: "entity" },
|
||||||
"unified-list": { type: "unified-list", webType: "table" },
|
"v2-list": { type: "v2-list", webType: "table" },
|
||||||
"modal-repeater-table": { type: "modal-repeater-table", webType: "table", columns: [], multiSelect: true },
|
"modal-repeater-table": { type: "modal-repeater-table", webType: "table", columns: [], multiSelect: true },
|
||||||
"category-manager": { type: "category-manager", webType: "custom" },
|
"category-manager": { type: "category-manager", webType: "custom" },
|
||||||
"numbering-rule": { type: "numbering-rule", webType: "text" },
|
"numbering-rule": { type: "numbering-rule", webType: "text" },
|
||||||
|
|
@ -159,10 +159,10 @@ export const componentDefaults: Record<string, any> = {
|
||||||
"repeat-screen-modal": { type: "repeat-screen-modal", webType: "custom" },
|
"repeat-screen-modal": { type: "repeat-screen-modal", webType: "custom" },
|
||||||
"related-data-buttons": { type: "related-data-buttons", webType: "custom" },
|
"related-data-buttons": { type: "related-data-buttons", webType: "custom" },
|
||||||
"split-panel-layout2": { type: "split-panel-layout2", webType: "custom" },
|
"split-panel-layout2": { type: "split-panel-layout2", webType: "custom" },
|
||||||
"unified-input": { type: "unified-input", webType: "text" },
|
"v2-input": { type: "v2-input", webType: "text" },
|
||||||
"unified-select": { type: "unified-select", webType: "select" },
|
"v2-select": { type: "v2-select", webType: "select" },
|
||||||
"unified-date": { type: "unified-date", webType: "date" },
|
"v2-date": { type: "v2-date", webType: "date" },
|
||||||
"unified-repeater": { type: "unified-repeater", webType: "custom" },
|
"v2-repeater": { type: "v2-repeater", webType: "custom" },
|
||||||
"v2-repeat-container": { type: "v2-repeat-container", webType: "custom" },
|
"v2-repeat-container": { type: "v2-repeat-container", webType: "custom" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -527,7 +527,7 @@ flowchart TB
|
||||||
|
|
||||||
subgraph Usage["사용처"]
|
subgraph Usage["사용처"]
|
||||||
U1[NumberingRuleDesigner.tsx]
|
U1[NumberingRuleDesigner.tsx]
|
||||||
U2[UnifiedSelect.tsx]
|
U2[V2Select.tsx]
|
||||||
U3[screenManagementService.ts]
|
U3[screenManagementService.ts]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -185,7 +185,7 @@ POST /api/screen-management/screens/:screenId/layout-v2
|
||||||
| `@/lib/registry/components/flow-widget` | 플로우 위젯 |
|
| `@/lib/registry/components/flow-widget` | 플로우 위젯 |
|
||||||
| `@/lib/registry/components/category-management` | 카테고리 관리 |
|
| `@/lib/registry/components/category-management` | 카테고리 관리 |
|
||||||
| `@/lib/registry/components/pivot-table` | 피벗 테이블 |
|
| `@/lib/registry/components/pivot-table` | 피벗 테이블 |
|
||||||
| `@/lib/registry/components/unified-grid` | 통합 그리드 |
|
| `@/lib/registry/components/v2-grid` | 통합 그리드 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -192,7 +192,7 @@ async function verifyRenderingEquality(layoutId: number) {
|
||||||
| 6 | select-basic | 129 | 100% | 낮음 |
|
| 6 | select-basic | 129 | 100% | 낮음 |
|
||||||
| 7 | split-panel-layout | 129 | 100% | 높음 |
|
| 7 | split-panel-layout | 129 | 100% | 높음 |
|
||||||
| 8 | date-input | 116 | 100% | 낮음 |
|
| 8 | date-input | 116 | 100% | 낮음 |
|
||||||
| 9 | unified-list | 97 | 100% | 높음 |
|
| 9 | v2-list | 97 | 100% | 높음 |
|
||||||
| 10 | number-input | 87 | 100% | 낮음 |
|
| 10 | number-input | 87 | 100% | 낮음 |
|
||||||
|
|
||||||
### 4.2 발견된 문제점
|
### 4.2 발견된 문제점
|
||||||
|
|
@ -433,7 +433,7 @@ DROP TABLE screen_layouts_v2;
|
||||||
- [ ] select-basic
|
- [ ] select-basic
|
||||||
- [ ] split-panel-layout
|
- [ ] split-panel-layout
|
||||||
- [ ] date-input
|
- [ ] date-input
|
||||||
- [ ] unified-list
|
- [ ] v2-list
|
||||||
- [ ] number-input
|
- [ ] number-input
|
||||||
|
|
||||||
### Step 3: 마이그레이션 스크립트
|
### Step 3: 마이그레이션 스크립트
|
||||||
|
|
@ -0,0 +1,192 @@
|
||||||
|
# V2 Components 구현 완료 보고서
|
||||||
|
|
||||||
|
## 구현 일시
|
||||||
|
|
||||||
|
2024-12-19
|
||||||
|
|
||||||
|
## 구현된 컴포넌트 목록 (10개)
|
||||||
|
|
||||||
|
### Phase 1: 핵심 입력 컴포넌트
|
||||||
|
|
||||||
|
| 컴포넌트 | 파일 | 모드/타입 | 설명 |
|
||||||
|
| :---------------- | :------------------ | :-------------------------------------------- | :---------------------- |
|
||||||
|
| **V2Input** | `V2Input.tsx` | text, number, password, slider, color, button | 통합 입력 컴포넌트 |
|
||||||
|
| **V2Select** | `V2Select.tsx` | dropdown, radio, check, tag, toggle, swap | 통합 선택 컴포넌트 |
|
||||||
|
| **V2Date** | `V2Date.tsx` | date, time, datetime + range | 통합 날짜/시간 컴포넌트 |
|
||||||
|
|
||||||
|
### Phase 2: 레이아웃 및 그룹 컴포넌트
|
||||||
|
|
||||||
|
| 컴포넌트 | 파일 | 모드/타입 | 설명 |
|
||||||
|
| :---------------- | :------------------ | :-------------------------------------------------------- | :--------------------- |
|
||||||
|
| **V2List** | `V2List.tsx` | table, card, kanban, list | 통합 리스트 컴포넌트 |
|
||||||
|
| **V2Layout** | `V2Layout.tsx` | grid, split, flex, divider, screen-embed | 통합 레이아웃 컴포넌트 |
|
||||||
|
| **V2Group** | `V2Group.tsx` | tabs, accordion, section, card-section, modal, form-modal | 통합 그룹 컴포넌트 |
|
||||||
|
|
||||||
|
### Phase 3: 미디어 및 비즈니스 컴포넌트
|
||||||
|
|
||||||
|
| 컴포넌트 | 파일 | 모드/타입 | 설명 |
|
||||||
|
| :------------------- | :--------------------- | :------------------------------------------------------------- | :---------------------- |
|
||||||
|
| **V2Media** | `V2Media.tsx` | file, image, video, audio | 통합 미디어 컴포넌트 |
|
||||||
|
| **V2Biz** | `V2Biz.tsx` | flow, rack, map, numbering, category, mapping, related-buttons | 통합 비즈니스 컴포넌트 |
|
||||||
|
| **V2Hierarchy** | `V2Hierarchy.tsx` | tree, org, bom, cascading | 통합 계층 구조 컴포넌트 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 공통 인프라
|
||||||
|
|
||||||
|
### 설정 패널
|
||||||
|
|
||||||
|
- **DynamicConfigPanel**: JSON Schema 기반 동적 설정 UI 생성
|
||||||
|
|
||||||
|
### 렌더러
|
||||||
|
|
||||||
|
- **V2ComponentRenderer**: v2Type에 따른 동적 컴포넌트 렌더링
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 파일 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
frontend/components/v2/
|
||||||
|
├── index.ts # 모듈 인덱스
|
||||||
|
├── V2ComponentRenderer.tsx # 동적 렌더러
|
||||||
|
├── DynamicConfigPanel.tsx # JSON Schema 설정 패널
|
||||||
|
├── V2Input.tsx # 통합 입력
|
||||||
|
├── V2Select.tsx # 통합 선택
|
||||||
|
├── V2Date.tsx # 통합 날짜
|
||||||
|
├── V2List.tsx # 통합 리스트
|
||||||
|
├── V2Layout.tsx # 통합 레이아웃
|
||||||
|
├── V2Group.tsx # 통합 그룹
|
||||||
|
├── V2Media.tsx # 통합 미디어
|
||||||
|
├── V2Biz.tsx # 통합 비즈니스
|
||||||
|
└── V2Hierarchy.tsx # 통합 계층
|
||||||
|
|
||||||
|
frontend/types/
|
||||||
|
└── v2-components.ts # 타입 정의
|
||||||
|
|
||||||
|
db/migrations/
|
||||||
|
└── v2_component_schema.sql # DB 스키마 (미실행)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 사용 예시
|
||||||
|
|
||||||
|
### 기본 사용법
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import {
|
||||||
|
V2Input,
|
||||||
|
V2Select,
|
||||||
|
V2Date,
|
||||||
|
V2List,
|
||||||
|
V2ComponentRenderer
|
||||||
|
} from "@/components/v2";
|
||||||
|
|
||||||
|
// V2Input 사용
|
||||||
|
<V2Input
|
||||||
|
id="name"
|
||||||
|
label="이름"
|
||||||
|
required
|
||||||
|
config={{ type: "text", placeholder: "이름을 입력하세요" }}
|
||||||
|
value={name}
|
||||||
|
onChange={setName}
|
||||||
|
/>
|
||||||
|
|
||||||
|
// V2Select 사용
|
||||||
|
<V2Select
|
||||||
|
id="status"
|
||||||
|
label="상태"
|
||||||
|
config={{
|
||||||
|
mode: "dropdown",
|
||||||
|
source: "code",
|
||||||
|
codeGroup: "ORDER_STATUS",
|
||||||
|
searchable: true
|
||||||
|
}}
|
||||||
|
value={status}
|
||||||
|
onChange={setStatus}
|
||||||
|
/>
|
||||||
|
|
||||||
|
// V2Date 사용
|
||||||
|
<V2Date
|
||||||
|
id="orderDate"
|
||||||
|
label="주문일"
|
||||||
|
config={{ type: "date", format: "YYYY-MM-DD" }}
|
||||||
|
value={orderDate}
|
||||||
|
onChange={setOrderDate}
|
||||||
|
/>
|
||||||
|
|
||||||
|
// V2List 사용
|
||||||
|
<V2List
|
||||||
|
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 { V2ComponentRenderer } from "@/components/v2";
|
||||||
|
|
||||||
|
// v2Type에 따라 자동으로 적절한 컴포넌트 렌더링
|
||||||
|
<V2ComponentRenderer
|
||||||
|
props={{
|
||||||
|
v2Type: "V2Input",
|
||||||
|
id: "dynamicField",
|
||||||
|
label: "동적 필드",
|
||||||
|
config: { type: "text" },
|
||||||
|
value: fieldValue,
|
||||||
|
onChange: setFieldValue,
|
||||||
|
}}
|
||||||
|
/>;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 주의사항
|
||||||
|
|
||||||
|
### 기존 컴포넌트와의 공존
|
||||||
|
|
||||||
|
1. **기존 컴포넌트는 그대로 유지**: 모든 레거시 컴포넌트는 정상 동작
|
||||||
|
2. **신규 화면에서만 V2 컴포넌트 사용**: 기존 화면에 영향 없음
|
||||||
|
3. **마이그레이션 없음**: 자동 마이그레이션 진행하지 않음
|
||||||
|
|
||||||
|
### 데이터베이스 마이그레이션
|
||||||
|
|
||||||
|
`db/migrations/v2_component_schema.sql` 파일은 아직 실행되지 않았습니다.
|
||||||
|
필요시 수동으로 실행해야 합니다:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
psql -h localhost -U postgres -d plm_db -f db/migrations/v2_component_schema.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 다음 단계 (선택)
|
||||||
|
|
||||||
|
1. **화면 관리 에디터 통합**: V2 컴포넌트를 화면 에디터의 컴포넌트 팔레트에 추가
|
||||||
|
2. **기존 비즈니스 컴포넌트 연동**: V2Biz의 플레이스홀더를 실제 구현으로 교체
|
||||||
|
3. **테스트 페이지 작성**: 모든 V2 컴포넌트 데모 페이지
|
||||||
|
4. **문서화**: 각 컴포넌트별 상세 사용 가이드
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 관련 문서
|
||||||
|
|
||||||
|
- `PLAN_RENEWAL.md`: 리뉴얼 계획서
|
||||||
|
- `docs/phase0-component-usage-analysis.md`: 컴포넌트 사용 현황 분석
|
||||||
|
- `docs/phase0-migration-strategy.md`: 마이그레이션 전략 (참고용)
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
|
|
||||||
| 파일 | 참조 횟수 | 영향도 | 용도 |
|
| 파일 | 참조 횟수 | 영향도 | 용도 |
|
||||||
|------|----------|--------|------|
|
|------|----------|--------|------|
|
||||||
| `UnifiedRepeater.tsx` | 3회 | 🟢 낮음 | 타입 주석 |
|
| `V2Repeater.tsx` | 3회 | 🟢 낮음 | 타입 주석 |
|
||||||
| `ScreenDesigner.tsx` | 2회 | 🟢 낮음 | 타입 주석 |
|
| `ScreenDesigner.tsx` | 2회 | 🟢 낮음 | 타입 주석 |
|
||||||
| `ButtonConfigPanel.tsx` | 2회 | 🟢 낮음 | 타입 주석 |
|
| `ButtonConfigPanel.tsx` | 2회 | 🟢 낮음 | 타입 주석 |
|
||||||
| `ScreenRelationFlow.tsx` | 2회 | 🟢 낮음 | 타입 주석 |
|
| `ScreenRelationFlow.tsx` | 2회 | 🟢 낮음 | 타입 주석 |
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## 1. 개요
|
## 1. 개요
|
||||||
|
|
||||||
현재 **68개 이상**으로 파편화된 화면 관리 컴포넌트들을 **9개의 핵심 통합 컴포넌트(Unified Components)**로 재편합니다.
|
현재 **68개 이상**으로 파편화된 화면 관리 컴포넌트들을 **9개의 핵심 통합 컴포넌트(V2 Components)**로 재편합니다.
|
||||||
각 컴포넌트는 **속성(Config)** 설정을 통해 다양한 형태(View Mode)와 기능(Behavior)을 수행하도록 설계되어, 유지보수성과 확장성을 극대화합니다.
|
각 컴포넌트는 **속성(Config)** 설정을 통해 다양한 형태(View Mode)와 기능(Behavior)을 수행하도록 설계되어, 유지보수성과 확장성을 극대화합니다.
|
||||||
|
|
||||||
### 현재 컴포넌트 현황 (AS-IS)
|
### 현재 컴포넌트 현황 (AS-IS)
|
||||||
|
|
@ -24,11 +24,11 @@
|
||||||
|
|
||||||
| 통합 컴포넌트 (TO-BE) | 포함되는 기존 컴포넌트 (AS-IS) | 핵심 속성 (Configuration) |
|
| 통합 컴포넌트 (TO-BE) | 포함되는 기존 컴포넌트 (AS-IS) | 핵심 속성 (Configuration) |
|
||||||
| :-------------------- | :------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------- |
|
| :-------------------- | :------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **1. Unified Select** | Select, Radio, Checkbox, Boolean, Code, Entity, Combobox, Toggle | **`mode`**: "dropdown" / "radio" / "check" / "tag"<br>**`source`**: "static" / "code" / "db" / "api"<br>**`dependency`**: { parentField: "..." } |
|
| **1. V2 Select** | Select, Radio, Checkbox, Boolean, Code, Entity, Combobox, Toggle | **`mode`**: "dropdown" / "radio" / "check" / "tag"<br>**`source`**: "static" / "code" / "db" / "api"<br>**`dependency`**: { parentField: "..." } |
|
||||||
| **2. Unified Input** | Text, Number, Email, Tel, Password, Color, Search, Integer, Decimal | **`type`**: "text" / "number" / "password"<br>**`format`**: "email", "currency", "biz_no"<br>**`mask`**: "000-0000-0000" |
|
| **2. V2 Input** | Text, Number, Email, Tel, Password, Color, Search, Integer, Decimal | **`type`**: "text" / "number" / "password"<br>**`format`**: "email", "currency", "biz_no"<br>**`mask`**: "000-0000-0000" |
|
||||||
| **3. Unified Date** | Date, Time, DateTime, DateRange, Month, Year | **`type`**: "date" / "time" / "datetime"<br>**`range`**: true/false |
|
| **3. V2 Date** | Date, Time, DateTime, DateRange, Month, Year | **`type`**: "date" / "time" / "datetime"<br>**`range`**: true/false |
|
||||||
| **4. Unified Text** | Textarea, RichEditor, Markdown, HTML | **`mode`**: "simple" / "rich" / "code"<br>**`rows`**: number |
|
| **4. V2 Text** | Textarea, RichEditor, Markdown, HTML | **`mode`**: "simple" / "rich" / "code"<br>**`rows`**: number |
|
||||||
| **5. Unified Media** | File, Image, Video, Audio, Attachment | **`type`**: "file" / "image"<br>**`multiple`**: true/false<br>**`preview`**: true/false |
|
| **5. V2 Media** | File, Image, Video, Audio, Attachment | **`type`**: "file" / "image"<br>**`multiple`**: true/false<br>**`preview`**: true/false |
|
||||||
|
|
||||||
### B. 구조/데이터 위젯 (Structure & Data Widgets) - 4종
|
### B. 구조/데이터 위젯 (Structure & Data Widgets) - 4종
|
||||||
|
|
||||||
|
|
@ -36,10 +36,10 @@
|
||||||
|
|
||||||
| 통합 컴포넌트 (TO-BE) | 포함되는 기존 컴포넌트 (AS-IS) | 핵심 속성 (Configuration) | 활용 예시 |
|
| 통합 컴포넌트 (TO-BE) | 포함되는 기존 컴포넌트 (AS-IS) | 핵심 속성 (Configuration) | 활용 예시 |
|
||||||
| :-------------------- | :-------------------------------------------------- | :------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------- |
|
| :-------------------- | :-------------------------------------------------- | :------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **6. Unified List** | **Table, Card List, Repeater, DataGrid, List View** | **`viewMode`**: "table" / "card" / "kanban"<br>**`editable`**: true/false | - `viewMode='table'`: 엑셀형 리스트<br>- `viewMode='card'`: **카드 디스플레이**<br>- `editable=true`: **반복 필드 그룹** |
|
| **6. V2 List** | **Table, Card List, Repeater, DataGrid, List View** | **`viewMode`**: "table" / "card" / "kanban"<br>**`editable`**: true/false | - `viewMode='table'`: 엑셀형 리스트<br>- `viewMode='card'`: **카드 디스플레이**<br>- `editable=true`: **반복 필드 그룹** |
|
||||||
| **7. Unified Layout** | **Row, Col, Split Panel, Grid, Spacer** | **`type`**: "grid" / "split" / "flex"<br>**`columns`**: number | - `type='split'`: **화면 분할 패널**<br>- `type='grid'`: 격자 레이아웃 |
|
| **7. V2 Layout** | **Row, Col, Split Panel, Grid, Spacer** | **`type`**: "grid" / "split" / "flex"<br>**`columns`**: number | - `type='split'`: **화면 분할 패널**<br>- `type='grid'`: 격자 레이아웃 |
|
||||||
| **8. Unified Group** | Tab, Accordion, FieldSet, Modal, Section | **`type`**: "tab" / "accordion" / "modal" | - 탭이나 아코디언으로 내용 그룹화 |
|
| **8. V2 Group** | Tab, Accordion, FieldSet, Modal, Section | **`type`**: "tab" / "accordion" / "modal" | - 탭이나 아코디언으로 내용 그룹화 |
|
||||||
| **9. Unified Biz** | **Rack Structure**, Calendar, Gantt | **`type`**: "rack" / "calendar" / "gantt" | - `type='rack'`: **랙 구조 설정**<br>- 특수 비즈니스 로직 플러그인 탑재 |
|
| **9. V2 Biz** | **Rack Structure**, Calendar, Gantt | **`type`**: "rack" / "calendar" / "gantt" | - `type='rack'`: **랙 구조 설정**<br>- 특수 비즈니스 로직 플러그인 탑재 |
|
||||||
|
|
||||||
### C. Config Panel 통합 전략 (핵심)
|
### C. Config Panel 통합 전략 (핵심)
|
||||||
|
|
||||||
|
|
@ -60,16 +60,16 @@
|
||||||
### Case 1: "테이블을 카드 리스트로 변경"
|
### Case 1: "테이블을 카드 리스트로 변경"
|
||||||
|
|
||||||
- **AS-IS**: `DataTable` 컴포넌트를 삭제하고 `CardList` 컴포넌트를 새로 추가해야 함.
|
- **AS-IS**: `DataTable` 컴포넌트를 삭제하고 `CardList` 컴포넌트를 새로 추가해야 함.
|
||||||
- **TO-BE**: `UnifiedList`의 속성창에서 **[View Mode]**를 `Table` → `Card`로 변경하면 즉시 반영.
|
- **TO-BE**: `V2List`의 속성창에서 **[View Mode]**를 `Table` → `Card`로 변경하면 즉시 반영.
|
||||||
|
|
||||||
### Case 2: "단일 선택을 라디오 버튼으로 변경"
|
### Case 2: "단일 선택을 라디오 버튼으로 변경"
|
||||||
|
|
||||||
- **AS-IS**: `SelectWidget`을 삭제하고 `RadioWidget` 추가.
|
- **AS-IS**: `SelectWidget`을 삭제하고 `RadioWidget` 추가.
|
||||||
- **TO-BE**: `UnifiedSelect` 속성창에서 **[Display Mode]**를 `Dropdown` → `Radio`로 변경.
|
- **TO-BE**: `V2Select` 속성창에서 **[Display Mode]**를 `Dropdown` → `Radio`로 변경.
|
||||||
|
|
||||||
### Case 3: "입력 폼에 반복 필드(Repeater) 추가"
|
### Case 3: "입력 폼에 반복 필드(Repeater) 추가"
|
||||||
|
|
||||||
- **TO-BE**: `UnifiedList` 컴포넌트 배치 후 `editable: true`, `viewMode: "table"` 설정.
|
- **TO-BE**: `V2List` 컴포넌트 배치 후 `editable: true`, `viewMode: "table"` 설정.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
통합 작업 전 필수 분석 및 설계를 진행합니다.
|
통합 작업 전 필수 분석 및 설계를 진행합니다.
|
||||||
|
|
||||||
- [ ] 기존 컴포넌트 사용 현황 분석 (화면별 위젯 사용 빈도 조사)
|
- [ ] 기존 컴포넌트 사용 현황 분석 (화면별 위젯 사용 빈도 조사)
|
||||||
- [ ] 데이터 마이그레이션 전략 설계 (`widgetType` → `UnifiedWidget.type` 매핑 정의)
|
- [ ] 데이터 마이그레이션 전략 설계 (`widgetType` → `V2Widget.type` 매핑 정의)
|
||||||
- [ ] `sys_input_type` 테이블 JSON Schema 설계
|
- [ ] `sys_input_type` 테이블 JSON Schema 설계
|
||||||
- [ ] DynamicConfigPanel 프로토타입 설계
|
- [ ] DynamicConfigPanel 프로토타입 설계
|
||||||
|
|
||||||
|
|
@ -88,9 +88,9 @@
|
||||||
|
|
||||||
가장 중복이 많고 효과가 즉각적인 입력 필드부터 통합합니다.
|
가장 중복이 많고 효과가 즉각적인 입력 필드부터 통합합니다.
|
||||||
|
|
||||||
- [ ] **UnifiedInput 구현**: Text, Number, Email, Tel, Password 통합
|
- [ ] **V2Input 구현**: Text, Number, Email, Tel, Password 통합
|
||||||
- [ ] **UnifiedSelect 구현**: Select, Radio, Checkbox, Boolean 통합
|
- [ ] **V2Select 구현**: Select, Radio, Checkbox, Boolean 통합
|
||||||
- [ ] **UnifiedDate 구현**: Date, DateTime, Time 통합
|
- [ ] **V2Date 구현**: Date, DateTime, Time 통합
|
||||||
- [ ] 기존 위젯과 **병행 운영** (deprecated 마킹, 삭제하지 않음)
|
- [ ] 기존 위젯과 **병행 운영** (deprecated 마킹, 삭제하지 않음)
|
||||||
|
|
||||||
### Phase 2: Config Panel 통합 (2주)
|
### Phase 2: Config Panel 통합 (2주)
|
||||||
|
|
@ -105,15 +105,15 @@
|
||||||
|
|
||||||
프로젝트의 데이터를 보여주는 핵심 뷰를 통합합니다.
|
프로젝트의 데이터를 보여주는 핵심 뷰를 통합합니다.
|
||||||
|
|
||||||
- [ ] **UnifiedList 구현**: Table, Card, Repeater 통합 렌더러 개발
|
- [ ] **V2List 구현**: Table, Card, Repeater 통합 렌더러 개발
|
||||||
- [ ] **UnifiedLayout 구현**: Split Panel, Grid, Flex 통합
|
- [ ] **V2Layout 구현**: Split Panel, Grid, Flex 통합
|
||||||
- [ ] **UnifiedGroup 구현**: Tab, Accordion, Modal 통합
|
- [ ] **V2Group 구현**: Tab, Accordion, Modal 통합
|
||||||
|
|
||||||
### Phase 4: 안정화 및 마이그레이션 (2주)
|
### Phase 4: 안정화 및 마이그레이션 (2주)
|
||||||
|
|
||||||
신규 컴포넌트 안정화 후 점진적 전환을 진행합니다.
|
신규 컴포넌트 안정화 후 점진적 전환을 진행합니다.
|
||||||
|
|
||||||
- [ ] 신규 화면은 Unified 컴포넌트만 사용하도록 가이드
|
- [ ] 신규 화면은 V2 컴포넌트만 사용하도록 가이드
|
||||||
- [ ] 기존 화면 데이터 마이그레이션 스크립트 개발
|
- [ ] 기존 화면 데이터 마이그레이션 스크립트 개발
|
||||||
- [ ] 마이그레이션 테스트 (스테이징 환경)
|
- [ ] 마이그레이션 테스트 (스테이징 환경)
|
||||||
- [ ] 문서화 및 개발 가이드 작성
|
- [ ] 문서화 및 개발 가이드 작성
|
||||||
|
|
@ -122,7 +122,7 @@
|
||||||
|
|
||||||
충분한 안정화 기간 후 레거시 컴포넌트 정리를 검토합니다.
|
충분한 안정화 기간 후 레거시 컴포넌트 정리를 검토합니다.
|
||||||
|
|
||||||
- [ ] 사용 현황 재분석 (Unified 전환율 확인)
|
- [ ] 사용 현황 재분석 (V2 전환율 확인)
|
||||||
- [ ] 미전환 화면 목록 정리
|
- [ ] 미전환 화면 목록 정리
|
||||||
- [ ] 레거시 컴포넌트 삭제 여부 결정 (별도 회의)
|
- [ ] 레거시 컴포넌트 삭제 여부 결정 (별도 회의)
|
||||||
|
|
||||||
|
|
@ -132,27 +132,27 @@
|
||||||
|
|
||||||
### 5.1 위젯 타입 매핑 테이블
|
### 5.1 위젯 타입 매핑 테이블
|
||||||
|
|
||||||
기존 `widgetType`을 신규 Unified 컴포넌트로 매핑합니다.
|
기존 `widgetType`을 신규 V2 컴포넌트로 매핑합니다.
|
||||||
|
|
||||||
| 기존 widgetType | 신규 컴포넌트 | 속성 설정 |
|
| 기존 widgetType | 신규 컴포넌트 | 속성 설정 |
|
||||||
| :-------------- | :------------ | :------------------------------ |
|
| :-------------- | :------------ | :------------------------------ |
|
||||||
| `text` | UnifiedInput | `type: "text"` |
|
| `text` | V2Input | `type: "text"` |
|
||||||
| `number` | UnifiedInput | `type: "number"` |
|
| `number` | V2Input | `type: "number"` |
|
||||||
| `email` | UnifiedInput | `type: "text", format: "email"` |
|
| `email` | V2Input | `type: "text", format: "email"` |
|
||||||
| `tel` | UnifiedInput | `type: "text", format: "tel"` |
|
| `tel` | V2Input | `type: "text", format: "tel"` |
|
||||||
| `select` | UnifiedSelect | `mode: "dropdown"` |
|
| `select` | V2Select | `mode: "dropdown"` |
|
||||||
| `radio` | UnifiedSelect | `mode: "radio"` |
|
| `radio` | V2Select | `mode: "radio"` |
|
||||||
| `checkbox` | UnifiedSelect | `mode: "check"` |
|
| `checkbox` | V2Select | `mode: "check"` |
|
||||||
| `date` | UnifiedDate | `type: "date"` |
|
| `date` | V2Date | `type: "date"` |
|
||||||
| `datetime` | UnifiedDate | `type: "datetime"` |
|
| `datetime` | V2Date | `type: "datetime"` |
|
||||||
| `textarea` | UnifiedText | `mode: "simple"` |
|
| `textarea` | V2Text | `mode: "simple"` |
|
||||||
| `file` | UnifiedMedia | `type: "file"` |
|
| `file` | V2Media | `type: "file"` |
|
||||||
| `image` | UnifiedMedia | `type: "image"` |
|
| `image` | V2Media | `type: "image"` |
|
||||||
|
|
||||||
### 5.2 마이그레이션 원칙
|
### 5.2 마이그레이션 원칙
|
||||||
|
|
||||||
1. **비파괴적 전환**: 기존 데이터 구조 유지, 신규 필드 추가 방식
|
1. **비파괴적 전환**: 기존 데이터 구조 유지, 신규 필드 추가 방식
|
||||||
2. **하위 호환성**: 기존 `widgetType` 필드는 유지, `unifiedType` 필드 추가
|
2. **하위 호환성**: 기존 `widgetType` 필드는 유지, `v2Type` 필드 추가
|
||||||
3. **점진적 전환**: 화면 수정 시점에 자동 또는 수동 전환
|
3. **점진적 전환**: 화면 수정 시점에 자동 또는 수동 전환
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -183,7 +183,7 @@
|
||||||
|
|
||||||
현재 `frontend/lib/registry/components/`에 등록된 모든 컴포넌트의 통합 가능 여부를 분석했습니다.
|
현재 `frontend/lib/registry/components/`에 등록된 모든 컴포넌트의 통합 가능 여부를 분석했습니다.
|
||||||
|
|
||||||
#### UnifiedInput으로 통합 (4개)
|
#### V2Input으로 통합 (4개)
|
||||||
|
|
||||||
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
||||||
| :------------- | :--------------- | :------------- |
|
| :------------- | :--------------- | :------------- |
|
||||||
|
|
@ -192,7 +192,7 @@
|
||||||
| slider-basic | `type: "slider"` | 속성 추가 필요 |
|
| slider-basic | `type: "slider"` | 속성 추가 필요 |
|
||||||
| button-primary | `type: "button"` | 별도 검토 |
|
| button-primary | `type: "button"` | 별도 검토 |
|
||||||
|
|
||||||
#### UnifiedSelect로 통합 (8개)
|
#### V2Select로 통합 (8개)
|
||||||
|
|
||||||
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
||||||
| :------------------------ | :----------------------------------- | :------------- |
|
| :------------------------ | :----------------------------------- | :------------- |
|
||||||
|
|
@ -205,19 +205,19 @@
|
||||||
| mail-recipient-selector | `mode: "multi", type: "email"` | 복합 컴포넌트 |
|
| mail-recipient-selector | `mode: "multi", type: "email"` | 복합 컴포넌트 |
|
||||||
| location-swap-selector | `mode: "swap"` | 특수 UI |
|
| location-swap-selector | `mode: "swap"` | 특수 UI |
|
||||||
|
|
||||||
#### UnifiedDate로 통합 (1개)
|
#### V2Date로 통합 (1개)
|
||||||
|
|
||||||
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
||||||
| :------------ | :------------- | :--- |
|
| :------------ | :------------- | :--- |
|
||||||
| date-input | `type: "date"` | |
|
| date-input | `type: "date"` | |
|
||||||
|
|
||||||
#### UnifiedText로 통합 (1개)
|
#### V2Text로 통합 (1개)
|
||||||
|
|
||||||
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
||||||
| :------------- | :--------------- | :--- |
|
| :------------- | :--------------- | :--- |
|
||||||
| textarea-basic | `mode: "simple"` | |
|
| textarea-basic | `mode: "simple"` | |
|
||||||
|
|
||||||
#### UnifiedMedia로 통합 (3개)
|
#### V2Media로 통합 (3개)
|
||||||
|
|
||||||
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
||||||
| :------------ | :------------------------------ | :--- |
|
| :------------ | :------------------------------ | :--- |
|
||||||
|
|
@ -225,7 +225,7 @@
|
||||||
| image-widget | `type: "image"` | |
|
| image-widget | `type: "image"` | |
|
||||||
| image-display | `type: "image", readonly: true` | |
|
| image-display | `type: "image", readonly: true` | |
|
||||||
|
|
||||||
#### UnifiedList로 통합 (8개)
|
#### V2List로 통합 (8개)
|
||||||
|
|
||||||
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
||||||
| :-------------------- | :------------------------------------ | :------------ |
|
| :-------------------- | :------------------------------------ | :------------ |
|
||||||
|
|
@ -238,7 +238,7 @@
|
||||||
| table-search-widget | `viewMode: "table", searchable: true` | |
|
| table-search-widget | `viewMode: "table", searchable: true` | |
|
||||||
| tax-invoice-list | `viewMode: "table", bizType: "tax"` | 특수 비즈니스 |
|
| tax-invoice-list | `viewMode: "table", bizType: "tax"` | 특수 비즈니스 |
|
||||||
|
|
||||||
#### UnifiedLayout으로 통합 (4개)
|
#### V2Layout으로 통합 (4개)
|
||||||
|
|
||||||
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
||||||
| :------------------ | :-------------------------- | :------------- |
|
| :------------------ | :-------------------------- | :------------- |
|
||||||
|
|
@ -247,7 +247,7 @@
|
||||||
| divider-line | `type: "divider"` | 속성 추가 필요 |
|
| divider-line | `type: "divider"` | 속성 추가 필요 |
|
||||||
| screen-split-panel | `type: "screen-embed"` | 화면 임베딩 |
|
| screen-split-panel | `type: "screen-embed"` | 화면 임베딩 |
|
||||||
|
|
||||||
#### UnifiedGroup으로 통합 (5개)
|
#### V2Group으로 통합 (5개)
|
||||||
|
|
||||||
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
||||||
| :------------------- | :--------------------- | :------------ |
|
| :------------------- | :--------------------- | :------------ |
|
||||||
|
|
@ -257,7 +257,7 @@
|
||||||
| section-card | `type: "card-section"` | |
|
| section-card | `type: "card-section"` | |
|
||||||
| universal-form-modal | `type: "form-modal"` | 복합 컴포넌트 |
|
| universal-form-modal | `type: "form-modal"` | 복합 컴포넌트 |
|
||||||
|
|
||||||
#### UnifiedBiz로 통합 (7개)
|
#### V2Biz로 통합 (7개)
|
||||||
|
|
||||||
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
| 현재 컴포넌트 | 매핑 속성 | 비고 |
|
||||||
| :-------------------- | :------------------------ | :--------------- |
|
| :-------------------- | :------------------------ | :--------------- |
|
||||||
|
|
@ -274,8 +274,8 @@
|
||||||
| 현재 컴포넌트 | 문제점 | 제안 |
|
| 현재 컴포넌트 | 문제점 | 제안 |
|
||||||
| :-------------------------- | :------------------- | :------------------------------ |
|
| :-------------------------- | :------------------- | :------------------------------ |
|
||||||
| conditional-container | 조건부 렌더링 로직 | 공통 속성으로 분리 |
|
| conditional-container | 조건부 렌더링 로직 | 공통 속성으로 분리 |
|
||||||
| selected-items-detail-input | 복합 (선택+상세입력) | UnifiedList + UnifiedGroup 조합 |
|
| selected-items-detail-input | 복합 (선택+상세입력) | V2List + V2Group 조합 |
|
||||||
| text-display | 읽기 전용 텍스트 | UnifiedInput (readonly: true) |
|
| text-display | 읽기 전용 텍스트 | V2Input (readonly: true) |
|
||||||
|
|
||||||
### 8.2 매핑 분석 결과
|
### 8.2 매핑 분석 결과
|
||||||
|
|
||||||
|
|
@ -291,7 +291,7 @@
|
||||||
|
|
||||||
### 8.3 속성 확장 필요 사항
|
### 8.3 속성 확장 필요 사항
|
||||||
|
|
||||||
#### UnifiedInput 속성 확장
|
#### V2Input 속성 확장
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 기존
|
// 기존
|
||||||
|
|
@ -301,7 +301,7 @@ type: "text" | "number" | "password";
|
||||||
type: "text" | "number" | "password" | "slider" | "color" | "button";
|
type: "text" | "number" | "password" | "slider" | "color" | "button";
|
||||||
```
|
```
|
||||||
|
|
||||||
#### UnifiedSelect 속성 확장
|
#### V2Select 속성 확장
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 기존
|
// 기존
|
||||||
|
|
@ -311,7 +311,7 @@ mode: "dropdown" | "radio" | "check" | "tag";
|
||||||
mode: "dropdown" | "radio" | "check" | "tag" | "toggle" | "swap";
|
mode: "dropdown" | "radio" | "check" | "tag" | "toggle" | "swap";
|
||||||
```
|
```
|
||||||
|
|
||||||
#### UnifiedLayout 속성 확장
|
#### V2Layout 속성 확장
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 기존
|
// 기존
|
||||||
|
|
@ -326,8 +326,8 @@ type: "grid" | "split" | "flex" | "divider" | "screen-embed";
|
||||||
`conditional-container`의 기능을 모든 컴포넌트에서 사용 가능한 공통 속성으로 분리합니다.
|
`conditional-container`의 기능을 모든 컴포넌트에서 사용 가능한 공통 속성으로 분리합니다.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 모든 Unified 컴포넌트에 적용 가능한 공통 속성
|
// 모든 V2 컴포넌트에 적용 가능한 공통 속성
|
||||||
interface BaseUnifiedProps {
|
interface BaseV2Props {
|
||||||
// ... 기존 속성
|
// ... 기존 속성
|
||||||
|
|
||||||
/** 조건부 렌더링 설정 */
|
/** 조건부 렌더링 설정 */
|
||||||
|
|
@ -356,12 +356,12 @@ DB 테이블 `cascading_hierarchy_group`에서 4가지 계층 타입을 지원
|
||||||
| **BOM** | 자재명세서 구조 | 부품 > 하위부품 |
|
| **BOM** | 자재명세서 구조 | 부품 > 하위부품 |
|
||||||
| **TREE** | 일반 트리 | 카테고리 |
|
| **TREE** | 일반 트리 | 카테고리 |
|
||||||
|
|
||||||
### 9.2 통합 방안: UnifiedHierarchy 신설 (10번째 컴포넌트)
|
### 9.2 통합 방안: V2Hierarchy 신설 (10번째 컴포넌트)
|
||||||
|
|
||||||
계층 구조는 일반 입력/표시 위젯과 성격이 다르므로 **별도 컴포넌트로 분리**합니다.
|
계층 구조는 일반 입력/표시 위젯과 성격이 다르므로 **별도 컴포넌트로 분리**합니다.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface UnifiedHierarchyProps {
|
interface V2HierarchyProps {
|
||||||
/** 계층 유형 */
|
/** 계층 유형 */
|
||||||
type: "tree" | "org" | "bom" | "cascading";
|
type: "tree" | "org" | "bom" | "cascading";
|
||||||
|
|
||||||
|
|
@ -400,16 +400,16 @@ interface UnifiedHierarchyProps {
|
||||||
|
|
||||||
| # | 컴포넌트 | 역할 | 커버 범위 |
|
| # | 컴포넌트 | 역할 | 커버 범위 |
|
||||||
| :-: | :------------------- | :------------- | :----------------------------------- |
|
| :-: | :------------------- | :------------- | :----------------------------------- |
|
||||||
| 1 | **UnifiedInput** | 단일 값 입력 | text, number, slider, button 등 |
|
| 1 | **V2Input** | 단일 값 입력 | text, number, slider, button 등 |
|
||||||
| 2 | **UnifiedSelect** | 선택 입력 | dropdown, radio, checkbox, toggle 등 |
|
| 2 | **V2Select** | 선택 입력 | dropdown, radio, checkbox, toggle 등 |
|
||||||
| 3 | **UnifiedDate** | 날짜/시간 입력 | date, datetime, time, range |
|
| 3 | **V2Date** | 날짜/시간 입력 | date, datetime, time, range |
|
||||||
| 4 | **UnifiedText** | 다중 행 텍스트 | textarea, rich editor, markdown |
|
| 4 | **V2Text** | 다중 행 텍스트 | textarea, rich editor, markdown |
|
||||||
| 5 | **UnifiedMedia** | 파일/미디어 | file, image, video, audio |
|
| 5 | **V2Media** | 파일/미디어 | file, image, video, audio |
|
||||||
| 6 | **UnifiedList** | 데이터 목록 | table, card, repeater, kanban |
|
| 6 | **V2List** | 데이터 목록 | table, card, repeater, kanban |
|
||||||
| 7 | **UnifiedLayout** | 레이아웃 배치 | grid, split, flex, divider |
|
| 7 | **V2Layout** | 레이아웃 배치 | grid, split, flex, divider |
|
||||||
| 8 | **UnifiedGroup** | 콘텐츠 그룹화 | tabs, accordion, section, modal |
|
| 8 | **V2Group** | 콘텐츠 그룹화 | tabs, accordion, section, modal |
|
||||||
| 9 | **UnifiedBiz** | 비즈니스 특화 | flow, rack, map, numbering 등 |
|
| 9 | **V2Biz** | 비즈니스 특화 | flow, rack, map, numbering 등 |
|
||||||
| 10 | **UnifiedHierarchy** | 계층 구조 | tree, org, bom, cascading |
|
| 10 | **V2Hierarchy** | 계층 구조 | tree, org, bom, cascading |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -443,14 +443,14 @@ interface UnifiedHierarchyProps {
|
||||||
|
|
||||||
### 11.3 속성 통합 설계
|
### 11.3 속성 통합 설계
|
||||||
|
|
||||||
#### 2단계 연쇄 → UnifiedSelect 속성
|
#### 2단계 연쇄 → V2Select 속성
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// AS-IS: 별도 관리 메뉴에서 정의 후 참조
|
// AS-IS: 별도 관리 메뉴에서 정의 후 참조
|
||||||
<SelectWidget cascadingRelation="WAREHOUSE_LOCATION" />
|
<SelectWidget cascadingRelation="WAREHOUSE_LOCATION" />
|
||||||
|
|
||||||
// TO-BE: 컴포넌트 속성에서 직접 정의
|
// TO-BE: 컴포넌트 속성에서 직접 정의
|
||||||
<UnifiedSelect
|
<V2Select
|
||||||
source="db"
|
source="db"
|
||||||
table="warehouse_location"
|
table="warehouse_location"
|
||||||
valueColumn="location_code"
|
valueColumn="location_code"
|
||||||
|
|
@ -470,7 +470,7 @@ interface UnifiedHierarchyProps {
|
||||||
// cascading_condition 테이블에 저장
|
// cascading_condition 테이블에 저장
|
||||||
|
|
||||||
// TO-BE: 모든 컴포넌트에 공통 속성으로 적용
|
// TO-BE: 모든 컴포넌트에 공통 속성으로 적용
|
||||||
<UnifiedInput
|
<V2Input
|
||||||
conditional={{
|
conditional={{
|
||||||
enabled: true,
|
enabled: true,
|
||||||
field: "order_type", // 참조할 필드
|
field: "order_type", // 참조할 필드
|
||||||
|
|
@ -487,7 +487,7 @@ interface UnifiedHierarchyProps {
|
||||||
// AS-IS: cascading_auto_fill_group 테이블에 정의
|
// AS-IS: cascading_auto_fill_group 테이블에 정의
|
||||||
|
|
||||||
// TO-BE: 컴포넌트 속성에서 직접 정의
|
// TO-BE: 컴포넌트 속성에서 직접 정의
|
||||||
<UnifiedInput
|
<V2Input
|
||||||
autoFill={{
|
autoFill={{
|
||||||
enabled: true,
|
enabled: true,
|
||||||
sourceTable: "company_mng", // 조회할 테이블
|
sourceTable: "company_mng", // 조회할 테이블
|
||||||
|
|
@ -504,7 +504,7 @@ interface UnifiedHierarchyProps {
|
||||||
// AS-IS: cascading_mutual_exclusion 테이블에 정의
|
// AS-IS: cascading_mutual_exclusion 테이블에 정의
|
||||||
|
|
||||||
// TO-BE: 컴포넌트 속성에서 직접 정의
|
// TO-BE: 컴포넌트 속성에서 직접 정의
|
||||||
<UnifiedSelect
|
<V2Select
|
||||||
mutualExclusion={{
|
mutualExclusion={{
|
||||||
enabled: true,
|
enabled: true,
|
||||||
targetField: "sub_category", // 상호 배제 대상 필드
|
targetField: "sub_category", // 상호 배제 대상 필드
|
||||||
|
|
@ -518,7 +518,7 @@ interface UnifiedHierarchyProps {
|
||||||
| 현재 메뉴 | TO-BE | 비고 |
|
| 현재 메뉴 | TO-BE | 비고 |
|
||||||
| :-------------------------- | :----------------------- | :-------------------- |
|
| :-------------------------- | :----------------------- | :-------------------- |
|
||||||
| **연쇄 드롭다운 통합 관리** | **삭제** | 6개 탭 전체 제거 |
|
| **연쇄 드롭다운 통합 관리** | **삭제** | 6개 탭 전체 제거 |
|
||||||
| ├─ 2단계 연쇄관계 | UnifiedSelect 속성 | inline 정의 |
|
| ├─ 2단계 연쇄관계 | V2Select 속성 | inline 정의 |
|
||||||
| ├─ 다단계 계층 | **테이블관리로 이동** | 복잡한 구조 유지 필요 |
|
| ├─ 다단계 계층 | **테이블관리로 이동** | 복잡한 구조 유지 필요 |
|
||||||
| ├─ 조건부 필터 | 공통 conditional 속성 | 모든 컴포넌트에 적용 |
|
| ├─ 조건부 필터 | 공통 conditional 속성 | 모든 컴포넌트에 적용 |
|
||||||
| ├─ 자동 입력 | autoFill 속성 | 컴포넌트별 정의 |
|
| ├─ 자동 입력 | autoFill 속성 | 컴포넌트별 정의 |
|
||||||
|
|
@ -557,21 +557,21 @@ interface UnifiedHierarchyProps {
|
||||||
|
|
||||||
| # | 컴포넌트 | 역할 |
|
| # | 컴포넌트 | 역할 |
|
||||||
| :-: | :------------------- | :--------------------------------------- |
|
| :-: | :------------------- | :--------------------------------------- |
|
||||||
| 1 | **UnifiedInput** | 단일 값 입력 (text, number, slider 등) |
|
| 1 | **V2Input** | 단일 값 입력 (text, number, slider 등) |
|
||||||
| 2 | **UnifiedSelect** | 선택 입력 (dropdown, radio, checkbox 등) |
|
| 2 | **V2Select** | 선택 입력 (dropdown, radio, checkbox 등) |
|
||||||
| 3 | **UnifiedDate** | 날짜/시간 입력 |
|
| 3 | **V2Date** | 날짜/시간 입력 |
|
||||||
| 4 | **UnifiedText** | 다중 행 텍스트 (textarea, rich editor) |
|
| 4 | **V2Text** | 다중 행 텍스트 (textarea, rich editor) |
|
||||||
| 5 | **UnifiedMedia** | 파일/미디어 (file, image) |
|
| 5 | **V2Media** | 파일/미디어 (file, image) |
|
||||||
| 6 | **UnifiedList** | 데이터 목록 (table, card, repeater) |
|
| 6 | **V2List** | 데이터 목록 (table, card, repeater) |
|
||||||
| 7 | **UnifiedLayout** | 레이아웃 배치 (grid, split, flex) |
|
| 7 | **V2Layout** | 레이아웃 배치 (grid, split, flex) |
|
||||||
| 8 | **UnifiedGroup** | 콘텐츠 그룹화 (tabs, accordion, section) |
|
| 8 | **V2Group** | 콘텐츠 그룹화 (tabs, accordion, section) |
|
||||||
| 9 | **UnifiedBiz** | 비즈니스 특화 (flow, rack, map 등) |
|
| 9 | **V2Biz** | 비즈니스 특화 (flow, rack, map 등) |
|
||||||
| 10 | **UnifiedHierarchy** | 계층 구조 (tree, org, bom, cascading) |
|
| 10 | **V2Hierarchy** | 계층 구조 (tree, org, bom, cascading) |
|
||||||
|
|
||||||
### 12.2 공통 속성 (모든 컴포넌트에 적용)
|
### 12.2 공통 속성 (모든 컴포넌트에 적용)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface BaseUnifiedProps {
|
interface BaseV2Props {
|
||||||
// 기본 속성
|
// 기본 속성
|
||||||
id: string;
|
id: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
|
|
@ -614,10 +614,10 @@ interface BaseUnifiedProps {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 12.3 UnifiedSelect 전용 속성
|
### 12.3 V2Select 전용 속성
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface UnifiedSelectProps extends BaseUnifiedProps {
|
interface V2SelectProps extends BaseV2Props {
|
||||||
// 표시 모드
|
// 표시 모드
|
||||||
mode: "dropdown" | "radio" | "check" | "tag" | "toggle" | "swap";
|
mode: "dropdown" | "radio" | "check" | "tag" | "toggle" | "swap";
|
||||||
|
|
||||||
|
|
@ -660,11 +660,11 @@ interface UnifiedSelectProps extends BaseUnifiedProps {
|
||||||
| AS-IS | TO-BE |
|
| AS-IS | TO-BE |
|
||||||
| :---------------------------- | :----------------------------------- |
|
| :---------------------------- | :----------------------------------- |
|
||||||
| 연쇄 드롭다운 통합 관리 (6탭) | **삭제** |
|
| 연쇄 드롭다운 통합 관리 (6탭) | **삭제** |
|
||||||
| - 2단계 연쇄관계 | → UnifiedSelect.cascading 속성 |
|
| - 2단계 연쇄관계 | → V2Select.cascading 속성 |
|
||||||
| - 다단계 계층 | → 테이블관리 > 계층 구조 설정 |
|
| - 다단계 계층 | → 테이블관리 > 계층 구조 설정 |
|
||||||
| - 조건부 필터 | → 공통 conditional 속성 |
|
| - 조건부 필터 | → 공통 conditional 속성 |
|
||||||
| - 자동 입력 | → 공통 autoFill 속성 |
|
| - 자동 입력 | → 공통 autoFill 속성 |
|
||||||
| - 상호 배제 | → UnifiedSelect.mutualExclusion 속성 |
|
| - 상호 배제 | → V2Select.mutualExclusion 속성 |
|
||||||
| - 카테고리 값 연쇄 | → 카테고리 관리와 통합 |
|
| - 카테고리 값 연쇄 | → 카테고리 관리와 통합 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# V2 컴포넌트 및 Unified 폼 컴포넌트 결합도 분석 보고서
|
# V2 컴포넌트 및 V2 폼 컴포넌트 결합도 분석 보고서
|
||||||
|
|
||||||
> 작성일: 2026-01-26
|
> 작성일: 2026-01-26
|
||||||
> 목적: 컴포넌트 간 결합도 분석 및 느슨한 결합 전환 가능성 평가
|
> 목적: 컴포넌트 간 결합도 분석 및 느슨한 결합 전환 가능성 평가
|
||||||
|
|
@ -29,23 +29,23 @@
|
||||||
| 16 | v2-table-search-widget | `v2-table-search-widget/` | 테이블 검색 위젯 |
|
| 16 | v2-table-search-widget | `v2-table-search-widget/` | 테이블 검색 위젯 |
|
||||||
| 17 | v2-tabs-widget | `v2-tabs-widget/` | 탭 위젯 |
|
| 17 | v2-tabs-widget | `v2-tabs-widget/` | 탭 위젯 |
|
||||||
| 18 | v2-text-display | `v2-text-display/` | 텍스트 표시 |
|
| 18 | v2-text-display | `v2-text-display/` | 텍스트 표시 |
|
||||||
| 19 | v2-unified-repeater | `v2-unified-repeater/` | 통합 리피터 |
|
| 19 | v2-repeater | `v2-repeater/` | 통합 리피터 |
|
||||||
|
|
||||||
### 1.2 Unified 폼 컴포넌트 (11개)
|
### 1.2 V2 폼 컴포넌트 (11개)
|
||||||
|
|
||||||
| # | 컴포넌트 | 파일 | 주요 용도 |
|
| # | 컴포넌트 | 파일 | 주요 용도 |
|
||||||
|---|---------|------|----------|
|
|---|---------|------|----------|
|
||||||
| 1 | UnifiedInput | `UnifiedInput.tsx` | 텍스트/숫자/이메일 등 입력 |
|
| 1 | V2Input | `V2Input.tsx` | 텍스트/숫자/이메일 등 입력 |
|
||||||
| 2 | UnifiedSelect | `UnifiedSelect.tsx` | 선택박스/라디오/체크박스 |
|
| 2 | V2Select | `V2Select.tsx` | 선택박스/라디오/체크박스 |
|
||||||
| 3 | UnifiedDate | `UnifiedDate.tsx` | 날짜/시간 입력 |
|
| 3 | V2Date | `V2Date.tsx` | 날짜/시간 입력 |
|
||||||
| 4 | UnifiedRepeater | `UnifiedRepeater.tsx` | 리피터 (테이블 형태) |
|
| 4 | V2Repeater | `V2Repeater.tsx` | 리피터 (테이블 형태) |
|
||||||
| 5 | UnifiedLayout | `UnifiedLayout.tsx` | 레이아웃 컨테이너 |
|
| 5 | V2Layout | `V2Layout.tsx` | 레이아웃 컨테이너 |
|
||||||
| 6 | UnifiedGroup | `UnifiedGroup.tsx` | 그룹 컨테이너 (카드/탭/접기) |
|
| 6 | V2Group | `V2Group.tsx` | 그룹 컨테이너 (카드/탭/접기) |
|
||||||
| 7 | UnifiedHierarchy | `UnifiedHierarchy.tsx` | 계층 구조 표시 |
|
| 7 | V2Hierarchy | `V2Hierarchy.tsx` | 계층 구조 표시 |
|
||||||
| 8 | UnifiedList | `UnifiedList.tsx` | 리스트 표시 |
|
| 8 | V2List | `V2List.tsx` | 리스트 표시 |
|
||||||
| 9 | UnifiedMedia | `UnifiedMedia.tsx` | 파일/이미지/비디오 업로드 |
|
| 9 | V2Media | `V2Media.tsx` | 파일/이미지/비디오 업로드 |
|
||||||
| 10 | UnifiedBiz | `UnifiedBiz.tsx` | 비즈니스 컴포넌트 |
|
| 10 | V2Biz | `V2Biz.tsx` | 비즈니스 컴포넌트 |
|
||||||
| 11 | UnifiedFormContext | `UnifiedFormContext.tsx` | 폼 상태 관리 컨텍스트 |
|
| 11 | V2FormContext | `V2FormContext.tsx` | 폼 상태 관리 컨텍스트 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -140,29 +140,29 @@ window.addEventListener("checkboxSelectionChange", handleSelectionChange);
|
||||||
| v2-table-search-widget | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| v2-table-search-widget | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| v2-text-display | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| v2-text-display | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| v2-repeat-screen-modal | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| v2-repeat-screen-modal | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| v2-unified-repeater | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| v2-repeater | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
|
|
||||||
### 2.3 Unified 폼 컴포넌트 결합도 상세
|
### 2.3 V2 폼 컴포넌트 결합도 상세
|
||||||
|
|
||||||
| 컴포넌트 | buttonActions Import | CustomEvent 사용 | window.__ 사용 | 결합도 점수 |
|
| 컴포넌트 | buttonActions Import | CustomEvent 사용 | window.__ 사용 | 결합도 점수 |
|
||||||
|---------|---------------------|------------------|----------------|------------|
|
|---------|---------------------|------------------|----------------|------------|
|
||||||
| **UnifiedRepeater** | ❌ | 7개 수신/발생 | 2개 사용 | 🔴 8/10 |
|
| **V2Repeater** | ❌ | 7개 수신/발생 | 2개 사용 | 🔴 8/10 |
|
||||||
| **UnifiedFormContext** | ❌ | 3개 발생 | ❌ | 🟠 4/10 |
|
| **V2FormContext** | ❌ | 3개 발생 | ❌ | 🟠 4/10 |
|
||||||
| UnifiedInput | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| V2Input | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| UnifiedSelect | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| V2Select | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| UnifiedDate | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| V2Date | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| UnifiedLayout | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| V2Layout | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| UnifiedGroup | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| V2Group | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| UnifiedHierarchy | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| V2Hierarchy | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| UnifiedList | ❌ | 0개 (TableList 래핑) | ❌ | 🟢 2/10 |
|
| V2List | ❌ | 0개 (TableList 래핑) | ❌ | 🟢 2/10 |
|
||||||
| UnifiedMedia | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| V2Media | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
| UnifiedBiz | ❌ | 0개 | ❌ | 🟢 1/10 |
|
| V2Biz | ❌ | 0개 | ❌ | 🟢 1/10 |
|
||||||
|
|
||||||
**UnifiedRepeater 상세:**
|
**V2Repeater 상세:**
|
||||||
```typescript
|
```typescript
|
||||||
// 전역 상태 사용
|
// 전역 상태 사용
|
||||||
window.__unifiedRepeaterInstances = new Set();
|
window.__v2RepeaterInstances = new Set();
|
||||||
window.__unifiedRepeaterInstances.add(targetTableName);
|
window.__v2RepeaterInstances.add(targetTableName);
|
||||||
|
|
||||||
// CustomEvent 수신
|
// CustomEvent 수신
|
||||||
window.addEventListener("repeaterSave", handleSaveEvent);
|
window.addEventListener("repeaterSave", handleSaveEvent);
|
||||||
|
|
@ -171,7 +171,7 @@ window.addEventListener("componentDataTransfer", handleComponentDataTransfer);
|
||||||
window.addEventListener("splitPanelDataTransfer", handleSplitPanelDataTransfer);
|
window.addEventListener("splitPanelDataTransfer", handleSplitPanelDataTransfer);
|
||||||
```
|
```
|
||||||
|
|
||||||
**UnifiedFormContext 상세:**
|
**V2FormContext 상세:**
|
||||||
```typescript
|
```typescript
|
||||||
// CustomEvent 발생 (레거시 호환)
|
// CustomEvent 발생 (레거시 호환)
|
||||||
window.dispatchEvent(new CustomEvent("beforeFormSave", { detail: eventDetail }));
|
window.dispatchEvent(new CustomEvent("beforeFormSave", { detail: eventDetail }));
|
||||||
|
|
@ -211,7 +211,7 @@ window.dispatchEvent(new CustomEvent("afterFormSave", { detail: { ... } }));
|
||||||
│ │
|
│ │
|
||||||
▼ ▼
|
▼ ▼
|
||||||
┌───────────┐ ┌───────────┐
|
┌───────────┐ ┌───────────┐
|
||||||
│Unified │ │Unified │
|
│V2 │ │V2 │
|
||||||
│Repeater │ │FormContext│
|
│Repeater │ │FormContext│
|
||||||
└───────────┘ └───────────┘
|
└───────────┘ └───────────┘
|
||||||
```
|
```
|
||||||
|
|
@ -227,10 +227,10 @@ window.dispatchEvent(new CustomEvent("afterFormSave", { detail: { ... } }));
|
||||||
| `refreshTable` | v2-button-primary, buttonActions | 테이블 데이터 새로고침 |
|
| `refreshTable` | v2-button-primary, buttonActions | 테이블 데이터 새로고침 |
|
||||||
| `closeEditModal` | v2-button-primary, buttonActions | 수정 모달 닫기 |
|
| `closeEditModal` | v2-button-primary, buttonActions | 수정 모달 닫기 |
|
||||||
| `saveSuccessInModal` | v2-button-primary, buttonActions | 저장 성공 알림 (연속 등록) |
|
| `saveSuccessInModal` | v2-button-primary, buttonActions | 저장 성공 알림 (연속 등록) |
|
||||||
| `beforeFormSave` | UnifiedFormContext, buttonActions | 저장 전 데이터 수집 |
|
| `beforeFormSave` | V2FormContext, buttonActions | 저장 전 데이터 수집 |
|
||||||
| `afterFormSave` | UnifiedFormContext | 저장 완료 알림 |
|
| `afterFormSave` | V2FormContext | 저장 완료 알림 |
|
||||||
| `tableListDataChange` | v2-table-list | 테이블 데이터 변경 알림 |
|
| `tableListDataChange` | v2-table-list | 테이블 데이터 변경 알림 |
|
||||||
| `repeaterDataChange` | UnifiedRepeater | 리피터 데이터 변경 알림 |
|
| `repeaterDataChange` | V2Repeater | 리피터 데이터 변경 알림 |
|
||||||
| `repeaterSave` | buttonActions | 리피터 저장 요청 |
|
| `repeaterSave` | buttonActions | 리피터 저장 요청 |
|
||||||
| `openScreenModal` | v2-split-panel-layout | 화면 모달 열기 |
|
| `openScreenModal` | v2-split-panel-layout | 화면 모달 열기 |
|
||||||
| `refreshCardDisplay` | buttonActions | 카드 디스플레이 새로고침 |
|
| `refreshCardDisplay` | buttonActions | 카드 디스플레이 새로고침 |
|
||||||
|
|
@ -240,13 +240,13 @@ window.dispatchEvent(new CustomEvent("afterFormSave", { detail: { ... } }));
|
||||||
| 이벤트명 | 수신 컴포넌트 | 처리 내용 |
|
| 이벤트명 | 수신 컴포넌트 | 처리 내용 |
|
||||||
|---------|-------------|----------|
|
|---------|-------------|----------|
|
||||||
| `refreshTable` | v2-table-list, v2-split-panel-layout | 데이터 재조회 |
|
| `refreshTable` | v2-table-list, v2-split-panel-layout | 데이터 재조회 |
|
||||||
| `beforeFormSave` | v2-repeat-container, UnifiedRepeater | formData에 섹션 데이터 추가 |
|
| `beforeFormSave` | v2-repeat-container, V2Repeater | formData에 섹션 데이터 추가 |
|
||||||
| `tableListDataChange` | v2-aggregation-widget, v2-repeat-container | 집계 재계산, 데이터 동기화 |
|
| `tableListDataChange` | v2-aggregation-widget, v2-repeat-container | 집계 재계산, 데이터 동기화 |
|
||||||
| `repeaterDataChange` | v2-aggregation-widget, v2-repeat-container | 집계 재계산, 데이터 동기화 |
|
| `repeaterDataChange` | v2-aggregation-widget, v2-repeat-container | 집계 재계산, 데이터 동기화 |
|
||||||
| `repeaterSave` | UnifiedRepeater | 리피터 데이터 저장 실행 |
|
| `repeaterSave` | V2Repeater | 리피터 데이터 저장 실행 |
|
||||||
| `selectionChange` | v2-aggregation-widget | 선택 기반 집계 |
|
| `selectionChange` | v2-aggregation-widget | 선택 기반 집계 |
|
||||||
| `componentDataTransfer` | UnifiedRepeater | 컴포넌트 간 데이터 전달 |
|
| `componentDataTransfer` | V2Repeater | 컴포넌트 간 데이터 전달 |
|
||||||
| `splitPanelDataTransfer` | UnifiedRepeater | 분할 패널 데이터 전달 |
|
| `splitPanelDataTransfer` | V2Repeater | 분할 패널 데이터 전달 |
|
||||||
| `refreshCardDisplay` | v2-card-display | 카드 데이터 재조회 |
|
| `refreshCardDisplay` | v2-card-display | 카드 데이터 재조회 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -255,7 +255,7 @@ window.dispatchEvent(new CustomEvent("afterFormSave", { detail: { ... } }));
|
||||||
|
|
||||||
| 전역 변수 | 사용 컴포넌트 | 용도 | 위험도 |
|
| 전역 변수 | 사용 컴포넌트 | 용도 | 위험도 |
|
||||||
|----------|-------------|------|--------|
|
|----------|-------------|------|--------|
|
||||||
| `window.__unifiedRepeaterInstances` | UnifiedRepeater, buttonActions | 리피터 인스턴스 추적 | 🟠 중간 |
|
| `window.__v2RepeaterInstances` | V2Repeater, buttonActions | 리피터 인스턴스 추적 | 🟠 중간 |
|
||||||
| `window.__relatedButtonsTargetTables` | v2-table-list | 관련 버튼 대상 테이블 | 🟠 중간 |
|
| `window.__relatedButtonsTargetTables` | v2-table-list | 관련 버튼 대상 테이블 | 🟠 중간 |
|
||||||
| `window.__relatedButtonsSelectedData` | v2-table-list, buttonActions | 관련 버튼 선택 데이터 | 🟠 중간 |
|
| `window.__relatedButtonsSelectedData` | v2-table-list, buttonActions | 관련 버튼 선택 데이터 | 🟠 중간 |
|
||||||
| `window.__dataRegistry` | v2-table-list (v1/v2) | 테이블 데이터 레지스트리 | 🟠 중간 |
|
| `window.__dataRegistry` | v2-table-list (v1/v2) | 테이블 데이터 레지스트리 | 🟠 중간 |
|
||||||
|
|
@ -272,12 +272,12 @@ window.dispatchEvent(new CustomEvent("afterFormSave", { detail: { ... } }));
|
||||||
| 🟠 중간 (4-6점) | 4개 | v2-repeat-container, v2-split-panel-layout, v2-aggregation-widget, v2-tabs-widget |
|
| 🟠 중간 (4-6점) | 4개 | v2-repeat-container, v2-split-panel-layout, v2-aggregation-widget, v2-tabs-widget |
|
||||||
| 🟢 낮음 (1-3점) | 12개 | 나머지 |
|
| 🟢 낮음 (1-3점) | 12개 | 나머지 |
|
||||||
|
|
||||||
### 6.2 Unified 컴포넌트 (11개)
|
### 6.2 V2 컴포넌트 (11개)
|
||||||
|
|
||||||
| 결합도 수준 | 개수 | 컴포넌트 |
|
| 결합도 수준 | 개수 | 컴포넌트 |
|
||||||
|------------|------|---------|
|
|------------|------|---------|
|
||||||
| 🔴 높음 (7-10점) | 1개 | UnifiedRepeater |
|
| 🔴 높음 (7-10점) | 1개 | V2Repeater |
|
||||||
| 🟠 중간 (4-6점) | 1개 | UnifiedFormContext |
|
| 🟠 중간 (4-6점) | 1개 | V2FormContext |
|
||||||
| 🟢 낮음 (1-3점) | 9개 | 나머지 |
|
| 🟢 낮음 (1-3점) | 9개 | 나머지 |
|
||||||
|
|
||||||
### 6.3 전체 결합도 분포
|
### 6.3 전체 결합도 분포
|
||||||
|
|
@ -288,14 +288,14 @@ window.dispatchEvent(new CustomEvent("afterFormSave", { detail: { ... } }));
|
||||||
높은 결합도 (🔴): 3개 (10.3%)
|
높은 결합도 (🔴): 3개 (10.3%)
|
||||||
├── v2-button-primary
|
├── v2-button-primary
|
||||||
├── v2-table-list
|
├── v2-table-list
|
||||||
└── UnifiedRepeater
|
└── V2Repeater
|
||||||
|
|
||||||
중간 결합도 (🟠): 5개 (17.2%)
|
중간 결합도 (🟠): 5개 (17.2%)
|
||||||
├── v2-repeat-container
|
├── v2-repeat-container
|
||||||
├── v2-split-panel-layout
|
├── v2-split-panel-layout
|
||||||
├── v2-aggregation-widget
|
├── v2-aggregation-widget
|
||||||
├── v2-tabs-widget
|
├── v2-tabs-widget
|
||||||
└── UnifiedFormContext
|
└── V2FormContext
|
||||||
|
|
||||||
낮은 결합도 (🟢): 21개 (72.5%)
|
낮은 결합도 (🟢): 21개 (72.5%)
|
||||||
└── 나머지 모든 컴포넌트
|
└── 나머지 모든 컴포넌트
|
||||||
|
|
@ -318,7 +318,7 @@ v2-table-list 오류 발생 시:
|
||||||
├── related-button 이벤트 미발생 → 관련 버튼 비활성화
|
├── related-button 이벤트 미발생 → 관련 버튼 비활성화
|
||||||
└── 전역 상태 오염 가능성
|
└── 전역 상태 오염 가능성
|
||||||
|
|
||||||
UnifiedRepeater 오류 발생 시:
|
V2Repeater 오류 발생 시:
|
||||||
├── beforeFormSave 처리 실패 → 리피터 데이터 저장 누락
|
├── beforeFormSave 처리 실패 → 리피터 데이터 저장 누락
|
||||||
├── repeaterSave 수신 실패 → 저장 요청 무시
|
├── repeaterSave 수신 실패 → 저장 요청 무시
|
||||||
└── 전역 인스턴스 레지스트리 오류
|
└── 전역 인스턴스 레지스트리 오류
|
||||||
|
|
@ -330,7 +330,7 @@ UnifiedRepeater 오류 발생 시:
|
||||||
|---------|-----------------|----------|
|
|---------|-----------------|----------|
|
||||||
| v2-button-primary | 저장/삭제 전체 | ❌ 격리 안됨 |
|
| v2-button-primary | 저장/삭제 전체 | ❌ 격리 안됨 |
|
||||||
| v2-table-list | 집계/관련버튼 | ❌ 격리 안됨 |
|
| v2-table-list | 집계/관련버튼 | ❌ 격리 안됨 |
|
||||||
| UnifiedRepeater | 리피터 저장 | ❌ 격리 안됨 |
|
| V2Repeater | 리피터 저장 | ❌ 격리 안됨 |
|
||||||
| v2-aggregation-widget | 자신만 | ✅ 부분 격리 |
|
| v2-aggregation-widget | 자신만 | ✅ 부분 격리 |
|
||||||
| v2-repeat-container | 자신만 | ✅ 부분 격리 |
|
| v2-repeat-container | 자신만 | ✅ 부분 격리 |
|
||||||
| 나머지 21개 | 자신만 | ✅ 완전 격리 |
|
| 나머지 21개 | 자신만 | ✅ 완전 격리 |
|
||||||
|
|
@ -357,7 +357,7 @@ UnifiedRepeater 오류 발생 시:
|
||||||
|---------|---------|----------|
|
|---------|---------|----------|
|
||||||
| 1 | v2-button-primary | buttonActions 의존성 제거, 독립 저장 서비스 |
|
| 1 | v2-button-primary | buttonActions 의존성 제거, 독립 저장 서비스 |
|
||||||
| 2 | v2-table-list | 전역 상태 제거, EventBus 전환 |
|
| 2 | v2-table-list | 전역 상태 제거, EventBus 전환 |
|
||||||
| 3 | UnifiedRepeater | 전역 상태 제거, EventBus 전환 |
|
| 3 | V2Repeater | 전역 상태 제거, EventBus 전환 |
|
||||||
|
|
||||||
### 8.3 3단계: 이벤트 통합 (2-3일)
|
### 8.3 3단계: 이벤트 통합 (2-3일)
|
||||||
|
|
||||||
|
|
@ -422,7 +422,7 @@ UnifiedRepeater 오류 발생 시:
|
||||||
|---------|-----------------|-------------------|-------------|------|
|
|---------|-----------------|-------------------|-------------|------|
|
||||||
| **v2-button-primary** | ✅ | ✅ | ✅ | 완료 |
|
| **v2-button-primary** | ✅ | ✅ | ✅ | 완료 |
|
||||||
| **v2-table-list** | ✅ | - | ✅ | 완료 |
|
| **v2-table-list** | ✅ | - | ✅ | 완료 |
|
||||||
| **UnifiedRepeater** | ✅ | - | ✅ | 완료 |
|
| **V2Repeater** | ✅ | - | ✅ | 완료 |
|
||||||
|
|
||||||
### 10.3 아키텍처 특징
|
### 10.3 아키텍처 특징
|
||||||
|
|
||||||
|
|
@ -469,7 +469,7 @@ useEffect(() => {
|
||||||
### 11.1 현재 상태 요약
|
### 11.1 현재 상태 요약
|
||||||
|
|
||||||
- **전체 29개 컴포넌트 중 72.5%(21개)는 이미 낮은 결합도**를 가지고 있어 독립적으로 동작
|
- **전체 29개 컴포넌트 중 72.5%(21개)는 이미 낮은 결합도**를 가지고 있어 독립적으로 동작
|
||||||
- **핵심 문제 컴포넌트 3개 (v2-button-primary, v2-table-list, UnifiedRepeater) 마이그레이션 완료**
|
- **핵심 문제 컴포넌트 3개 (v2-button-primary, v2-table-list, V2Repeater) 마이그레이션 완료**
|
||||||
- **buttonActions.ts (7,145줄)**는 추후 분할 예정 (현재는 동작 유지)
|
- **buttonActions.ts (7,145줄)**는 추후 분할 예정 (현재는 동작 유지)
|
||||||
|
|
||||||
### 11.2 달성 목표
|
### 11.2 달성 목표
|
||||||
|
|
@ -514,22 +514,22 @@ frontend/
|
||||||
│ │ ├── v2-table-search-widget/
|
│ │ ├── v2-table-search-widget/
|
||||||
│ │ ├── v2-tabs-widget/
|
│ │ ├── v2-tabs-widget/
|
||||||
│ │ ├── v2-text-display/
|
│ │ ├── v2-text-display/
|
||||||
│ │ └── v2-unified-repeater/
|
│ │ └── v2-repeater/
|
||||||
│ └── utils/
|
│ └── utils/
|
||||||
│ └── buttonActions.ts (7,145줄)
|
│ └── buttonActions.ts (7,145줄)
|
||||||
└── components/
|
└── components/
|
||||||
└── unified/
|
└── v2/
|
||||||
├── UnifiedInput.tsx
|
├── V2Input.tsx
|
||||||
├── UnifiedSelect.tsx
|
├── V2Select.tsx
|
||||||
├── UnifiedDate.tsx
|
├── V2Date.tsx
|
||||||
├── UnifiedRepeater.tsx
|
├── V2Repeater.tsx
|
||||||
├── UnifiedLayout.tsx
|
├── V2Layout.tsx
|
||||||
├── UnifiedGroup.tsx
|
├── V2Group.tsx
|
||||||
├── UnifiedHierarchy.tsx
|
├── V2Hierarchy.tsx
|
||||||
├── UnifiedList.tsx
|
├── V2List.tsx
|
||||||
├── UnifiedMedia.tsx
|
├── V2Media.tsx
|
||||||
├── UnifiedBiz.tsx
|
├── V2Biz.tsx
|
||||||
└── UnifiedFormContext.tsx
|
└── V2FormContext.tsx
|
||||||
```
|
```
|
||||||
|
|
||||||
## 부록 B: V2 Core 파일 구조 (구현됨)
|
## 부록 B: V2 Core 파일 구조 (구현됨)
|
||||||
|
|
@ -67,7 +67,7 @@ V2(Version 2) 컴포넌트는 기존 레거시 컴포넌트의 문제점을 해
|
||||||
|------------|------|------|
|
|------------|------|------|
|
||||||
| `v2-rack-structure` | 렉 구조 | 창고 렉 구조 표시 |
|
| `v2-rack-structure` | 렉 구조 | 창고 렉 구조 표시 |
|
||||||
| `v2-repeat-screen-modal` | 반복 화면 모달 | 반복 가능한 화면 모달 |
|
| `v2-repeat-screen-modal` | 반복 화면 모달 | 반복 가능한 화면 모달 |
|
||||||
| `v2-unified-repeater` | 통합 리피터 | 통합 리피터 테이블 |
|
| `v2-repeater` | 통합 리피터 | 통합 리피터 테이블 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -172,10 +172,10 @@ import { V2ErrorBoundary } from "@/lib/v2-core";
|
||||||
|--------|------|--------|--------|
|
|--------|------|--------|--------|
|
||||||
| `v2:table:refresh` | 테이블 새로고침 | v2-button-primary | v2-table-list |
|
| `v2:table:refresh` | 테이블 새로고침 | v2-button-primary | v2-table-list |
|
||||||
| `v2:table:data:change` | 테이블 데이터 변경 | v2-table-list | v2-aggregation-widget |
|
| `v2:table:data:change` | 테이블 데이터 변경 | v2-table-list | v2-aggregation-widget |
|
||||||
| `v2:form:save:collect` | 폼 저장 전 데이터 수집 | buttonActions | v2-repeat-container, UnifiedRepeater |
|
| `v2:form:save:collect` | 폼 저장 전 데이터 수집 | buttonActions | v2-repeat-container, V2Repeater |
|
||||||
| `v2:modal:close` | 모달 닫기 | v2-button-primary | EditModal |
|
| `v2:modal:close` | 모달 닫기 | v2-button-primary | EditModal |
|
||||||
| `v2:modal:save:success` | 모달 저장 성공 | v2-button-primary | EditModal |
|
| `v2:modal:save:success` | 모달 저장 성공 | v2-button-primary | EditModal |
|
||||||
| `v2:repeater:save` | 리피터 저장 | buttonActions | UnifiedRepeater |
|
| `v2:repeater:save` | 리피터 저장 | buttonActions | V2Repeater |
|
||||||
| `v2:component:error` | 컴포넌트 에러 | V2ErrorBoundary | 로깅/모니터링 |
|
| `v2:component:error` | 컴포넌트 에러 | V2ErrorBoundary | 로깅/모니터링 |
|
||||||
|
|
||||||
### 4.2 이벤트 흐름 다이어그램
|
### 4.2 이벤트 흐름 다이어그램
|
||||||
|
|
@ -333,7 +333,7 @@ export const BadConfigPanel: React.FC<Props> = ({ config, onChange }) => {
|
||||||
|---------|-------------|---------------|-------------|
|
|---------|-------------|---------------|-------------|
|
||||||
| v2-button-primary | ✅ | ✅ | ✅ |
|
| v2-button-primary | ✅ | ✅ | ✅ |
|
||||||
| v2-table-list | ✅ | ✅ | ✅ |
|
| v2-table-list | ✅ | ✅ | ✅ |
|
||||||
| UnifiedRepeater | ✅ | ✅ | ✅ |
|
| V2Repeater | ✅ | ✅ | ✅ |
|
||||||
|
|
||||||
### 7.3 장애 격리 검증
|
### 7.3 장애 격리 검증
|
||||||
|
|
||||||
|
|
@ -341,7 +341,7 @@ export const BadConfigPanel: React.FC<Props> = ({ config, onChange }) => {
|
||||||
v2-button-primary 에러 발생 시:
|
v2-button-primary 에러 발생 시:
|
||||||
├── V2ErrorBoundary 캐치 → 버튼만 에러 UI 표시
|
├── V2ErrorBoundary 캐치 → 버튼만 에러 UI 표시
|
||||||
├── v2-table-list: 정상 동작 ✅
|
├── v2-table-list: 정상 동작 ✅
|
||||||
└── UnifiedRepeater: 정상 동작 ✅
|
└── V2Repeater: 정상 동작 ✅
|
||||||
|
|
||||||
v2-table-list 에러 발생 시:
|
v2-table-list 에러 발생 시:
|
||||||
├── V2ErrorBoundary 캐치 → 테이블만 에러 UI 표시
|
├── V2ErrorBoundary 캐치 → 테이블만 에러 UI 표시
|
||||||
|
|
@ -351,30 +351,30 @@ v2-table-list 에러 발생 시:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Unified 폼 컴포넌트
|
## 8. V2 폼 컴포넌트
|
||||||
|
|
||||||
### 8.1 목록 (11개)
|
### 8.1 목록 (11개)
|
||||||
|
|
||||||
| 컴포넌트 | 파일 | 용도 |
|
| 컴포넌트 | 파일 | 용도 |
|
||||||
|---------|------|------|
|
|---------|------|------|
|
||||||
| UnifiedInput | UnifiedInput.tsx | 텍스트/숫자/이메일/채번 입력 |
|
| V2Input | V2Input.tsx | 텍스트/숫자/이메일/채번 입력 |
|
||||||
| UnifiedSelect | UnifiedSelect.tsx | 선택박스/라디오/체크박스/카테고리 |
|
| V2Select | V2Select.tsx | 선택박스/라디오/체크박스/카테고리 |
|
||||||
| UnifiedDate | UnifiedDate.tsx | 날짜/시간 입력 |
|
| V2Date | V2Date.tsx | 날짜/시간 입력 |
|
||||||
| UnifiedRepeater | UnifiedRepeater.tsx | 리피터 테이블 |
|
| V2Repeater | V2Repeater.tsx | 리피터 테이블 |
|
||||||
| UnifiedLayout | UnifiedLayout.tsx | 레이아웃 컨테이너 |
|
| V2Layout | V2Layout.tsx | 레이아웃 컨테이너 |
|
||||||
| UnifiedGroup | UnifiedGroup.tsx | 그룹 컨테이너 |
|
| V2Group | V2Group.tsx | 그룹 컨테이너 |
|
||||||
| UnifiedHierarchy | UnifiedHierarchy.tsx | 계층 구조 표시 |
|
| V2Hierarchy | V2Hierarchy.tsx | 계층 구조 표시 |
|
||||||
| UnifiedList | UnifiedList.tsx | 리스트 표시 |
|
| V2List | V2List.tsx | 리스트 표시 |
|
||||||
| UnifiedMedia | UnifiedMedia.tsx | 파일/이미지/비디오 |
|
| V2Media | V2Media.tsx | 파일/이미지/비디오 |
|
||||||
| UnifiedBiz | UnifiedBiz.tsx | 비즈니스 컴포넌트 |
|
| V2Biz | V2Biz.tsx | 비즈니스 컴포넌트 |
|
||||||
| UnifiedFormContext | UnifiedFormContext.tsx | 폼 상태 관리 |
|
| V2FormContext | V2FormContext.tsx | 폼 상태 관리 |
|
||||||
|
|
||||||
### 8.2 inputType 자동 처리
|
### 8.2 inputType 자동 처리
|
||||||
|
|
||||||
Unified 컴포넌트는 `inputType`에 따라 자동으로 적절한 UI를 렌더링합니다:
|
V2 컴포넌트는 `inputType`에 따라 자동으로 적절한 UI를 렌더링합니다:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// UnifiedInput.tsx
|
// V2Input.tsx
|
||||||
switch (inputType) {
|
switch (inputType) {
|
||||||
case "numbering":
|
case "numbering":
|
||||||
// 채번 규칙 자동 조회 및 코드 생성
|
// 채번 규칙 자동 조회 및 코드 생성
|
||||||
|
|
@ -386,7 +386,7 @@ switch (inputType) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnifiedSelect.tsx
|
// V2Select.tsx
|
||||||
switch (inputType) {
|
switch (inputType) {
|
||||||
case "category":
|
case "category":
|
||||||
// 카테고리 값 자동 조회 및 드롭다운 표시
|
// 카테고리 값 자동 조회 및 드롭다운 표시
|
||||||
|
|
@ -468,8 +468,8 @@ V2 Core:
|
||||||
V2 컴포넌트:
|
V2 컴포넌트:
|
||||||
- frontend/lib/registry/components/v2-*/
|
- frontend/lib/registry/components/v2-*/
|
||||||
|
|
||||||
Unified 폼 컴포넌트:
|
V2 폼 컴포넌트:
|
||||||
- frontend/components/unified/
|
- frontend/components/v2/
|
||||||
|
|
||||||
채번/카테고리 테스트 테이블:
|
채번/카테고리 테스트 테이블:
|
||||||
- db/migrations/040_create_numbering_rules_test.sql
|
- db/migrations/040_create_numbering_rules_test.sql
|
||||||
|
|
@ -534,6 +534,6 @@ frontend/lib/registry/components/
|
||||||
├── v2-table-search-widget/
|
├── v2-table-search-widget/
|
||||||
├── v2-tabs-widget/
|
├── v2-tabs-widget/
|
||||||
├── v2-text-display/
|
├── v2-text-display/
|
||||||
└── v2-unified-repeater/
|
└── v2-repeater/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -15,29 +15,29 @@
|
||||||
|
|
||||||
### 상위 15개 컴포넌트
|
### 상위 15개 컴포넌트
|
||||||
|
|
||||||
| 순위 | 컴포넌트 | 사용 횟수 | 사용 화면 수 | Unified 매핑 |
|
| 순위 | 컴포넌트 | 사용 횟수 | 사용 화면 수 | V2 매핑 |
|
||||||
| :--: | :-------------------------- | :-------: | :----------: | :------------------------------ |
|
| :--: | :-------------------------- | :-------: | :----------: | :------------------------------ |
|
||||||
| 1 | button-primary | 571 | 364 | UnifiedInput (type: button) |
|
| 1 | button-primary | 571 | 364 | V2Input (type: button) |
|
||||||
| 2 | text-input | 805 | 166 | **UnifiedInput (type: text)** |
|
| 2 | text-input | 805 | 166 | **V2Input (type: text)** |
|
||||||
| 3 | table-list | 130 | 130 | UnifiedList (viewMode: table) |
|
| 3 | table-list | 130 | 130 | V2List (viewMode: table) |
|
||||||
| 4 | table-search-widget | 127 | 127 | UnifiedList (searchable: true) |
|
| 4 | table-search-widget | 127 | 127 | V2List (searchable: true) |
|
||||||
| 5 | select-basic | 121 | 76 | **UnifiedSelect** |
|
| 5 | select-basic | 121 | 76 | **V2Select** |
|
||||||
| 6 | number-input | 86 | 34 | **UnifiedInput (type: number)** |
|
| 6 | number-input | 86 | 34 | **V2Input (type: number)** |
|
||||||
| 7 | date-input | 83 | 51 | **UnifiedDate** |
|
| 7 | date-input | 83 | 51 | **V2Date** |
|
||||||
| 8 | file-upload | 41 | 18 | UnifiedMedia (type: file) |
|
| 8 | file-upload | 41 | 18 | V2Media (type: file) |
|
||||||
| 9 | tabs-widget | 39 | 39 | UnifiedGroup (type: tabs) |
|
| 9 | tabs-widget | 39 | 39 | V2Group (type: tabs) |
|
||||||
| 10 | split-panel-layout | 39 | 39 | UnifiedLayout (type: split) |
|
| 10 | split-panel-layout | 39 | 39 | V2Layout (type: split) |
|
||||||
| 11 | category-manager | 38 | 38 | UnifiedBiz (type: category) |
|
| 11 | category-manager | 38 | 38 | V2Biz (type: category) |
|
||||||
| 12 | numbering-rule | 31 | 31 | UnifiedBiz (type: numbering) |
|
| 12 | numbering-rule | 31 | 31 | V2Biz (type: numbering) |
|
||||||
| 13 | selected-items-detail-input | 29 | 29 | 복합 컴포넌트 |
|
| 13 | selected-items-detail-input | 29 | 29 | 복합 컴포넌트 |
|
||||||
| 14 | modal-repeater-table | 25 | 25 | UnifiedList (modal: true) |
|
| 14 | modal-repeater-table | 25 | 25 | V2List (modal: true) |
|
||||||
| 15 | image-widget | 29 | 29 | UnifiedMedia (type: image) |
|
| 15 | image-widget | 29 | 29 | V2Media (type: image) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Unified 컴포넌트별 통합 대상 분석
|
## 2. V2 컴포넌트별 통합 대상 분석
|
||||||
|
|
||||||
### UnifiedInput (예상 통합 대상: 891개)
|
### V2Input (예상 통합 대상: 891개)
|
||||||
|
|
||||||
| 기존 컴포넌트 | 사용 횟수 | 비율 |
|
| 기존 컴포넌트 | 사용 횟수 | 비율 |
|
||||||
| :------------ | :-------: | :---: |
|
| :------------ | :-------: | :---: |
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
**우선순위: 1위** - 가장 많이 사용되는 컴포넌트
|
**우선순위: 1위** - 가장 많이 사용되는 컴포넌트
|
||||||
|
|
||||||
### UnifiedSelect (예상 통합 대상: 140개)
|
### V2Select (예상 통합 대상: 140개)
|
||||||
|
|
||||||
| 기존 컴포넌트 | 사용 횟수 | widgetType |
|
| 기존 컴포넌트 | 사용 횟수 | widgetType |
|
||||||
| :------------------------ | :-------: | :--------- |
|
| :------------------------ | :-------: | :--------- |
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
|
|
||||||
**우선순위: 2위** - 다양한 모드 지원 필요
|
**우선순위: 2위** - 다양한 모드 지원 필요
|
||||||
|
|
||||||
### UnifiedDate (예상 통합 대상: 83개)
|
### V2Date (예상 통합 대상: 83개)
|
||||||
|
|
||||||
| 기존 컴포넌트 | 사용 횟수 |
|
| 기존 컴포넌트 | 사용 횟수 |
|
||||||
| :---------------- | :-------: |
|
| :---------------- | :-------: |
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
|
|
||||||
**우선순위: 3위**
|
**우선순위: 3위**
|
||||||
|
|
||||||
### UnifiedList (예상 통합 대상: 283개)
|
### V2List (예상 통합 대상: 283개)
|
||||||
|
|
||||||
| 기존 컴포넌트 | 사용 횟수 | 비고 |
|
| 기존 컴포넌트 | 사용 횟수 | 비고 |
|
||||||
| :-------------------- | :-------: | :---------- |
|
| :-------------------- | :-------: | :---------- |
|
||||||
|
|
@ -82,14 +82,14 @@
|
||||||
|
|
||||||
**우선순위: 4위** - 핵심 데이터 표시 컴포넌트
|
**우선순위: 4위** - 핵심 데이터 표시 컴포넌트
|
||||||
|
|
||||||
### UnifiedMedia (예상 통합 대상: 70개)
|
### V2Media (예상 통합 대상: 70개)
|
||||||
|
|
||||||
| 기존 컴포넌트 | 사용 횟수 |
|
| 기존 컴포넌트 | 사용 횟수 |
|
||||||
| :------------ | :-------: |
|
| :------------ | :-------: |
|
||||||
| file-upload | 41 |
|
| file-upload | 41 |
|
||||||
| image-widget | 29 |
|
| image-widget | 29 |
|
||||||
|
|
||||||
### UnifiedLayout (예상 통합 대상: 62개)
|
### V2Layout (예상 통합 대상: 62개)
|
||||||
|
|
||||||
| 기존 컴포넌트 | 사용 횟수 |
|
| 기존 컴포넌트 | 사용 횟수 |
|
||||||
| :------------------ | :-------: |
|
| :------------------ | :-------: |
|
||||||
|
|
@ -97,7 +97,7 @@
|
||||||
| screen-split-panel | 21 |
|
| screen-split-panel | 21 |
|
||||||
| split-panel-layout2 | 2 |
|
| split-panel-layout2 | 2 |
|
||||||
|
|
||||||
### UnifiedGroup (예상 통합 대상: 99개)
|
### V2Group (예상 통합 대상: 99개)
|
||||||
|
|
||||||
| 기존 컴포넌트 | 사용 횟수 |
|
| 기존 컴포넌트 | 사용 횟수 |
|
||||||
| :-------------------- | :-------: |
|
| :-------------------- | :-------: |
|
||||||
|
|
@ -109,7 +109,7 @@
|
||||||
| universal-form-modal | 7 |
|
| universal-form-modal | 7 |
|
||||||
| repeat-screen-modal | 5 |
|
| repeat-screen-modal | 5 |
|
||||||
|
|
||||||
### UnifiedBiz (예상 통합 대상: 79개)
|
### V2Biz (예상 통합 대상: 79개)
|
||||||
|
|
||||||
| 기존 컴포넌트 | 사용 횟수 |
|
| 기존 컴포넌트 | 사용 횟수 |
|
||||||
| :--------------------- | :-------: |
|
| :--------------------- | :-------: |
|
||||||
|
|
@ -127,27 +127,27 @@
|
||||||
|
|
||||||
### Phase 1 우선순위 (즉시 효과가 큰 컴포넌트)
|
### Phase 1 우선순위 (즉시 효과가 큰 컴포넌트)
|
||||||
|
|
||||||
| 순위 | Unified 컴포넌트 | 통합 대상 수 | 영향 화면 수 | 이유 |
|
| 순위 | V2 컴포넌트 | 통합 대상 수 | 영향 화면 수 | 이유 |
|
||||||
| :---: | :---------------- | :----------: | :----------: | :--------------- |
|
| :---: | :---------------- | :----------: | :----------: | :--------------- |
|
||||||
| **1** | **UnifiedInput** | 891개 | 200+ | 가장 많이 사용 |
|
| **1** | **V2Input** | 891개 | 200+ | 가장 많이 사용 |
|
||||||
| **2** | **UnifiedSelect** | 140개 | 100+ | 다양한 모드 필요 |
|
| **2** | **V2Select** | 140개 | 100+ | 다양한 모드 필요 |
|
||||||
| **3** | **UnifiedDate** | 83개 | 51 | 비교적 단순 |
|
| **3** | **V2Date** | 83개 | 51 | 비교적 단순 |
|
||||||
|
|
||||||
### Phase 2 우선순위 (데이터 표시 컴포넌트)
|
### Phase 2 우선순위 (데이터 표시 컴포넌트)
|
||||||
|
|
||||||
| 순위 | Unified 컴포넌트 | 통합 대상 수 | 이유 |
|
| 순위 | V2 컴포넌트 | 통합 대상 수 | 이유 |
|
||||||
| :---: | :---------------- | :----------: | :--------------- |
|
| :---: | :---------------- | :----------: | :--------------- |
|
||||||
| **4** | **UnifiedList** | 283개 | 핵심 데이터 표시 |
|
| **4** | **V2List** | 283개 | 핵심 데이터 표시 |
|
||||||
| **5** | **UnifiedLayout** | 62개 | 레이아웃 구조 |
|
| **5** | **V2Layout** | 62개 | 레이아웃 구조 |
|
||||||
| **6** | **UnifiedGroup** | 99개 | 콘텐츠 그룹화 |
|
| **6** | **V2Group** | 99개 | 콘텐츠 그룹화 |
|
||||||
|
|
||||||
### Phase 3 우선순위 (특수 컴포넌트)
|
### Phase 3 우선순위 (특수 컴포넌트)
|
||||||
|
|
||||||
| 순위 | Unified 컴포넌트 | 통합 대상 수 | 이유 |
|
| 순위 | V2 컴포넌트 | 통합 대상 수 | 이유 |
|
||||||
| :---: | :------------------- | :----------: | :------------ |
|
| :---: | :------------------- | :----------: | :------------ |
|
||||||
| **7** | **UnifiedMedia** | 70개 | 파일/이미지 |
|
| **7** | **V2Media** | 70개 | 파일/이미지 |
|
||||||
| **8** | **UnifiedBiz** | 79개 | 비즈니스 특화 |
|
| **8** | **V2Biz** | 79개 | 비즈니스 특화 |
|
||||||
| **9** | **UnifiedHierarchy** | 0개 | 신규 기능 |
|
| **9** | **V2Hierarchy** | 0개 | 신규 기능 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -156,8 +156,8 @@
|
||||||
### 4.1 button-primary 분리 검토
|
### 4.1 button-primary 분리 검토
|
||||||
|
|
||||||
- 사용량: 571개 (1위)
|
- 사용량: 571개 (1위)
|
||||||
- 현재 계획: UnifiedInput에 포함
|
- 현재 계획: V2Input에 포함
|
||||||
- **제안**: 별도 `UnifiedButton` 컴포넌트로 분리 검토
|
- **제안**: 별도 `V2Button` 컴포넌트로 분리 검토
|
||||||
- 버튼은 입력과 성격이 다름
|
- 버튼은 입력과 성격이 다름
|
||||||
- 액션 타입, 스타일, 권한 등 복잡한 설정 필요
|
- 액션 타입, 스타일, 권한 등 복잡한 설정 필요
|
||||||
|
|
||||||
|
|
@ -181,5 +181,5 @@
|
||||||
1. [ ] 데이터 마이그레이션 전략 설계 (Phase 0-2)
|
1. [ ] 데이터 마이그레이션 전략 설계 (Phase 0-2)
|
||||||
2. [ ] sys_input_type JSON Schema 설계 (Phase 0-3)
|
2. [ ] sys_input_type JSON Schema 설계 (Phase 0-3)
|
||||||
3. [ ] DynamicConfigPanel 프로토타입 (Phase 0-4)
|
3. [ ] DynamicConfigPanel 프로토타입 (Phase 0-4)
|
||||||
4. [ ] UnifiedInput 구현 시작 (Phase 1-1)
|
4. [ ] V2Input 구현 시작 (Phase 1-1)
|
||||||
|
|
||||||
|
|
@ -67,8 +67,8 @@
|
||||||
"componentConfig": { ... },
|
"componentConfig": { ... },
|
||||||
|
|
||||||
// 신규 필드 추가
|
// 신규 필드 추가
|
||||||
"unifiedType": "UnifiedInput", // 새로운 통합 컴포넌트 타입
|
"v2Type": "V2Input", // 새로운 통합 컴포넌트 타입
|
||||||
"unifiedConfig": { // 새로운 설정 구조
|
"v2Config": { // 새로운 설정 구조
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"format": "none",
|
"format": "none",
|
||||||
"placeholder": "텍스트를 입력하세요"
|
"placeholder": "텍스트를 입력하세요"
|
||||||
|
|
@ -87,13 +87,13 @@
|
||||||
### 2.2 렌더링 로직 수정
|
### 2.2 렌더링 로직 수정
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 렌더러에서 unifiedType 우선 사용
|
// 렌더러에서 v2Type 우선 사용
|
||||||
function renderComponent(props: ComponentProps) {
|
function renderComponent(props: ComponentProps) {
|
||||||
// 신규 타입이 있으면 Unified 컴포넌트 사용
|
// 신규 타입이 있으면 V2 컴포넌트 사용
|
||||||
if (props.unifiedType) {
|
if (props.v2Type) {
|
||||||
return <UnifiedComponentRenderer
|
return <V2ComponentRenderer
|
||||||
type={props.unifiedType}
|
type={props.v2Type}
|
||||||
config={props.unifiedConfig}
|
config={props.v2Config}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ function renderComponent(props: ComponentProps) {
|
||||||
|
|
||||||
## 3. 컴포넌트별 매핑 규칙
|
## 3. 컴포넌트별 매핑 규칙
|
||||||
|
|
||||||
### 3.1 text-input → UnifiedInput
|
### 3.1 text-input → V2Input
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// AS-IS
|
// AS-IS
|
||||||
|
|
@ -126,8 +126,8 @@ function renderComponent(props: ComponentProps) {
|
||||||
|
|
||||||
// TO-BE
|
// TO-BE
|
||||||
{
|
{
|
||||||
"unifiedType": "UnifiedInput",
|
"v2Type": "V2Input",
|
||||||
"unifiedConfig": {
|
"v2Config": {
|
||||||
"type": "text", // componentConfig.webType 또는 "text"
|
"type": "text", // componentConfig.webType 또는 "text"
|
||||||
"format": "none", // componentConfig.format
|
"format": "none", // componentConfig.format
|
||||||
"placeholder": "..." // componentConfig.placeholder
|
"placeholder": "..." // componentConfig.placeholder
|
||||||
|
|
@ -135,7 +135,7 @@ function renderComponent(props: ComponentProps) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3.2 number-input → UnifiedInput
|
### 3.2 number-input → V2Input
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// AS-IS
|
// AS-IS
|
||||||
|
|
@ -152,8 +152,8 @@ function renderComponent(props: ComponentProps) {
|
||||||
|
|
||||||
// TO-BE
|
// TO-BE
|
||||||
{
|
{
|
||||||
"unifiedType": "UnifiedInput",
|
"v2Type": "V2Input",
|
||||||
"unifiedConfig": {
|
"v2Config": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"min": 0,
|
"min": 0,
|
||||||
"max": 100,
|
"max": 100,
|
||||||
|
|
@ -162,7 +162,7 @@ function renderComponent(props: ComponentProps) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3.3 select-basic → UnifiedSelect
|
### 3.3 select-basic → V2Select
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// AS-IS (code 타입)
|
// AS-IS (code 타입)
|
||||||
|
|
@ -178,8 +178,8 @@ function renderComponent(props: ComponentProps) {
|
||||||
|
|
||||||
// TO-BE
|
// TO-BE
|
||||||
{
|
{
|
||||||
"unifiedType": "UnifiedSelect",
|
"v2Type": "V2Select",
|
||||||
"unifiedConfig": {
|
"v2Config": {
|
||||||
"mode": "dropdown",
|
"mode": "dropdown",
|
||||||
"source": "code",
|
"source": "code",
|
||||||
"codeGroup": "ORDER_STATUS"
|
"codeGroup": "ORDER_STATUS"
|
||||||
|
|
@ -200,8 +200,8 @@ function renderComponent(props: ComponentProps) {
|
||||||
|
|
||||||
// TO-BE
|
// TO-BE
|
||||||
{
|
{
|
||||||
"unifiedType": "UnifiedSelect",
|
"v2Type": "V2Select",
|
||||||
"unifiedConfig": {
|
"v2Config": {
|
||||||
"mode": "dropdown",
|
"mode": "dropdown",
|
||||||
"source": "entity",
|
"source": "entity",
|
||||||
"searchable": true,
|
"searchable": true,
|
||||||
|
|
@ -211,7 +211,7 @@ function renderComponent(props: ComponentProps) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3.4 date-input → UnifiedDate
|
### 3.4 date-input → V2Date
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// AS-IS
|
// AS-IS
|
||||||
|
|
@ -226,8 +226,8 @@ function renderComponent(props: ComponentProps) {
|
||||||
|
|
||||||
// TO-BE
|
// TO-BE
|
||||||
{
|
{
|
||||||
"unifiedType": "UnifiedDate",
|
"v2Type": "V2Date",
|
||||||
"unifiedConfig": {
|
"v2Config": {
|
||||||
"type": "date",
|
"type": "date",
|
||||||
"format": "YYYY-MM-DD"
|
"format": "YYYY-MM-DD"
|
||||||
}
|
}
|
||||||
|
|
@ -245,11 +245,11 @@ function renderComponent(props: ComponentProps) {
|
||||||
|
|
||||||
interface MigrationResult {
|
interface MigrationResult {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
unifiedType: string;
|
v2Type: string;
|
||||||
unifiedConfig: Record<string, any>;
|
v2Config: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function migrateToUnified(
|
export function migrateToV2(
|
||||||
componentType: string,
|
componentType: string,
|
||||||
componentConfig: Record<string, any>
|
componentConfig: Record<string, any>
|
||||||
): MigrationResult {
|
): MigrationResult {
|
||||||
|
|
@ -258,8 +258,8 @@ export function migrateToUnified(
|
||||||
case 'text-input':
|
case 'text-input':
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
unifiedType: 'UnifiedInput',
|
v2Type: 'V2Input',
|
||||||
unifiedConfig: {
|
v2Config: {
|
||||||
type: componentConfig.webType || 'text',
|
type: componentConfig.webType || 'text',
|
||||||
format: componentConfig.format || 'none',
|
format: componentConfig.format || 'none',
|
||||||
placeholder: componentConfig.placeholder
|
placeholder: componentConfig.placeholder
|
||||||
|
|
@ -269,8 +269,8 @@ export function migrateToUnified(
|
||||||
case 'number-input':
|
case 'number-input':
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
unifiedType: 'UnifiedInput',
|
v2Type: 'V2Input',
|
||||||
unifiedConfig: {
|
v2Config: {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
min: componentConfig.min,
|
min: componentConfig.min,
|
||||||
max: componentConfig.max,
|
max: componentConfig.max,
|
||||||
|
|
@ -281,8 +281,8 @@ export function migrateToUnified(
|
||||||
case 'select-basic':
|
case 'select-basic':
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
unifiedType: 'UnifiedSelect',
|
v2Type: 'V2Select',
|
||||||
unifiedConfig: {
|
v2Config: {
|
||||||
mode: 'dropdown',
|
mode: 'dropdown',
|
||||||
source: componentConfig.webType || 'static',
|
source: componentConfig.webType || 'static',
|
||||||
codeGroup: componentConfig.codeCategory,
|
codeGroup: componentConfig.codeCategory,
|
||||||
|
|
@ -295,8 +295,8 @@ export function migrateToUnified(
|
||||||
case 'date-input':
|
case 'date-input':
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
unifiedType: 'UnifiedDate',
|
v2Type: 'V2Date',
|
||||||
unifiedConfig: {
|
v2Config: {
|
||||||
type: componentConfig.webType || 'date',
|
type: componentConfig.webType || 'date',
|
||||||
format: componentConfig.format
|
format: componentConfig.format
|
||||||
}
|
}
|
||||||
|
|
@ -305,8 +305,8 @@ export function migrateToUnified(
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
unifiedType: '',
|
v2Type: '',
|
||||||
unifiedConfig: {}
|
v2Config: {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -322,8 +322,8 @@ SELECT * FROM screen_layouts;
|
||||||
-- 마이그레이션 실행 (text-input 예시)
|
-- 마이그레이션 실행 (text-input 예시)
|
||||||
UPDATE screen_layouts
|
UPDATE screen_layouts
|
||||||
SET properties = properties || jsonb_build_object(
|
SET properties = properties || jsonb_build_object(
|
||||||
'unifiedType', 'UnifiedInput',
|
'v2Type', 'V2Input',
|
||||||
'unifiedConfig', jsonb_build_object(
|
'v2Config', jsonb_build_object(
|
||||||
'type', COALESCE(properties->'componentConfig'->>'webType', 'text'),
|
'type', COALESCE(properties->'componentConfig'->>'webType', 'text'),
|
||||||
'format', COALESCE(properties->'componentConfig'->>'format', 'none'),
|
'format', COALESCE(properties->'componentConfig'->>'format', 'none'),
|
||||||
'placeholder', properties->'componentConfig'->>'placeholder'
|
'placeholder', properties->'componentConfig'->>'placeholder'
|
||||||
|
|
@ -352,7 +352,7 @@ WHERE sl.layout_id = slb.layout_id;
|
||||||
|
|
||||||
-- 또는 신규 필드만 제거
|
-- 또는 신규 필드만 제거
|
||||||
UPDATE screen_layouts
|
UPDATE screen_layouts
|
||||||
SET properties = properties - 'unifiedType' - 'unifiedConfig' - '_migration';
|
SET properties = properties - 'v2Type' - 'v2Config' - '_migration';
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5.2 단계적 롤백
|
### 5.2 단계적 롤백
|
||||||
|
|
@ -362,7 +362,7 @@ SET properties = properties - 'unifiedType' - 'unifiedConfig' - '_migration';
|
||||||
async function rollbackScreen(screenId: number) {
|
async function rollbackScreen(screenId: number) {
|
||||||
await db.query(`
|
await db.query(`
|
||||||
UPDATE screen_layouts sl
|
UPDATE screen_layouts sl
|
||||||
SET properties = properties - 'unifiedType' - 'unifiedConfig' - '_migration'
|
SET properties = properties - 'v2Type' - 'v2Config' - '_migration'
|
||||||
WHERE screen_id = $1
|
WHERE screen_id = $1
|
||||||
`, [screenId]);
|
`, [screenId]);
|
||||||
}
|
}
|
||||||
|
|
@ -375,9 +375,9 @@ async function rollbackScreen(screenId: number) {
|
||||||
| 단계 | 작업 | 대상 | 시점 |
|
| 단계 | 작업 | 대상 | 시점 |
|
||||||
|:---:|:---|:---|:---|
|
|:---:|:---|:---|:---|
|
||||||
| 1 | 백업 테이블 생성 | 전체 | Phase 1 시작 전 |
|
| 1 | 백업 테이블 생성 | 전체 | Phase 1 시작 전 |
|
||||||
| 2 | UnifiedInput 마이그레이션 | text-input, number-input | Phase 1 중 |
|
| 2 | V2Input 마이그레이션 | text-input, number-input | Phase 1 중 |
|
||||||
| 3 | UnifiedSelect 마이그레이션 | select-basic | Phase 1 중 |
|
| 3 | V2Select 마이그레이션 | select-basic | Phase 1 중 |
|
||||||
| 4 | UnifiedDate 마이그레이션 | date-input | Phase 1 중 |
|
| 4 | V2Date 마이그레이션 | date-input | Phase 1 중 |
|
||||||
| 5 | 검증 및 테스트 | 전체 | Phase 1 완료 후 |
|
| 5 | 검증 및 테스트 | 전체 | Phase 1 완료 후 |
|
||||||
| 6 | 레거시 필드 제거 | 전체 | Phase 5 (추후) |
|
| 6 | 레거시 필드 제거 | 전체 | Phase 5 (추후) |
|
||||||
|
|
||||||
|
|
@ -477,7 +477,7 @@ className={cn(
|
||||||
|
|
||||||
- ✅ `FileComponentConfigPanel.tsx`: `text-gray-900` → `text-foreground`, `text-blue-*` → `text-primary`
|
- ✅ `FileComponentConfigPanel.tsx`: `text-gray-900` → `text-foreground`, `text-blue-*` → `text-primary`
|
||||||
- ✅ `ButtonConfigPanel.tsx`: 모든 `text-gray-*`, `bg-gray-*`, `hover:bg-gray-*` 교체
|
- ✅ `ButtonConfigPanel.tsx`: 모든 `text-gray-*`, `bg-gray-*`, `hover:bg-gray-*` 교체
|
||||||
- ✅ `UnifiedPropertiesPanel.tsx`: 모든 `text-gray-*`, `border-gray-*` 교체
|
- ✅ `V2PropertiesPanel.tsx`: 모든 `text-gray-*`, `border-gray-*` 교체
|
||||||
- ✅ `app/(main)/admin/page.tsx`: 전체 페이지 하드코딩 색상 교체
|
- ✅ `app/(main)/admin/page.tsx`: 전체 페이지 하드코딩 색상 교체
|
||||||
- ✅ `CardDisplayComponent.tsx`: 모든 `text-gray-*`, `bg-gray-*`, 인라인 색상 교체
|
- ✅ `CardDisplayComponent.tsx`: 모든 `text-gray-*`, `bg-gray-*`, 인라인 색상 교체
|
||||||
- ✅ `getComponentConfigPanel.tsx`: 로딩 상태 하드코딩 색상 교체
|
- ✅ `getComponentConfigPanel.tsx`: 로딩 상태 하드코딩 색상 교체
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue