버전 관리 시스템 혁신: 4자리 버전 체계(MAJOR.MINOR.PATCH.BUILD) 도입, 규정 문서 작성 및 서버 시각 KST 적용
This commit is contained in:
parent
3ba4139eb6
commit
586e09c8af
54
docs/version manage.md
Normal file
54
docs/version manage.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# 📘 SMART IMS 버전 관리 규정 (Versioning Rules)
|
||||||
|
|
||||||
|
SMART IMS 플랫폼의 모든 배포와 업데이트는 아래의 **MAJOR.MINOR.PATCH.BUILD** 4자리 버전 관리 체계를 엄격히 준수합니다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1️⃣ MAJOR (첫 번째 자리)
|
||||||
|
**대규모 변경, 하위 호환성 붕괴**
|
||||||
|
|
||||||
|
- **의미**: 시스템의 근간이 바뀌거나 기존 데이터/연동 체계와의 호환성이 파괴될 때 증가합니다.
|
||||||
|
- **상황**: API 구조 전면 개편, 데이터베이스 아키텍처 변경, 통신 프로토콜 교체 등.
|
||||||
|
- **규칙**:
|
||||||
|
- 절대 자주 올리지 않으며, "제품의 세대 교체" 수준에서만 사용합니다.
|
||||||
|
- 사용자는 업데이트 전 반드시 호환성 여부를 검토해야 합니다.
|
||||||
|
- **예시**: `1.x.x.x` → `2.0.0.0`
|
||||||
|
|
||||||
|
## 2️⃣ MINOR (두 번째 자리)
|
||||||
|
**기능 추가, 호환성 유지**
|
||||||
|
|
||||||
|
- **의미**: 기존 시스템과 호환성을 유지하면서 새로운 기능이 추가되거나 UI가 대폭 개선될 때 증가합니다.
|
||||||
|
- **상황**: 신규 모듈 추가, 기존 기능 확장, 설정 옵션 대량 추가 등.
|
||||||
|
- **규칙**:
|
||||||
|
- 기능 단위의 주요 배포 시 사용합니다.
|
||||||
|
- 고객에게 "업데이트 권장" 수준의 변화를 의미합니다.
|
||||||
|
- **예시**: `1.2.x.x` → `1.3.0.0`
|
||||||
|
|
||||||
|
## 3️⃣ PATCH (세 번째 자리)
|
||||||
|
**버그 수정, 품질 개선**
|
||||||
|
|
||||||
|
- **의미**: 새로운 기능 추가 없이 기존 기능의 버그를 수정하거나 성능을 개선할 때 증가합니다.
|
||||||
|
- **상황**: 보안 패치, 성능 최적화, 로직 오류 수정 등.
|
||||||
|
- **규칙**:
|
||||||
|
- 기능 추가는 엄격히 금지됩니다.
|
||||||
|
- 긴급한 오류 수정 및 정기 유지보수 배포에 주로 사용됩니다.
|
||||||
|
- **예시**: `1.2.3.x` → `1.2.4.0`
|
||||||
|
|
||||||
|
## 4️⃣ BUILD / REVISION (네 번째 자리)
|
||||||
|
**빌드 번호 또는 미세 변경**
|
||||||
|
|
||||||
|
- **의미**: 사용자에게 기능적/시각적 변화를 거의 주지 않는 기술적 수정 시 증가합니다.
|
||||||
|
- **상황**:
|
||||||
|
- **빌드 번호**: CI/CD 파이프라인의 빌드 식별자.
|
||||||
|
- **핫픽스**: 오타 수정, 로그 문구 변경, 주석 업데이트 등.
|
||||||
|
- **규칙**:
|
||||||
|
- 사용자에게 "버전 변경 체감"을 주지 않는 수준의 작업입니다.
|
||||||
|
- 릴리스 노트(Changelog) 작성을 생략할 수 있습니다.
|
||||||
|
- **예시**: `1.2.3.45` (45번째 빌드)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 버전 비교 및 업데이트 공지 원칙
|
||||||
|
1. 플랫폼은 원격 저장소의 최신 태그 버전과 현재 설치된 버전의 **4자리를 순차적으로 비교**합니다.
|
||||||
|
2. 상위 자리수가 더 높을 경우 즉시 시스템 업데이트 안내를 발생시킵니다.
|
||||||
|
3. 모든 버전은 `v` 접두사를 포함하여 관리하나, 비교 시에는 숫자로 정규화하여 처리합니다.
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "smartims",
|
"name": "smartims",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.4.0",
|
"version": "0.4.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@ -361,13 +361,17 @@ initTables();
|
|||||||
const packageJson = require('./package.json');
|
const packageJson = require('./package.json');
|
||||||
|
|
||||||
app.get('/api/health', (req, res) => {
|
app.get('/api/health', (req, res) => {
|
||||||
|
// Force Korean time (UTC+9) for the timestamp
|
||||||
|
const kstOffset = 9 * 60 * 60 * 1000;
|
||||||
|
const kstDate = new Date(Date.now() + kstOffset);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
version: packageJson.version,
|
version: packageJson.version,
|
||||||
node_version: process.version,
|
node_version: process.version,
|
||||||
platform: process.platform,
|
platform: process.platform,
|
||||||
arch: process.arch,
|
arch: process.arch,
|
||||||
timestamp: new Date().toISOString().replace('T', ' ').split('.')[0]
|
timestamp: kstDate.toISOString().replace('T', ' ').split('.')[0]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"version": "0.4.0",
|
"version": "0.4.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -531,22 +531,26 @@ router.get('/version/remote', isAuthenticated, hasRole('admin'), async (req, res
|
|||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
|
|
||||||
// Version Comparison Helper
|
// Version Comparison Helper
|
||||||
const compareVersions = (v1, v2) => {
|
const parseV = (v) => (v || '').replace(/^v/, '').split('.').map(n => parseInt(n) || 0);
|
||||||
const parts1 = v1.split('.').map(Number);
|
const compare = (v1, v2) => {
|
||||||
const parts2 = v2.split('.').map(Number);
|
const p1 = parseV(v1);
|
||||||
for (let i = 0; i < 3; i++) {
|
const p2 = parseV(v2);
|
||||||
if (parts1[i] > parts2[i]) return 1;
|
// Compare up to 4 parts (MAJOR.MINOR.PATCH.BUILD)
|
||||||
if (parts1[i] < parts2[i]) return -1;
|
for (let i = 0; i < 4; i++) {
|
||||||
|
const n1 = p1[i] || 0;
|
||||||
|
const n2 = p2[i] || 0;
|
||||||
|
if (n1 > n2) return 1;
|
||||||
|
if (n1 < n2) return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Filter 1: History is ONLY versions <= current
|
// Filter 1: History is ONLY versions <= current
|
||||||
const history = allTags.filter(t => compareVersions(t.version, currentVersion) <= 0);
|
const history = allTags.filter(t => compare(t.version, currentVersion) <= 0);
|
||||||
|
|
||||||
// Filter 2: Latest is the absolute newest tag available (could be > current)
|
// Filter 2: Latest is the absolute newest tag available (could be > current)
|
||||||
const latestFromRemote = allTags[0] || null;
|
const latestFromRemote = allTags[0] || null;
|
||||||
const needsUpdate = latestFromRemote ? (compareVersions(latestFromRemote.version, currentVersion) > 0) : false;
|
const needsUpdate = latestFromRemote ? (compare(latestFromRemote.version, currentVersion) > 0) : false;
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
current: currentVersion,
|
current: currentVersion,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user