# 화면관리 시스템 타입 문제 분석 및 해결방안 ## 📋 현재 상황 분석 ### 주요 시스템들 1. **화면관리 시스템** (Screen Management) 2. **제어관리 시스템** (Button Dataflow Control) 3. **테이블 타입관리 시스템** (Table Type Management) ### 발견된 문제점들 ## 🚨 1. 타입 정의 분산 및 중복 문제 ### 1.1 WebType 타입 정의 분산 **문제**: WebType이 여러 파일에서 서로 다르게 정의되어 불일치 발생 #### 현재 상황: - `frontend/types/screen.ts`: 화면관리용 WebType 정의 - `backend-node/src/types/tableManagement.ts`: 테이블관리용 타입 정의 - `backend-node/prisma/schema.prisma`: DB 스키마의 web_type_standards 모델 - `frontend/lib/registry/types.ts`: 레지스트리용 WebType 정의 #### 구체적 충돌 사례: ```typescript // frontend/types/screen.ts export type WebType = | "text" | "number" | "date" | "code" | "entity" | "textarea" | "boolean" | "decimal" | "button" | "datetime" | "dropdown" | "text_area" | "checkbox" | "radio" | "file" | "email" | "tel" | "url"; // 실제 DB에서는 다른 web_type 값들이 존재할 수 있음 // 예: "varchar", "integer", "timestamp" 등 ``` ### 1.2 ButtonActionType 중복 정의 **문제**: 버튼 액션 타입이 여러 곳에서 다르게 정의됨 #### 충돌 위치: - `frontend/types/screen.ts`: `"control"` 포함, `"modal"` 포함 - `frontend/lib/utils/buttonActions.ts`: `"cancel"` 포함, `"modal"` 포함 - `frontend/hooks/admin/useButtonActions.ts`: DB 스키마 기반 정의 #### 문제 코드: ```typescript // frontend/types/screen.ts export type ButtonActionType = | "save" | "delete" | "edit" | "add" | "search" | "reset" | "submit" | "close" | "popup" | "modal" | "newWindow" | "navigate" | "control"; // frontend/lib/utils/buttonActions.ts export type ButtonActionType = | "save" | "cancel" | "delete" | "edit" | "add" | "search" | "reset" | "submit" | "close" | "popup" | "navigate" | "modal" | "newWindow"; ``` ## 🚨 2. 데이터베이스 스키마와 TypeScript 타입 불일치 ### 2.1 web_type_standards 테이블 불일치 **문제**: Prisma 스키마와 TypeScript 인터페이스 간 필드명/타입 차이 #### DB 스키마: ```sql model web_type_standards { web_type String @id @db.VarChar(50) type_name String @db.VarChar(100) type_name_eng String? @db.VarChar(100) description String? category String? @default("input") @db.VarChar(50) default_config Json? -- JSON 타입 validation_rules Json? -- JSON 타입 component_name String? @default("TextWidget") @db.VarChar(100) config_panel String? @db.VarChar(100) } ``` #### TypeScript 인터페이스: ```typescript export interface WebTypeDefinition { id: string; // web_type와 매핑되지 않음 name: string; // type_name과 매핑? category: string; description: string; defaultConfig: Record; // default_config Json과 타입 불일치 validationRules?: Record; // validation_rules Json과 타입 불일치 isActive: boolean; // DB에는 is_active String 필드 } ``` ### 2.2 ColumnInfo 타입 불일치 **문제**: 테이블 컬럼 정보 타입이 프론트엔드/백엔드에서 다름 #### 백엔드 타입: ```typescript // backend-node/src/types/tableManagement.ts export interface ColumnTypeInfo { columnName: string; displayName: string; dataType: string; dbType: string; webType: string; // string 타입 inputType?: "direct" | "auto"; detailSettings: string; // JSON 문자열 isNullable: string; // "Y" | "N" 문자열 isPrimaryKey: boolean; } ``` #### 프론트엔드 타입: ```typescript // frontend/types/screen.ts export interface ColumnInfo { tableName: string; columnName: string; columnLabel?: string; dataType: string; webType?: WebType; // WebType union 타입 (불일치!) inputType?: "direct" | "auto"; isNullable: string; detailSettings?: string; // optional vs required 차이 } ``` ## 🚨 3. 컴포넌트 인터페이스 타입 안전성 문제 ### 3.1 ComponentData 타입 캐스팅 문제 **문제**: 런타임에 타입 안전성이 보장되지 않는 강제 캐스팅 #### 문제 코드: ```typescript // frontend/components/screen/RealtimePreview.tsx const widget = component as WidgetComponent; // 위험한 강제 캐스팅 // frontend/components/screen/InteractiveScreenViewer.tsx component: any; // any 타입으로 타입 안전성 상실 ``` ### 3.2 DynamicWebTypeRenderer Props 불일치 **문제**: 동적 렌더링 시 props 타입이 일관되지 않음 #### 문제 위치: ```typescript // frontend/lib/registry/DynamicWebTypeRenderer.tsx export interface DynamicComponentProps { webType: string; // WebType이 아닌 string props?: Record; // any 타입 사용 config?: Record; // any 타입 사용 onEvent?: (event: string, data: any) => void; // any 타입 } // 실제 사용 시 {...} // any 타입 콜백 }} /> ``` ## 🚨 4. 제어관리 시스템 타입 문제 ### 4.1 ButtonDataflowConfig 타입 복잡성 **문제**: 제어관리 설정이 복잡하고 타입 안전성 부족 #### 현재 타입: ```typescript export interface ButtonDataflowConfig { controlMode: "simple" | "advanced"; selectedDiagramId?: number; selectedRelationshipId?: number; directControl?: { conditions: DataflowCondition[]; // 복잡한 중첩 타입 actions: any[]; // any 타입 사용 }; } ``` ### 4.2 OptimizedButtonDataflowService 타입 문제 **문제**: 서비스 클래스에서 any 타입 남용으로 타입 안전성 상실 #### Linter 오류 (57개): - `Unexpected any` 경고 26개 - `unknown` 타입 오류 2개 - 사용되지 않는 변수 경고 29개 ## 🎯 해결방안 및 구현 계획 ## Phase 1: 중앙집중식 타입 정의 통합 (우선순위: 높음) ### 1.1 통합 타입 파일 생성 ``` frontend/types/ ├── unified-core.ts # 핵심 공통 타입들 ├── screen-management.ts # 화면관리 전용 타입 ├── control-management.ts # 제어관리 전용 타입 ├── table-management.ts # 테이블관리 전용 타입 └── index.ts # 모든 타입 re-export ``` ### 1.2 WebType 통합 정의 ```typescript // frontend/types/unified-core.ts export type WebType = | "text" | "number" | "decimal" | "date" | "datetime" | "select" | "dropdown" | "radio" | "checkbox" | "boolean" | "textarea" | "code" | "entity" | "file" | "email" | "tel" | "url" | "button"; // DB에서 동적으로 로드되는 웹타입도 지원 export type DynamicWebType = WebType | string; ``` ### 1.3 ButtonActionType 통합 정의 ```typescript // frontend/types/unified-core.ts export type ButtonActionType = | "save" | "cancel" | "delete" | "edit" | "add" | "search" | "reset" | "submit" | "close" | "popup" | "modal" | "navigate" | "control"; ``` ## Phase 2: 데이터베이스 타입 매핑 표준화 (우선순위: 높음) ### 2.1 Prisma 스키마 기반 타입 생성 ```typescript // frontend/types/database-mappings.ts import { web_type_standards, button_action_standards } from "@prisma/client"; // Prisma 타입을 프론트엔드 타입으로 변환하는 매퍼 export type WebTypeStandard = web_type_standards; export interface WebTypeDefinition { webType: string; // web_type 필드 typeName: string; // type_name 필드 typeNameEng?: string; // type_name_eng 필드 description?: string; category: string; defaultConfig: Record; // Json 타입 매핑 validationRules?: Record; // Json 타입 매핑 componentName?: string; // component_name 필드 configPanel?: string; // config_panel 필드 isActive: boolean; // is_active "Y"/"N" → boolean 변환 } // 변환 함수 export const mapWebTypeStandardToDefinition = ( standard: WebTypeStandard ): WebTypeDefinition => ({ webType: standard.web_type, typeName: standard.type_name, typeNameEng: standard.type_name_eng || undefined, description: standard.description || undefined, category: standard.category || "input", defaultConfig: (standard.default_config as any) || {}, validationRules: (standard.validation_rules as any) || undefined, componentName: standard.component_name || undefined, configPanel: standard.config_panel || undefined, isActive: standard.is_active === "Y", }); ``` ### 2.2 ColumnInfo 타입 통합 ```typescript // frontend/types/table-management.ts export interface UnifiedColumnInfo { // 공통 필드 tableName: string; columnName: string; displayName: string; dataType: string; // DB 데이터 타입 webType: DynamicWebType; // 웹 타입 (동적 지원) // 상세 정보 inputType: "direct" | "auto"; detailSettings?: Record; // JSON 파싱된 객체 description?: string; isNullable: boolean; // "Y"/"N" → boolean 변환 isPrimaryKey: boolean; // 표시 옵션 isVisible?: boolean; displayOrder?: number; // 메타데이터 maxLength?: number; numericPrecision?: number; numericScale?: number; defaultValue?: string; // 참조 관계 codeCategory?: string; referenceTable?: string; referenceColumn?: string; displayColumn?: string; } ``` ## Phase 3: 컴포넌트 타입 안전성 강화 (우선순위: 중간) ### 3.1 ComponentData 타입 가드 구현 ```typescript // frontend/types/screen-management.ts export type ComponentData = | ContainerComponent | WidgetComponent | GroupComponent | DataTableComponent; // 타입 가드 함수들 export const isWidgetComponent = ( component: ComponentData ): component is WidgetComponent => { return component.type === "widget"; }; export const isContainerComponent = ( component: ComponentData ): component is ContainerComponent => { return component.type === "container"; }; // 안전한 타입 캐스팅 유틸리티 export const asWidgetComponent = ( component: ComponentData ): WidgetComponent => { if (!isWidgetComponent(component)) { throw new Error(`Expected WidgetComponent, got ${component.type}`); } return component; }; ``` ### 3.2 DynamicWebTypeRenderer Props 타입 강화 ```typescript // frontend/lib/registry/types.ts export interface StrictDynamicComponentProps { webType: DynamicWebType; component: ComponentData; config?: WebTypeConfig; value?: unknown; onChange?: (value: unknown) => void; onEvent?: (event: WebTypeEvent) => void; readonly?: boolean; required?: boolean; className?: string; } export interface WebTypeEvent { type: "change" | "blur" | "focus" | "click"; value: unknown; field?: string; } export type WebTypeConfig = Record; ``` ## Phase 4: 제어관리 시스템 타입 정리 (우선순위: 중간) ### 4.1 ButtonDataflowConfig 타입 명확화 ```typescript // frontend/types/control-management.ts export interface ButtonDataflowConfig { // 기본 설정 controlMode: "simple" | "advanced"; // 관계도 방식 selectedDiagramId?: number; selectedRelationshipId?: number; // 직접 설정 방식 directControl?: DirectControlConfig; } export interface DirectControlConfig { conditions: DataflowCondition[]; actions: DataflowAction[]; logic?: "AND" | "OR"; } export interface DataflowCondition { id: string; type: "condition" | "group"; field?: string; operator?: ConditionOperator; value?: unknown; dataSource?: "form" | "table-selection" | "both"; } export interface DataflowAction { id: string; type: ActionType; tableName?: string; operation?: "INSERT" | "UPDATE" | "DELETE" | "SELECT"; fields?: ActionField[]; conditions?: DataflowCondition[]; } export type ConditionOperator = | "=" | "!=" | ">" | "<" | ">=" | "<=" | "LIKE" | "IN" | "NOT IN"; export type ActionType = "database" | "api" | "notification" | "redirect"; ``` ### 4.2 OptimizedButtonDataflowService 타입 정리 ```typescript // frontend/lib/services/optimizedButtonDataflowService.ts // any 타입 제거 및 구체적 타입 정의 export interface ExecutionContext { formData: Record; selectedRows?: unknown[]; selectedRowsData?: Record[]; controlDataSource: ControlDataSource; buttonId: string; componentData?: ComponentData; timestamp: string; clickCount?: number; } export interface ActionResult { success: boolean; message: string; data?: Record; error?: string; } export interface ValidationResult { success: boolean; message?: string; canExecuteImmediately: boolean; actions?: DataflowAction[]; } ``` ## Phase 5: 마이그레이션 및 검증 (우선순위: 낮음) ### 5.1 점진적 마이그레이션 계획 1. **Step 1**: 새로운 통합 타입 파일들 생성 2. **Step 2**: 기존 파일들에서 새 타입 import로 변경 3. **Step 3**: 타입 가드 및 유틸리티 함수 적용 4. **Step 4**: any 타입 제거 및 구체적 타입 적용 5. **Step 5**: 기존 타입 정의 파일들 제거 ### 5.2 검증 도구 구축 ```typescript // scripts/type-validation.ts // 타입 일관성 검증 스크립트 작성 // DB 스키마와 TypeScript 타입 간 일치성 검증 // 컴포넌트 Props 타입 검증 ``` ## 📋 구현 우선순위 ### 🔥 즉시 해결 필요 (Critical) 1. **WebType 통합** - 가장 많이 사용되는 기본 타입 2. **ButtonActionType 통합** - 제어관리 시스템 안정성 확보 3. **ColumnInfo 타입 표준화** - 테이블 관리 기능 정상화 ### ⚡ 단기간 해결 (High) 4. **ComponentData 타입 가드** - 런타임 안전성 확보 5. **DB 타입 매핑** - 프론트엔드/백엔드 연동 안정화 6. **DynamicWebTypeRenderer Props 정리** - 동적 렌더링 안정성 ### 📅 중장기 해결 (Medium) 7. **OptimizedButtonDataflowService any 타입 제거** - 코드 품질 향상 8. **ButtonDataflowConfig 구조 개선** - 제어관리 시스템 고도화 9. **타입 검증 도구 구축** - 지속적인 품질 관리 ## 💡 기대 효과 ### 개발 경험 개선 - 타입 자동완성 정확도 향상 - 컴파일 타임 오류 감소 - IDE 지원 기능 활용도 증대 ### 시스템 안정성 향상 - 런타임 타입 오류 방지 - API 연동 안정성 확보 - 데이터 일관성 보장 ### 유지보수성 향상 - 코드 가독성 개선 - 리팩토링 안정성 확보 - 새 기능 추가 시 사이드 이펙트 최소화 --- ## 🚀 다음 단계 이 분석을 바탕으로 다음과 같은 단계로 진행하는 것을 권장합니다: 1. **우선순위 검토**: 위의 우선순위가 프로젝트 상황에 적합한지 검토 2. **Phase 1 착수**: 통합 타입 파일 생성부터 시작 3. **점진적 적용**: 한 번에 모든 것을 바꾸지 말고 단계적으로 적용 4. **테스트 강화**: 타입 변경 시마다 충분한 테스트 수행 이 계획에 대한 의견이나 수정사항이 있으시면 말씀해 주세요.