9.7 KiB
9.7 KiB
카테고리 컴포넌트 DB 호환성 분석 및 수정
작성일: 2025-11-04
상태: 호환성 문제 발견 및 수정 완료
발견된 호환성 문제
1. 테이블명 불일치
| 예상 테이블명 | 실제 테이블명 | 상태 |
|---|---|---|
table_columns |
table_type_columns |
❌ 불일치 |
company_info |
company_mng |
❌ 불일치 |
2. 컬럼명 불일치
table_type_columns 테이블
| 예상 컬럼명 | 실제 컬럼명 | 상태 |
|---|---|---|
column_label |
존재하지 않음 | ❌ 불일치 |
web_type |
input_type |
❌ 불일치 |
column_order |
display_order |
❌ 불일치 |
company_code |
존재하지 않음 | ❌ 불일치 |
실제 table_type_columns 구조:
- id (integer, PK)
- table_name (varchar(255), NOT NULL)
- column_name (varchar(255), NOT NULL)
- input_type (varchar(50), NOT NULL, DEFAULT 'text')
- detail_settings (text)
- is_nullable (varchar(10), DEFAULT 'Y')
- display_order (integer, DEFAULT 0)
- created_date (timestamp, DEFAULT now())
- updated_date (timestamp, DEFAULT now())
company_mng 테이블
| 예상 컬럼명 | 실제 컬럼명 | 상태 |
|---|---|---|
company_code |
company_code |
✅ 일치 |
company_name |
company_name |
✅ 일치 |
실제 company_mng 구조:
- company_code (varchar(32), PK)
- company_name (varchar(64))
- writer (varchar(32))
- regdate (timestamp)
- status (varchar(32))
- business_registration_number (varchar(20))
- representative_name (varchar(100))
- representative_phone (varchar(20))
- email (varchar(255))
- website (varchar(500))
- address (varchar(500))
적용된 수정사항
1. 마이그레이션 파일 수정
파일: db/migrations/036_create_table_column_category_values.sql
변경사항:
-- 변경 전
CONSTRAINT fk_category_value_company FOREIGN KEY (company_code)
REFERENCES company_info(company_code),
-- 변경 후
CONSTRAINT fk_category_value_company FOREIGN KEY (company_code)
REFERENCES company_mng(company_code),
2. 백엔드 서비스 수정
파일: backend-node/src/services/tableCategoryValueService.ts
변경사항:
// 변경 전
const query = `
SELECT
tc.table_name AS "tableName",
tc.column_name AS "columnName",
tc.column_label AS "columnLabel",
COUNT(cv.value_id) AS "valueCount"
FROM table_columns tc
LEFT JOIN table_column_category_values cv
ON tc.table_name = cv.table_name
AND tc.column_name = cv.column_name
AND cv.is_active = true
AND (cv.company_code = $2 OR cv.company_code = '*')
WHERE tc.table_name = $1
AND tc.web_type = 'category'
AND (tc.company_code = $2 OR tc.company_code = '*')
GROUP BY tc.table_name, tc.column_name, tc.column_label, tc.column_order
ORDER BY tc.column_order, tc.column_label
`;
// 변경 후
const query = `
SELECT
tc.table_name AS "tableName",
tc.column_name AS "columnName",
tc.column_name AS "columnLabel", -- column_label이 없으므로 column_name 사용
COUNT(cv.value_id) AS "valueCount"
FROM table_type_columns tc -- table_columns → table_type_columns
LEFT JOIN table_column_category_values cv
ON tc.table_name = cv.table_name
AND tc.column_name = cv.column_name
AND cv.is_active = true
AND (cv.company_code = $2 OR cv.company_code = '*')
WHERE tc.table_name = $1
AND tc.input_type = 'category' -- web_type → input_type
GROUP BY tc.table_name, tc.column_name, tc.display_order -- column_order → display_order
ORDER BY tc.display_order, tc.column_name
`;
주요 차이점 분석
1. 멀티테넌시 방식
예상: 모든 테이블에 company_code 컬럼 존재
실제: table_type_columns에는 company_code 컬럼이 없음
영향:
- 카테고리 컬럼 조회 시 회사별 필터링 불가
- 모든 회사가 동일한 테이블 구조 사용
- 카테고리 값만 회사별로 분리됨 (의도된 설계로 보임)
결론: ✅ 정상 - 테이블 구조는 공통, 데이터만 회사별 분리
2. 라벨 관리
예상: table_columns.column_label 컬럼에 라벨 저장
실제: column_label 컬럼 없음
해결책:
- 현재는
column_name을 그대로 라벨로 사용 - 필요 시 향후
table_labels테이블과 JOIN하여 라벨 조회 가능
3. 타입 컬럼명
예상: web_type
실제: input_type
결론: ✅ 수정 완료 - input_type 사용으로 변경
테스트 계획
1. 마이그레이션 테스트
-- 1. 마이그레이션 실행
\i db/migrations/036_create_table_column_category_values.sql
-- 2. 테이블 생성 확인
SELECT table_name
FROM information_schema.tables
WHERE table_name = 'table_column_category_values';
-- 3. 외래키 제약조건 확인
SELECT
tc.constraint_name,
tc.table_name,
kcu.column_name,
ccu.table_name AS foreign_table_name,
ccu.column_name AS foreign_column_name
FROM information_schema.table_constraints AS tc
JOIN information_schema.key_column_usage AS kcu
ON tc.constraint_name = kcu.constraint_name
JOIN information_schema.constraint_column_usage AS ccu
ON ccu.constraint_name = tc.constraint_name
WHERE tc.table_name = 'table_column_category_values'
AND tc.constraint_type = 'FOREIGN KEY';
2. 카테고리 타입 컬럼 생성
먼저 테스트용 테이블에 카테고리 타입 컬럼을 추가해야 합니다:
-- 테스트용 projects 테이블이 없으면 생성
CREATE TABLE IF NOT EXISTS projects (
id SERIAL PRIMARY KEY,
project_name VARCHAR(200) NOT NULL,
project_type VARCHAR(50), -- 카테고리 타입
project_status VARCHAR(50), -- 카테고리 타입
priority VARCHAR(50), -- 카테고리 타입
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- table_type_columns에 카테고리 타입 등록
INSERT INTO table_type_columns (table_name, column_name, input_type, display_order)
VALUES
('projects', 'project_type', 'category', 1),
('projects', 'project_status', 'category', 2),
('projects', 'priority', 'category', 3)
ON CONFLICT DO NOTHING;
3. API 테스트
# 1. 카테고리 컬럼 목록 조회
curl -X GET http://localhost:8080/api/table-categories/projects/columns \
-H "Authorization: Bearer YOUR_TOKEN"
# 예상 응답:
# {
# "success": true,
# "data": [
# {
# "tableName": "projects",
# "columnName": "project_type",
# "columnLabel": "project_type",
# "valueCount": 4
# },
# {
# "tableName": "projects",
# "columnName": "project_status",
# "columnLabel": "project_status",
# "valueCount": 4
# },
# {
# "tableName": "projects",
# "columnName": "priority",
# "columnLabel": "priority",
# "valueCount": 4
# }
# ]
# }
# 2. 카테고리 값 목록 조회
curl -X GET http://localhost:8080/api/table-categories/projects/project_type/values \
-H "Authorization: Bearer YOUR_TOKEN"
# 예상 응답:
# {
# "success": true,
# "data": [
# {
# "valueId": 1,
# "valueCode": "DEV",
# "valueLabel": "개발",
# "color": "#3b82f6",
# ...
# }
# ]
# }
추가 고려사항
1. 라벨 표시 개선
현재는 columnName을 그대로 라벨로 사용하지만, 더 나은 사용자 경험을 위해 다음 개선 가능:
옵션 A: table_labels 테이블 활용
SELECT
tc.table_name AS "tableName",
tc.column_name AS "columnName",
COALESCE(tl.table_label, tc.column_name) AS "columnLabel",
COUNT(cv.value_id) AS "valueCount"
FROM table_type_columns tc
LEFT JOIN table_labels tl
ON tc.table_name = tl.table_name
LEFT JOIN table_column_category_values cv
ON tc.table_name = cv.table_name
AND tc.column_name = cv.column_name
WHERE tc.table_name = $1
AND tc.input_type = 'category'
GROUP BY tc.table_name, tc.column_name, tl.table_label, tc.display_order
ORDER BY tc.display_order;
옵션 B: detail_settings에서 라벨 추출
SELECT
tc.table_name AS "tableName",
tc.column_name AS "columnName",
COALESCE(
(tc.detail_settings::jsonb->>'label')::text,
tc.column_name
) AS "columnLabel"
FROM table_type_columns tc
WHERE tc.table_name = $1
AND tc.input_type = 'category';
2. input_type = 'category' 추가
현재 input_type에 'category' 값이 있는지 확인 필요:
-- 현재 사용 중인 input_type 확인
SELECT DISTINCT input_type
FROM table_type_columns
ORDER BY input_type;
만약 'category' 타입이 없다면, 기존 시스템에 추가해야 합니다.
호환성 체크리스트
데이터베이스
company_mng테이블 존재 확인table_type_columns테이블 구조 확인- 외래키 참조 수정 (
company_info→company_mng) input_type = 'category'추가 여부 확인- 테스트 데이터 삽입 확인
백엔드
- 테이블명 수정 (
table_columns→table_type_columns) - 컬럼명 수정 (
web_type→input_type) - 컬럼명 수정 (
column_order→display_order) - 라벨 처리 수정 (
column_label→column_name) - 멀티테넌시 로직 확인
프론트엔드
- API 응답 구조 확인
- 라벨 표시 테스트
- UI 테스트
결론
✅ 호환성 문제 수정 완료
주요 변경사항:
company_info→company_mng(외래키)table_columns→table_type_columns(테이블명)web_type→input_type(컬럼명)column_order→display_order(컬럼명)column_label→column_name(라벨 처리)
다음 단계:
- 마이그레이션 실행
- 테스트용 카테고리 컬럼 생성
- API 테스트
- 프론트엔드 테스트