From 586e09c8afef1739952a3dcd851e61620d336571 Mon Sep 17 00:00:00 2001 From: choibk Date: Sun, 25 Jan 2026 01:18:42 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B2=84=EC=A0=84=20=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20=ED=98=81=EC=8B=A0:=204=EC=9E=90?= =?UTF-8?q?=EB=A6=AC=20=EB=B2=84=EC=A0=84=20=EC=B2=B4=EA=B3=84(MAJOR.MINOR?= =?UTF-8?q?.PATCH.BUILD)=20=EB=8F=84=EC=9E=85,=20=EA=B7=9C=EC=A0=95=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EC=84=9C?= =?UTF-8?q?=EB=B2=84=20=EC=8B=9C=EA=B0=81=20KST=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/version manage.md | 54 +++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- server/index.js | 6 ++++- server/package.json | 2 +- server/routes/system.js | 20 +++++++++------ 5 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 docs/version manage.md diff --git a/docs/version manage.md b/docs/version manage.md new file mode 100644 index 0000000..e6a0150 --- /dev/null +++ b/docs/version manage.md @@ -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` 접두사λ₯Ό ν¬ν•¨ν•˜μ—¬ κ΄€λ¦¬ν•˜λ‚˜, 비ꡐ μ‹œμ—λŠ” 숫자둜 μ •κ·œν™”ν•˜μ—¬ μ²˜λ¦¬ν•©λ‹ˆλ‹€. \ No newline at end of file diff --git a/package.json b/package.json index 84c6481..6cccfdf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "smartims", "private": true, - "version": "0.4.0", + "version": "0.4.0.0", "type": "module", "scripts": { "dev": "vite", diff --git a/server/index.js b/server/index.js index 10f9050..0954089 100644 --- a/server/index.js +++ b/server/index.js @@ -361,13 +361,17 @@ initTables(); const packageJson = require('./package.json'); 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({ status: 'ok', version: packageJson.version, node_version: process.version, platform: process.platform, arch: process.arch, - timestamp: new Date().toISOString().replace('T', ' ').split('.')[0] + timestamp: kstDate.toISOString().replace('T', ' ').split('.')[0] }); }); diff --git a/server/package.json b/server/package.json index dc436c0..b7fabc2 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "server", - "version": "0.4.0", + "version": "0.4.0.0", "description": "", "main": "index.js", "scripts": { diff --git a/server/routes/system.js b/server/routes/system.js index 1d6fed0..51c3795 100644 --- a/server/routes/system.js +++ b/server/routes/system.js @@ -531,22 +531,26 @@ router.get('/version/remote', isAuthenticated, hasRole('admin'), async (req, res }).filter(Boolean); // Version Comparison Helper - const compareVersions = (v1, v2) => { - const parts1 = v1.split('.').map(Number); - const parts2 = v2.split('.').map(Number); - for (let i = 0; i < 3; i++) { - if (parts1[i] > parts2[i]) return 1; - if (parts1[i] < parts2[i]) return -1; + const parseV = (v) => (v || '').replace(/^v/, '').split('.').map(n => parseInt(n) || 0); + const compare = (v1, v2) => { + const p1 = parseV(v1); + const p2 = parseV(v2); + // Compare up to 4 parts (MAJOR.MINOR.PATCH.BUILD) + 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; }; // 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) 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({ current: currentVersion,