Spring (Java) Version 비교 방법 - version4j
다양한 상황에서 버전 체크, 비교를 해야하는 경우가 존재한다.
git, 앱 버전, java, 자체 프로그램 버전 등등,,
1. Version 이란?
version 은 특정 매체에서 제작, 또는 수정이 이루어질때의 제작되거나, 수정된 각각의 판본을 뜻한다.
소프트웨어에서의 버전은 수정사항, 기능의 추가사항, 버그수정 등 다양한 작업이후 배포될때
각각의 의미에 맞는 버전을 올리고 배포 작업이 이루어 지게 된다.
Version 은 (.) dot(점) 을 기준으로 구분되며, 다음과 같은 순서에 의해 정의되어있다.
Major Version . Minor Version . Build or Maintenance Version = 1.0.1
- Major Version : 대대적인 변화가 있을때, 즉 자잘한 수정이 아닌 큰 변화가 있을때 수정된다.
- Minor Version: 주요 기능의 추가, 변경 즉 주요 컨텐츠가 변경이 되었을 때 주로 수정된다.
- Maintenance Version(Patch): 버그, 자잘한 수정등이 발생했을 경우 변경 되게 된다.
* 추가로 -beta, -alpha 와 같이 테스트버전임을 명시하는 경우도 존재한다.
2. Version 소숫점의 의미
Version 은 dot(점)으로 이루어져 있기 때문에 잦은 오해가 발생하고는 한다.
1.15.0 과 1.3.0 둘중에 어떤 버전이 더 높은 버전일까요 ?
정답은 1.15.0 버전입니다.
소숫점으로 버전을 생각한다면 1.3.0 버전이 좀더 높지만 버전은 소숫점이 아닌 숫자 그자체를 봐야 하게 되는것이다.
1.15와 1.3 으로 숫자로 읽는것이 아닌 15 vs 3 으로 인식하는게 쉬운 방법입니다.
그렇다면, 버전은 정수나, 실수형이 아닌 문자형 자료형이라고 생각 할 수 있습니다.
어떻게 버전을 비교하면 좋을지 생각해본후에 아래의 글을 확인해봅시다.
라이브러리를 통한 Version 비교
버전 비교에 대한 불편함이 이미 존재했었기 때문일까요, 버전비교에 대한 라이브러리가 존재한다.
docs(문서) 만 보더라도 얼추 어떻게 사용하면 될지 이해가 가는 간단한 라이브러리 이다.
https://github.com/kcthota/version4j
우리는 해당 라이브러리를 통해, 버전비교를 해볼 예정이다.
1. VersionCheckUtil Class
해당 라이브러리를 사용하여 버전 비교를 하는 간단한 유틸 클래스를 생성해보겠다.
/**
* Utility class for version check.
*/
public class VersionCheckUtil {
public static Map<String, Object> checkVersion(String clientVersion, String comparisonVersion) {
Map<String, Object> resultMap = new HashMap<>();
// 1. Check if the client version is null or empty.
if(StringUtils.isEmpty(clientVersion)) {
throw new IllegalArgumentException("Client version is null or empty.");
}
// 2. Check if the comparison version is null or empty.
if(StringUtils.isEmpty(comparisonVersion)) {
throw new IllegalArgumentException("Comparison version is null or empty.");
}
// 3. Compare the client version and the comparison version.
Version client = new Version(clientVersion);
Version comparison = new Version(comparisonVersion);
boolean result = comparison.greaterThan(client);
// 4. Set the result to the map.
resultMap.put("result", result);
resultMap.put("clientVersion", clientVersion);
resultMap.put("comparisonVersion", comparisonVersion);
resultMap.put("message", result ? "comparison version is Greater" : "client version is Greater or Version Check Failed");
return resultMap;
}
}
해당 클래스의 코드만 보더라도, 결과를 담는 map, null 체크를 제외하면 단 3줄만에 비교가 끝난다.
* " ", Null 의 경우 VersionNotValidException이 발생하지만 IllegalArgumentException으로 발생하기 위에 따로 잡았다.
2. Test Code
class VersionTest {
@Test
@DisplayName("1. Version Basic Use Test")
void use_1() {
String clientVersion = "1.0.0";
String comparisonVersion = "1.5.0";
Map<String, Object> resultMap = VersionCheckUtil.checkVersion(clientVersion, comparisonVersion);
System.out.println("resultMap = " + resultMap);
}
@Test
@DisplayName("2. Version Exception Use Test")
void use_2() {
String clientVersion = null;
String comparisonVersion = "";
String version = "1.0.0";
String targetVersion = "100001.0.0"; // VersionNotValidException
Assertions.assertThrows(IllegalArgumentException.class, () -> {
VersionCheckUtil.checkVersion(clientVersion, comparisonVersion);
});
Assertions.assertThrows(VersionNotValidException.class, () -> {
VersionCheckUtil.checkVersion(version, targetVersion);
});
}
@Test
@DisplayName("3. Version Special Case")
void use_3() {
String clientVersion = "2.0.0";
String comparisonVersion = "error?";
Map<String, Object> resultMap = VersionCheckUtil.checkVersion(clientVersion, comparisonVersion);
System.out.println("resultMap = " + resultMap);
}
}
3. 결과
우선 테스트 결과부터 확인 후에 간단히 설명하겠다.
version4j 의 문서에도 나와있듯이 각 버전을 체크 할 수 있는 메서드들이 존재하며
.greaterThan(), lessThan()과 같이 더 높거나, 낮은 버전을 확인 할 수 있다.
각 메서드의 return 값은 true, false 로 return 되게 된다.
여기서 테스트 결과의 콘솔을 자세히 봤다면 이상할 수 있는 부분이 존재한다.
바로 2.0.0 과 error? 라는 두가지의 String 을 비교했을때 Exception이 발생하는것이 아닌, false 가 return 되기 때문이다.
(해당 부분을 인지하여 비교전에 체크 하는게 좋을것 같다.)
그 외에 다른 테스트들을 보게 된다면, 값이 Null 이거나, " " 일때는 의도한대로 IllegalException 을 내려주는것을 확인 할 수 있다.
4. 라이브러리를 사용하지 않고 Java 로 비교
우선 다들 비슷한 생각을 했을거라고 생각한다.
파라미터로 받은 version 을 dot(점) 으로 split 한 후에, 각 자릿수를 int 로 변환 후 비교 와 같은 비슷한 방식일것이다.
public class VersionCheck {
/**
* Compare two versions.
*
* version1 이 version2 보다 높으면 = 1
* version1 이 version2 보다 낮으면 = -1
* version1 과 version2 가 같으면 = 0
*/
public static int compareVersions(String version1, String version2) {
String[] levels1 = version1.split("\\.");
String[] levels2 = version2.split("\\.");
int length = Math.max(levels1.length, levels2.length);
for (int i = 0; i < length; i++) {
int v1 = i < levels1.length ? Integer.parseInt(levels1[i]) : 0;
int v2 = i < levels2.length ? Integer.parseInt(levels2[i]) : 0;
if (v1 < v2) {
return -1;
}
if (v1 > v2) {
return 1;
}
}
return 0; // Versions are equal
}
public static void main(String[] args) {
String resultMsg;
String version1 = "2.1.0";
String version2 = "1.3.0";
int result = compareVersions(version1, version2);
System.out.println("result = " + result);
if (result < 0) {
resultMsg = "version1 is Less";
System.out.println(version1 + " is less than " + version2);
} else if (result > 0) {
resultMsg = "version1 is Greater";
System.out.println(version1 + " is greater than " + version2);
} else {
resultMsg = "versions are Equal";
System.out.println(version1 + " is equal to " + version2);
}
System.out.println("resultMsg = " + resultMsg);
}
}
- String 을 split . 점으로 분리
- 최대길이 계산 후 각 버전의 문자열을 순차 비교
- 구성요소가 없다면 0으로 간주 (1.3 은 1.3.0 으로 간주한다)
- 각 버전의 구성요소를 비교하여 크거나 작거나 값에 따라 결과 반환
- 모든 구성요소가 같을시 버전은 동등한것으로 간주.
버전 비교에 대해서 알아봤고, 더 많은 활용법이나 예외가 있을시에 내용에 추가 하도록 하겠습니다.
'Language > Java' 카테고리의 다른 글
[Java] var 키워드란? (간단예제포함) (0) | 2023.09.26 |
---|---|
[Java] ThreadLocal이란? - (ThreadLocal, InheritableThreadLocal) 설명 및 예제(테스트) (0) | 2023.03.07 |
[Java] Java 메모리 영역(stack, heap, static), JVM, JAVA 변수 종류 (2) | 2023.02.07 |
[Java] Java 컬렉션(Collection) (0) | 2023.02.01 |
[Java] Multi Thread를 이용한 간단 게임 구현(구구단) (0) | 2023.01.26 |
댓글