ERP-node/테이블_타입_관리_개선_계획서.md

473 lines
14 KiB
Markdown
Raw Normal View History

# 테이블 타입 관리 개선 계획서
## 🎯 개선 목표
현재 테이블 타입 관리 시스템의 용어 통일과 타입 단순화를 통해 사용자 친화적이고 유연한 시스템으로 개선합니다.
## 📋 주요 변경사항
### 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% 안전**: 어떤 형태의 데이터도 수용 가능