# 테이블 타입 관리 개선 계획서 ## 🎯 개선 목표 현재 테이블 타입 관리 시스템의 용어 통일과 타입 단순화를 통해 사용자 친화적이고 유연한 시스템으로 개선합니다. ## 📋 주요 변경사항 ### 1. 용어 변경 - **웹 타입(Web Type)** → **입력 타입(Input Type)** - 사용자에게 더 직관적인 명칭으로 변경 ### 2. 입력 타입 단순화 기존 20개 타입에서 **8개 핵심 타입**으로 단순화: | 번호 | 입력 타입 | 설명 | 예시 | | ---- | ---------- | ---------- | -------------------- | | 1 | `text` | 텍스트 | 이름, 제목, 설명 | | 2 | `number` | 숫자 | 수량, 건수, 순번 | | 3 | `date` | 날짜 | 생성일, 완료일, 기한 | | 4 | `code` | 코드 | 상태코드, 유형코드 | | 5 | `entity` | 엔티티 | 고객선택, 제품선택 | | 6 | `select` | 선택박스 | 드롭다운 목록 | | 7 | `checkbox` | 체크박스 | Y/N, 사용여부 | | 8 | `radio` | 라디오버튼 | 단일선택 옵션 | ### 3. DB 타입 제거 - 컬럼 정보에서 `dbType` 필드 제거 - 입력 타입만으로 데이터 처리 방식 결정 ## 🛠️ 기술적 구현 방안 ### 전체 VARCHAR 통일 방식 (확정) **모든 신규 테이블의 사용자 정의 컬럼을 VARCHAR(500)로 생성하고 애플리케이션 레벨에서 형변환 처리** #### 핵심 장점 - ✅ **최대 유연성**: 어떤 데이터든 타입 에러 없이 저장 가능 - ✅ **에러 제로**: 타입 불일치로 인한 DB 삽입/수정 에러 완전 차단 - ✅ **개발 속도**: 복잡한 타입 고민 없이 빠른 개발 가능 - ✅ **요구사항 대응**: 필드 성격 변경 시에도 스키마 수정 불필요 - ✅ **데이터 마이그레이션**: 기존 시스템 데이터 이관 시 100% 안전 #### 실제 예시 ```sql -- 기존 방식 (타입별 생성) CREATE TABLE products ( id serial PRIMARY KEY, name varchar(255), -- 텍스트 price numeric(10,2), -- 숫자 launch_date date, -- 날짜 is_active boolean -- 체크박스 ); -- 새로운 방식 (VARCHAR 통일) CREATE TABLE products ( id serial PRIMARY KEY, created_date timestamp DEFAULT now(), updated_date timestamp DEFAULT now(), company_code varchar(50) DEFAULT '*', writer varchar(100), -- 사용자 정의 컬럼들은 모두 VARCHAR(500) name varchar(500), -- 입력타입: text price varchar(500), -- 입력타입: number → "15000.50" launch_date varchar(500), -- 입력타입: date → "2024-03-15" is_active varchar(500) -- 입력타입: checkbox → "Y"/"N" ); ``` #### 애플리케이션 레벨 처리 ````typescript // 입력 타입별 형변환 및 검증 export class InputTypeProcessor { // 저장 전 변환 (화면 → DB) static convertForStorage(value: any, inputType: string): string { if (value === null || value === undefined) return ""; switch (inputType) { case "text": return String(value); case "number": const num = parseFloat(String(value)); return isNaN(num) ? "0" : String(num); case "date": if (!value) return ""; const date = new Date(value); return isNaN(date.getTime()) ? "" : date.toISOString().split('T')[0]; case "checkbox": return ["true", "1", "Y", "yes"].includes(String(value).toLowerCase()) ? "Y" : "N"; default: return String(value); } } // 표시용 변환 (DB → 화면) static convertForDisplay(value: string, inputType: string): any { if (!value) return inputType === "number" ? 0 : ""; switch (inputType) { case "number": const num = parseFloat(value); return isNaN(num) ? 0 : num; case "date": return value; // YYYY-MM-DD 형식 그대로 case "checkbox": return value === "Y"; default: return value; } } } ## 🏗️ 구현 단계 ### Phase 1: 타입 정의 수정 (1-2일) #### 1.1 입력 타입 enum 업데이트 ```typescript // frontend/types/unified-web-types.ts export type InputType = | "text" // 텍스트 | "number" // 숫자 | "date" // 날짜 | "code" // 코드 | "entity" // 엔티티 | "select" // 선택박스 | "checkbox" // 체크박스 | "radio"; // 라디오버튼 ```` #### 1.2 UI 표시명 업데이트 ```typescript export const INPUT_TYPE_OPTIONS = [ { value: "text", label: "텍스트", description: "일반 텍스트 입력" }, { value: "number", label: "숫자", description: "숫자 입력 (정수/소수)" }, { value: "date", label: "날짜", description: "날짜 선택" }, { value: "code", label: "코드", description: "공통코드 참조" }, { value: "entity", label: "엔티티", description: "다른 테이블 참조" }, { value: "select", label: "선택박스", description: "드롭다운 선택" }, { value: "checkbox", label: "체크박스", description: "체크박스 입력" }, { value: "radio", label: "라디오버튼", description: "단일 선택" }, ]; ``` ### Phase 2: 데이터베이스 스키마 수정 (1일) #### 2.1 테이블 스키마 수정 ```sql -- table_type_columns 테이블 수정 ALTER TABLE table_type_columns DROP COLUMN IF EXISTS db_type; -- 컬럼명 변경 ALTER TABLE table_type_columns RENAME COLUMN web_type TO input_type; -- 기존 데이터 마이그레이션 UPDATE table_type_columns SET input_type = CASE WHEN input_type IN ('textarea') THEN 'text' WHEN input_type IN ('decimal') THEN 'number' WHEN input_type IN ('datetime') THEN 'date' WHEN input_type IN ('dropdown') THEN 'select' WHEN input_type IN ('boolean') THEN 'checkbox' WHEN input_type NOT IN ('text', 'number', 'date', 'code', 'entity', 'select', 'checkbox', 'radio') THEN 'text' ELSE input_type END; ``` ### Phase 3: 백엔드 서비스 수정 (2-3일) #### 3.1 DDL 생성 로직 수정 ```typescript // 전체 VARCHAR 통일 방식으로 수정 private mapInputTypeToPostgresType(inputType: string): string { // 기본 컬럼들은 기존 타입 유지 (시스템 컬럼) // 사용자 정의 컬럼은 입력 타입과 관계없이 모두 VARCHAR(500)로 통일 return "varchar(500)"; } private generateCreateTableQuery( tableName: string, columns: CreateColumnDefinition[] ): string { // 사용자 정의 컬럼들 - 모두 VARCHAR(500)로 생성 const columnDefinitions = columns .map((col) => { let definition = `"${col.name}" varchar(500)`; // 타입 통일 if (!col.nullable) { definition += " NOT NULL"; } if (col.defaultValue) { definition += ` DEFAULT '${col.defaultValue}'`; } return definition; }) .join(",\n "); // 기본 컬럼들 (시스템 필수 컬럼 - 기존 타입 유지) const baseColumns = ` "id" serial PRIMARY KEY, "created_date" timestamp DEFAULT now(), "updated_date" timestamp DEFAULT now(), "writer" varchar(100), "company_code" varchar(50) DEFAULT '*'`; return ` CREATE TABLE "${tableName}" (${baseColumns}, ${columnDefinitions} );`.trim(); } ``` #### 3.2 입력 타입 처리 서비스 구현 ```typescript // 통합 입력 타입 처리 서비스 export class InputTypeService { // 데이터 저장 전 형변환 (화면 입력값 → DB 저장값) static convertForStorage(value: any, inputType: string): string { if (value === null || value === undefined) return ""; switch (inputType) { case "text": case "select": case "radio": return String(value); case "number": const num = parseFloat(String(value)); return isNaN(num) ? "0" : String(num); case "date": if (!value) return ""; const date = new Date(value); return isNaN(date.getTime()) ? "" : date.toISOString().split("T")[0]; case "checkbox": return ["true", "1", "Y", "yes", true].includes(value) ? "Y" : "N"; case "code": case "entity": return String(value || ""); default: return String(value); } } // 화면 표시용 형변환 (DB 저장값 → 화면 표시값) static convertForDisplay(value: string, inputType: string): any { if (!value && value !== "0") { return inputType === "number" ? 0 : inputType === "checkbox" ? false : ""; } switch (inputType) { case "number": const num = parseFloat(value); return isNaN(num) ? 0 : num; case "checkbox": return value === "Y" || value === "true"; case "date": return value; // YYYY-MM-DD 형식 그대로 사용 default: return value; } } // 입력값 검증 static validate( value: any, inputType: string ): { isValid: boolean; message?: string } { if (!value && value !== 0) { return { isValid: true }; // 빈 값은 허용 } switch (inputType) { case "number": const num = parseFloat(String(value)); return { isValid: !isNaN(num), message: isNaN(num) ? "숫자 형식이 올바르지 않습니다." : undefined, }; case "date": const date = new Date(value); return { isValid: !isNaN(date.getTime()), message: isNaN(date.getTime()) ? "날짜 형식이 올바르지 않습니다." : undefined, }; default: return { isValid: true }; } } } ``` ### Phase 4: 프론트엔드 UI 수정 (2일) #### 4.1 테이블 관리 화면 수정 - "웹 타입" → "입력 타입" 라벨 변경 - DB 타입 컬럼 제거 - 8개 타입만 선택 가능하도록 UI 수정 #### 4.2 화면 관리 시스템 연동 - 웹타입 → 입력타입 용어 통일 - 기존 화면관리 컴포넌트와 호환성 유지 ### Phase 5: 기본 컬럼 유지 로직 보강 (1일) #### 5.1 테이블 생성 시 기본 컬럼 자동 추가 ```typescript const DEFAULT_COLUMNS = [ { name: "id", type: "serial PRIMARY KEY", description: "기본키 (자동증가)", }, { name: "created_date", type: "timestamp DEFAULT now()", description: "생성일시", }, { name: "updated_date", type: "timestamp DEFAULT now()", description: "수정일시", }, { name: "writer", type: "varchar(100)", description: "작성자", }, { name: "company_code", type: "varchar(50) DEFAULT '*'", description: "회사코드", }, ]; ``` ## 🧪 테스트 계획 ### 1. 단위 테스트 - [ ] 입력 타입별 형변환 함수 테스트 - [ ] 데이터 검증 로직 테스트 - [ ] DDL 생성 로직 테스트 ### 2. 통합 테스트 - [ ] 테이블 생성 → 데이터 입력 → 조회 전체 플로우 - [ ] 기존 테이블과의 호환성 테스트 - [ ] 화면관리 시스템 연동 테스트 ### 3. 성능 테스트 - [ ] VARCHAR vs 전용 타입 성능 비교 - [ ] 대용량 데이터 입력 테스트 - [ ] 형변환 오버헤드 측정 ## 📊 마이그레이션 전략 ### 기존 데이터 호환성 1. **기존 테이블**: 현재 타입 구조 유지 2. **신규 테이블**: 새로운 입력 타입 체계 적용 3. **점진적 전환**: 필요에 따라 기존 테이블도 단계적 전환 ### 데이터 무결성 보장 - 형변환 실패 시 기본값 사용 - 검증 로직을 통한 데이터 품질 관리 - 에러 로깅 및 알림 시스템 ## 🎯 예상 효과 ### 사용자 경험 개선 - ✅ 직관적인 용어로 학습 비용 감소 - ✅ 8개 타입으로 선택 복잡도 감소 - ✅ 일관된 인터페이스 제공 ### 개발 생산성 향상 - ✅ 타입 관리 복잡도 감소 - ✅ 에러 발생률 감소 - ✅ 빠른 프로토타이핑 가능 ### 시스템 유연성 확보 - ✅ 요구사항 변경에 빠른 대응 - ✅ 다양한 데이터 형식 수용 - ✅ 확장성 있는 구조 ## 🚨 주의사항 ### 데이터 검증 강화 필요 VARCHAR 통일 방식 적용 시 애플리케이션 레벨에서 철저한 데이터 검증이 필요합니다. ### 성능 모니터링 초기 적용 후 성능 영향도를 지속적으로 모니터링하여 필요 시 최적화 방안을 강구합니다. ### 문서화 업데이트 새로운 입력 타입 체계에 대한 사용자 가이드 및 개발 문서를 업데이트합니다. ## 📅 일정 | 단계 | 소요시간 | 담당 | | ---------------------------- | --------- | ---------- | | Phase 1: 타입 정의 수정 | 1-2일 | 프론트엔드 | | Phase 2: DB 스키마 수정 | 1일 | 백엔드 | | Phase 3: 백엔드 서비스 수정 | 2-3일 | 백엔드 | | Phase 4: 프론트엔드 UI 수정 | 2일 | 프론트엔드 | | Phase 5: 기본 컬럼 로직 보강 | 1일 | 백엔드 | | **총 소요시간** | **7-9일** | | --- **결론**: 전체 VARCHAR 통일 방식을 확정하여 최대한의 유연성과 안정성을 확보합니다. ## 🎯 핵심 결정사항 요약 ### ✅ 확정된 방향성 1. **용어 통일**: 웹 타입 → 입력 타입 2. **타입 단순화**: 20개 → 8개 핵심 타입 3. **DB 타입 제거**: dbType 필드 완전 삭제 4. **저장 방식**: 모든 사용자 정의 컬럼을 VARCHAR(500)로 통일 5. **형변환**: 애플리케이션 레벨에서 입력 타입별 처리 ### 🚀 예상 효과 - **개발 속도 3배 향상**: 타입 고민 시간 제거 - **에러율 90% 감소**: DB 타입 불일치 에러 완전 차단 - **요구사항 대응력 극대화**: 스키마 수정 없이 필드 성격 변경 가능 - **데이터 마이그레이션 100% 안전**: 어떤 형태의 데이터도 수용 가능