변경 이력 (changeLog)
프리셋 버전 업데이트 시 변경 내용을 명시적으로 선언하는 문법입니다. 자동 diff 엔진의 감지 정확도를 높이고, 특히 컬럼 이름변경(rename) 감지에 필수적입니다.
구조
{
"changeLog": [
{
"version": "2.0.0",
"date": "2026-03-09",
"summary": "변경 요약 설명",
"changes": [
{
"type": "column_added",
"tableRef": "hcm_work_orders",
"columnName": "total_amount",
"description": "작업지시 총금액 자동 계산 컬럼 추가"
}
]
}
]
}
ChangeLogEntry 필드
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
version | string | 필수 | 변경 대상 버전 (시맨틱 버전) |
date | string | 필수 | 변경 일자 (ISO 8601: YYYY-MM-DD) |
summary | string | 필수 | 변경 요약 설명 |
changes | array | 필수 | 개별 변경 항목 배열 (최소 1개) |
ChangeItem 필드
v2.1.0: Discriminated Union 패턴 --
type별로 필수 필드가 TypeScript 컴파일 타임에 보장됩니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
type | string | 필수 | 변경 유형 (아래 표 참조) |
tableRef | string | 조건부 | 대상 테이블 refId (테이블/컬럼 변경 시 필수) |
columnName | string | 조건부 | 대상 컬럼명 (컬럼 변경 시 필수) |
screenRef | string | 조건부 | 대상 화면 refId (화면 변경 시 선택) |
description | string | 필수 | 변경 설명 |
detail | object | 조건부 | 세부 변경 내용 (유형별 상이) |
변경 유형 (type) -- 17개
| type | 설명 | tableRef | columnName | detail | v2.1.0 신규 |
|---|---|---|---|---|---|
table_added | 테이블 신규 추가 | 필수 | -- | -- | |
table_removed | 테이블 삭제 | 필수 | -- | -- | |
table_renamed | 테이블 이름변경 | 필수 | -- | 필수 (kind: "table_rename") | v |
column_added | 컬럼 추가 | 필수 | 필수 | -- | |
column_removed | 컬럼 삭제 | 필수 | 필수 | -- | |
column_renamed | 컬럼 이름 변경 | 필수 | 필수 (새 이름) | 필수 (kind: "rename") | |
column_type_changed | 컬럼 타입 변경 | 필수 | 필수 | 필수 (kind: "type_change") | |
column_modified | 컬럼 속성 변경 | 필수 | 필수 | 권장 (kind: "property_change") | |
relationship_added | 관계 추가 | -- | -- | 권장 (kind: "relationship") | |
relationship_removed | 관계 삭제 | -- | -- | 권장 (kind: "relationship") | |
relationship_modified | 관계 유형 변경 | -- | -- | 필수 (kind: "relationship_modify") | v |
screen_added | 화면 추가 | 선택 | -- | -- | |
screen_modified | 화면 수정 | 선택 | -- | -- | |
screen_removed | 화면 삭제 | -- | -- | -- | |
workflow_changed | 워크플로우 변경 | -- | -- | -- | v |
seed_data_updated | 시드 데이터 변경 | 필수 | -- | -- | |
config_changed | 설정 변경 | -- | -- | -- |
참고:
screen_added/screen_modified에는screenRef(화면 refId)를 선택적으로 포함할 수 있으며,tableRef는 화면이 바인딩된 테이블 refId입니다.
detail 객체
컬럼 이름변경 (kind: "rename")
{
"type": "column_renamed",
"tableRef": "hcm_items",
"columnName": "unit_cost",
"description": "단가 컬럼명 변경",
"detail": {
"kind": "rename",
"oldName": "price",
"newName": "unit_cost",
"dataMigration": true
}
}
| 필드 | 타입 | 설명 |
|---|---|---|
kind | "rename" | 고정값 |
oldName | string | 이전 컬럼명 (이전 버전 테이블에 존재해야 함) |
newName | string | 새 컬럼명 (현재 tables에 존재해야 함) |
dataMigration | boolean | 데이터 마이그레이션 필요 여부 |
컬럼 타입변경 (kind: "type_change")
{
"type": "column_type_changed",
"tableRef": "hcm_bom_items",
"columnName": "quantity",
"description": "수량 정밀도 향상",
"detail": {
"kind": "type_change",
"oldType": "INT",
"newType": "DECIMAL",
"dataMigration": true,
"migrationHint": "INT → DECIMAL 자동 변환 가능. 소수점 없는 값에 .00 추가"
}
}
| 필드 | 타입 | 설명 |
|---|---|---|
kind | "type_change" | 고정값 |
oldType | string | 이전 컬럼 타입 |
newType | string | 새 컬럼 타입 |
dataMigration | boolean | 데이터 마이그레이션 필요 여부 |
migrationHint | string | 선택 -- 마이그레이션 가이드 |
테이블 이름변경 (kind: "table_rename") -- v2.1.0 신규
{
"type": "table_renamed",
"tableRef": "hcm_materials",
"description": "원자재 테이블 이름변경",
"detail": {
"kind": "table_rename",
"oldRefId": "hcm_raw_materials",
"newRefId": "hcm_materials",
"oldTableName": "hcm_raw_materials",
"newTableName": "hcm_materials",
"dataMigration": true
}
}
| 필드 | 타입 | 설명 |
|---|---|---|
kind | "table_rename" | 고정값 |
oldRefId | string | 이전 테이블 refId |
newRefId | string | 새 테이블 refId |
oldTableName | string | 이전 테이블명 |
newTableName | string | 새 테이블명 |
dataMigration | boolean | 데이터 마이그레이션 필요 여부 |
범용 속성 변경 (kind: "property_change")
v2.1.0: 기존
constraint_change를 대체하는 범용 속성 변경 상세 타입
{
"type": "column_modified",
"tableRef": "hcm_items",
"columnName": "item_code",
"description": "품목코드에 UNIQUE 추가",
"detail": {
"kind": "property_change",
"property": "constraints",
"oldValue": ["NOT_NULL"],
"newValue": ["NOT_NULL", "UNIQUE"],
"dataMigration": false
}
}
| 필드 | 타입 | 설명 |
|---|---|---|
kind | "property_change" | 고정값 |
property | string | 변경된 속성명 (constraints, defaultValue, isComputed, fkRef 등) |
oldValue | any | 이전 값 (선택) |
newValue | any | 새 값 (선택) |
dataMigration | boolean | 데이터 마이그레이션 필요 여부 |
관계 추가/삭제 (kind: "relationship")
{
"type": "relationship_added",
"description": "출하 → 판매오더 관계 추가",
"detail": {
"kind": "relationship",
"sourceRef": "hcm_shipments",
"targetRef": "hcm_sales_orders",
"relationType": "1:N"
}
}
| 필드 | 타입 | 설명 |
|---|---|---|
kind | "relationship" | 고정값 |
sourceRef | string | 소스 테이블 refId |
targetRef | string | 타겟 테이블 refId |
relationType | string | "1:1" | "1:N" | "M:N" |
관계 유형 변경 (kind: "relationship_modify") -- v2.1.0 신규
{
"type": "relationship_modified",
"description": "BOM ↔ 공정 관계 유형 변경 (1:N → M:N)",
"detail": {
"kind": "relationship_modify",
"sourceRef": "hcm_bom",
"targetRef": "hcm_processes",
"oldRelationType": "1:N",
"newRelationType": "M:N",
"dataMigration": true,
"migrationHint": "중간 테이블 자동 생성, 기존 FK 데이터 이관 필요"
}
}
| 필드 | 타입 | 설명 |
|---|---|---|
kind | "relationship_modify" | 고정값 |
sourceRef | string | 소스 테이블 refId |
targetRef | string | 타겟 테이블 refId |
oldRelationType | string | 이전 관계 유형 ("1:1" | "1:N" | "M:N") |
newRelationType | string | 새 관계 유형 ("1:1" | "1:N" | "M:N") |
dataMigration | boolean | 데이터 마이그레이션 필요 여부 |
migrationHint | string | 선택 -- 마이그레이션 가이드 |
규칙
| # | 규칙 |
|---|---|
| CL-1 | changeLog는 선택적 필드. 없으면 자동 diff 엔진만으로 감지 |
| CL-2 | 배열 순서는 최신 버전 우선 (내림차순): [v2.0.0, v1.1.0] |
| CL-3 | 각 엔트리의 version은 루트 version 이하여야 함 |
| CL-4 | date는 ISO 8601 형식 (YYYY-MM-DD) |
| CL-5 | changes 배열은 빈 배열 불가 -- 최소 1개 변경 항목 필요 |
| CL-6 | column_renamed 시 detail.oldName은 이전 버전에 존재해야 하고, detail.newName은 현재 tables에 존재해야 함 |
| CL-7 | column_type_changed 시 detail.oldType은 이전 버전 타입과 일치해야 함 |
| CL-8 | dataMigration: true 시 migrationHint 권장 |
| CL-9 | 하나의 컬럼에 여러 변경은 개별 항목으로 분리 (이름+타입 동시 → 2개 항목) |
| CL-10 | column_removed된 FK 컬럼의 관련 relationship 변경도 함께 선언 권장 |
| CL-11 | 최근 3개 major 버전의 changeLog만 유지. 이전 버전은 CHANGELOG.md로 아카이브 |
자동 Diff와의 상호작용
| 상황 | 동작 |
|---|---|
| changeLog에 명시적 선언 있음 | changeLog 우선 |
| changeLog에 없는 변경 감지됨 | 자동 diff 결과 사용 |
| changeLog와 자동 diff 결과 충돌 | changeLog 우선 + 경고 로그 |
| changeLog 검증 실패 | changeLog 무시 + 자동 diff 폴백 (안전 모드) |
특히 컬럼 이름변경 감지에서 changeLog가 중요합니다:
- 자동 diff는
displayName + type일치로 rename을 추측 (정확도 낮음) - changeLog의
column_renamed가 있으면 명시적 매핑으로 정확하게 감지
완전한 예제
{
"key": "hicumag_smart_factory",
"version": "2.0.0",
"displayName": "하이큐마그 스마트팩토리",
"changeLog": [
{
"version": "2.0.0",
"date": "2026-03-09",
"summary": "제조 흐름 분석 반영: 자동 계산 컬럼, 자동 채번, 소스 문서 끌고오기",
"changes": [
{
"type": "column_added",
"tableRef": "hcm_work_orders",
"columnName": "total_amount",
"description": "작업지시 총금액 자동 계산 컬럼"
},
{
"type": "column_renamed",
"tableRef": "hcm_items",
"columnName": "unit_cost",
"description": "단가 컬럼명 변경 (price → unit_cost)",
"detail": {
"kind": "rename",
"oldName": "price",
"newName": "unit_cost",
"dataMigration": true
}
},
{
"type": "column_type_changed",
"tableRef": "hcm_bom_items",
"columnName": "quantity",
"description": "수량 정밀도 향상 (INT → DECIMAL)",
"detail": {
"kind": "type_change",
"oldType": "INT",
"newType": "DECIMAL",
"dataMigration": true,
"migrationHint": "INT → DECIMAL 변환, 기존 데이터 자동 변환 가능"
}
},
{
"type": "table_renamed",
"tableRef": "hcm_materials",
"description": "원자재 테이블 이름변경",
"detail": {
"kind": "table_rename",
"oldRefId": "hcm_raw_materials",
"newRefId": "hcm_materials",
"oldTableName": "hcm_raw_materials",
"newTableName": "hcm_materials",
"dataMigration": true
}
},
{
"type": "relationship_modified",
"description": "BOM ↔ 공정 관계 유형 변경 (1:N → M:N)",
"detail": {
"kind": "relationship_modify",
"sourceRef": "hcm_bom",
"targetRef": "hcm_processes",
"oldRelationType": "1:N",
"newRelationType": "M:N",
"dataMigration": true,
"migrationHint": "중간 테이블 자동 생성, 기존 FK 데이터 이관 필요"
}
},
{
"type": "relationship_added",
"description": "출하 → 판매오더 관계 추가",
"detail": {
"kind": "relationship",
"sourceRef": "hcm_shipments",
"targetRef": "hcm_sales_orders",
"relationType": "1:N"
}
},
{
"type": "workflow_changed",
"description": "출하 승인 워크플로우 3단계로 확장"
}
]
},
{
"version": "1.1.0",
"date": "2026-02-15",
"summary": "BOM 관리 개선",
"changes": [
{
"type": "column_added",
"tableRef": "hcm_bom_items",
"columnName": "scrap_rate",
"description": "BOM 아이템 스크랩 비율 컬럼 추가"
}
]
}
],
"tables": [],
"relationships": []
}
검증 체크리스트
changeLog 검증은 2계층 전략으로 구성됩니다. L1(구조)은 JSON Schema로, L2(의미)는 런타임 검증기(changelog-validator.ts)로 검증합니다.
L1: 구조 검증 (JSON Schema)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"type": "object",
"required": ["version", "date", "summary", "changes"],
"properties": {
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
"date": { "type": "string", "format": "date" },
"summary": { "type": "string", "minLength": 1 },
"changes": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["type", "description"],
"properties": {
"type": {
"enum": [
"table_added",
"table_removed",
"table_renamed",
"column_added",
"column_removed",
"column_renamed",
"column_type_changed",
"column_modified",
"relationship_added",
"relationship_removed",
"relationship_modified",
"screen_added",
"screen_modified",
"screen_removed",
"workflow_changed",
"seed_data_updated",
"config_changed"
]
}
}
}
}
}
}
}
-
changeLog배열이 최신 버전 우선 내림차순인가? - 각 엔트리에
version,date,summary,changes필수 필드가 있는가? -
changes배열이 비어있지 않은가? (최소 1개) -
type이 17개 유효값 중 하나인가? -
version형식이 시맨틱 버전 (X.Y.Z)인가?
L2: 의미 검증 (런타임)
런타임 검증기는 packages/shared/src/solutions/changelog-validator.ts에 구현되어 있으며, CL-2~CL-12 규칙을 모두 검증합니다. 검증 실패 시 changeLog를 무시하고 자동 diff로 폴백 (안전 모드)합니다.
-
column_renamed의detail.oldName이 이전 버전 테이블에 존재하는가? -
column_renamed의detail.newName이 현재tables에 존재하는가? -
column_renamed의columnName === detail.newName인가? (CL-6) -
column_type_changed의oldType/newType이 실제 버전과 일치하는가? -
table_renamed의oldRefId가 이전 버전에 존재하는가? -
table_renamed/relationship_modified의dataMigration이true인가? (CL-12) -
column_removed된 FK 컬럼의 관련 relationship 변경도 선언되었는가? (CL-10) -
dataMigration: true인 항목에migrationHint가 있는가? (CL-8) -
screen_*변경에screenRef또는tableRef중 최소 하나가 있는가? (CL-6b) - 최근 3개 major 버전의 changeLog만 유지되고 있는가? (CL-11)
도구 지원
changeLog를 수동으로 작성하는 것은 비현실적입니다. 아래 도구를 활용하세요.
| 도구 | 용도 |
|---|---|
pnpm preset:diff <old.json> <new.json> | 두 버전 비교 후 changeLog 초안 자동 생성 |
pnpm preset:validate | changeLog 포함 전체 프리셋 L1+L2 검증 |
| VSCode JSON Schema | 자동완성 + 인라인 검증 지원 |
구현 현황
v2.1.0 기준 — 모든 구성 요소 구현 완료
| 구성 요소 | 파일 | 상태 |
|---|---|---|
| 타입 정의 (17개 discriminated union) | packages/shared/src/solutions/types.ts | ✅ |
| 검증기 (CL-2~CL-12) | packages/shared/src/solutions/changelog-validator.ts | ✅ |
| 선택적 적용 엔진 | packages/shared/src/solutions/solution-differ-selective.ts | ✅ |
| 업데이트 상태 관리 | packages/frontend/.../store/presetUpdateSlice.ts | ✅ |
| 3단계 프로그레시브 디스클로저 UI | packages/frontend/.../dialogs/PresetUpdateModal.tsx | ✅ |
| 업데이트 알림 배너 | packages/frontend/.../PresetUpdateBanner.tsx | ✅ |
| 캔버스 통합 (자동 감지 + 읽기전용) | packages/frontend/.../CanvasEditor.tsx | ✅ |
이전: 검증과 예제 | 처음으로: 프리셋 JSON 문법 규정집