본문 바로가기
Language/Java

[Java & Spring] Version 비교 방법 - version4j

by lucas_owner 2024. 6. 25.

 

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

 

GitHub - kcthota/version4j: Library to help compare major.minor.patch versions

Library to help compare major.minor.patch versions - kcthota/version4j

github.com

 

우리는 해당 라이브러리를 통해, 버전비교를 해볼 예정이다. 

 

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);
    }
}

 

  1. String 을 split . 점으로 분리
  2. 최대길이 계산 후 각 버전의 문자열을 순차 비교
  3. 구성요소가 없다면 0으로 간주 (1.3 은 1.3.0 으로 간주한다)
  4. 각 버전의 구성요소를 비교하여 크거나 작거나 값에 따라 결과 반환
  5. 모든 구성요소가 같을시 버전은 동등한것으로 간주. 

버전 비교에 대해서 알아봤고, 더 많은 활용법이나 예외가 있을시에 내용에 추가 하도록 하겠습니다.

반응형

댓글