# 테이블 타입 관리 개선 계획서

## 🎯 개선 목표

현재 테이블 타입 관리 시스템의 용어 통일과 타입 단순화를 통해 사용자 친화적이고 유연한 시스템으로 개선합니다.

## 📋 주요 변경사항

### 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/v2-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% 안전**: 어떤 형태의 데이터도 수용 가능
