오늘은 막 입사하여 코드 분석 중에 발생한 일을 다룰려고 한다.
신입 개발자로 정신없이 업무를 하던 중, 앱 버전 체크 코드를 발견했다.
val nowVersion = 1.1.1.split(".")
val updateVersion = 1.1.2.split(".")
val lastestVersion = 1.1.3.split(".")
for(i in 0..2){
if(nowVersion[i] < updateVersion[i]){
println("업데이트 안하면 사용 못함 ㅋㅋ")
}
if(nowVersion[i] < lastestVersion[i]){
println("새 버전 나옴")
}
}
대략 이런 모양이였는데
나에겐 이 코드가 비효율적으로 보였다..ㅜㅜ
하나하나 비교하는게 안좋게 보였던 것 같다.
어떻게 하면 더 쉽게 동작할 수 있을까 고민하던 중
문자열 크기 비교 방법을 찾았다.
val nowVersion = 1.1.1
val updateVersion = 1.1.2
val lastestVersion = 1.1.3
if(nowVersion < updateVersion){
println("업데이트 안하면 사용 못함 ㅋㅋ")
}else if(nowVersion < lastestVersion){
println("새 버전 나옴")
}
실제로 println("1.1.1" < "1.1.2") 출력 시 true가 나오는 것 처럼
훨씬 간단하고 직관적이라 도입해볼 수 있을 것 같아서 사수님께 도입하자고 말씀드릴 계획이였다.
그 전에 원리를 파악해보려고 검색을 해보았다.
그런데!!!!!!!!!
사실 이 방법은 매우매우 위험한 방법이였고, 도입했다면 난리가 났을 것 같다ㅠㅠ
(사용자 화면에 업데이트 문구가 마구마구 뜰뻔함..)
그 이유를 알아보자..!!
val nowVersion = 1.1.1
val updateVersion = 1.1.2
println(nowVersion < updateVersion) // true
val nowVersion = 1.1.100000
val updateVersion = 1.5.1
println(nowVersion < updateVersion) // true
다음 코드는 예상대로 동작한다.
짧게 테스트 했을 때, 잘 동작한다고 생각해서 대참사 날 뻔...
어떻게 문자열을 비교할까??
비교 연산자(<, >)를 ctrl 누른 상태로 타고 들어가보자.
그럼 String.kt 에 다음과 같은 함수로 연결된 것을 확인할 수 있다.

또 이 함수의 인터페이스를 확인해보면 여기까지 도달 할 수 있다.

이 인터페이스를 어디선가 상속받고 구현한게 있을텐데,
잘 안나와서 찾지 못하였다ㅠㅠ
(구현체 위치 아시는분은 댓글 부탁드려용)
우리가 알고싶었던 함수의 기능은 다음과 같다.
String.compareTo(String)
두 문자열이 있을 때,
맨 앞부터 각 각 하나씩 Char 형으로 변환하여 ASCII 코드 값으로 비교하는 방식이다.
같다면 0을,
다르면 길이의 차이만큼 Int 값을 반환해준다.
위에서 사용했던 코드를 바꿔보면 다음과 같다.
val nowVersion = 1.1.1
val updateVersion = 1.1.2
//println(nowVersion < updateVersion) // true
println(nowVersion.compareTo(updateVersion)) // true
A.compareTo(B)를 사용하면 Int 값을 뱉고
비교 연산자를 사용할 경우 같고 다름만 판단하여 Boolean 값을 뱉는 것으로 보인다.
val nowVersion = 1.1.1
val updateVersion = 1.1.2
println(nowVersion < updateVersion) // true
val nowVersion = 1.1.100000
val updateVersion = 1.5.1
println(nowVersion < updateVersion) // true
다음과 같은 코드는 잘 비교되지만,
string.compareTo(string)은 맨 앞부터 하나하나 Char 형으로 변환하여 ASCII 코드로 비교한다고 했다.
val nowVersion = 1.1.10
val updateVersion = 1.1.5
println(nowVersion < updateVersion) // false
분명 nowVersion 의 버전이 더 높으나
앞부터 하나 하나 비교할 경우 컴퓨터는 updateVersion 이 더 높다고 인식한다.
이걸 상용앱에 도입했다간 정말이지 아찔할뻔..ㅠㅠㅠㅠㅠ
무엇이든 원리를 파악하고 사용하자!!
안그럼 짤린다!