(Android)라이브 업데이트 한다구요? 반드시 조심하세요

1

오늘은 내가 실수한것실수를 예뱡하기위해 리펙토링한 나의 과정을 제 2의 내가 될지 모르는 후배, 선배 개발자들에게 남기고자 한다.

라이브 업데이트를 왜쓰는거야?

App이 마켓배포를 안한다면 이유는 간단하다.
권한에 깐깐한 구글이 절대 금지하는 짓을 저지르는 어플이나, 정부기관에서 쓰는 어플일 경우다.
우리의 회사는 후자다.

이런 앱은 앱마켓에서 배포가 되지않기때문에 자사의 라이브 업데이트를 사용한다.

라이브업데이트 어떻게 하는거야? 🤨🤨

글을 싫어하는 여러분을 위해 Flow Chart를 그렸다.

대충 이런식으로 작동하고 라이브업데이트를 하고있는 회사도 별반 다르지 않을것이다.

그리고 이 프로세스에서 오류가 날 만한 곳은
1. text파일 다운로드 경로
2. 버전체크
3. APK다운로드 경로
였으며
에러처리까지 완벽히 되어있는줄 알았다. (왜 에러처리가 이따위인지 당장 가서 혼쭐내고싶다)

단위테스트가 필요한 이유.


		var iServerVersion = 0.0
		var iLocalVersion = 0.0

                    try {
                    //패키지 이름을 가져온다.
                        val pInfo: PackageInfo = mContext.getPackageManager().getPackageInfo(Utils.FORESTVIEW_PACKAGE_NAME, PackageManager.GET_META_DATA)
                        val sLocalVersion: String = String.valueOf(pInfo.versionName)

                        iServerVersion = Double.parseDouble(ServerVersion)
                        iLocalVersion = Double.parseDouble(sLocalVersion)
                    } catch ( e : PackageManager.NameNotFoundException) {
                        e.printStackTrace();
                    }

    				//가져온 패키지의 버전이 높다면
                    if (iServerVersion <= iLocalVersion) {
                        FileDownLoad = "N"
                        break;
                    }

이곳에서 Exception이 났다.
Exception처리는 했기 때문에 앱이 죽지는 않는다고 생각했지만 더 큰 문제는 다음이다.

		var iServerVersion = 0.0
		var iLocalVersion = 0.0

선언을 이렇게 했기때문에 Exception으로 들어올 경우, iServerVersion <= iLocalVersion이 똑같기 때문에 업데이트를 실행하지 않는것이다.

결과론적으로 이 앱의 최신버전을 다운받은 사람은 더이상 최신버전을 업데이트 할수 없다.
여기서 개발자는 항상 의심을 하고 살아야된다는것을 배웠다.
에러처리를 했을때, 이런 에러가 났다면? 이라며 단위테스트를 해봐야 한다.

X됐는데 어떡하죠??

만약 이앱을 수만명이 쓴다고 생각하자.
APK를 다시깔도록 메일을 보내야하는데 누가 버전을 업데이트 했는지 모른다면??
그렇다면 수만명에게 일일이 메일을 보내야 하는걸까?
다행이 우리회사 앱을 사용하는 인원이 적었기에(다행인건지 슬픈건지) 문제는 작았지만 이걸 예방하는 방법을 강구해내야 했다.

당장 고쳐야할것

일단 첫번재로는 exception의 개선이다.

		var iServerVersion = 0.1
		var iLocalVersion = 0.0

                    try {
                    //패키지 이름을 가져온다.
                        val pInfo: PackageInfo = mContext.getPackageManager().getPackageInfo(Utils.FORESTVIEW_PACKAGE_NAME, PackageManager.GET_META_DATA)
                        val sLocalVersion: String = String.valueOf(pInfo.versionName)

                        iServerVersion = Double.parseDouble(ServerVersion)
                        iLocalVersion = Double.parseDouble(sLocalVersion)
                    } catch ( e : PackageManager.NameNotFoundException) {
                        e.printStackTrace();
                        iServerVersion= 0.1
                    }

    				//가져온 패키지의 버전이 높다면
                    if (iServerVersion <= iLocalVersion) {
                        FileDownLoad = "N"
                        break;
                    }

0.0에서 0.1로 바꿔주고, 혹시나 Exception으로 들어올때 0.1로 선언을 한다면 해당 문제는 없다.
하지만 다른코드에서 이런일이 발생할수도 있기에(카카오에서도 에러는 비일비재하다더라)
업데이트한 사용자만 따로 추출해낼수 있다면 일은 좀더 쉽게 진행되었을것이다.
그렇다고 해서 개인정보 WAS를 구축하기엔 비용이 너무 많이든다.

그게 문제라면.. Cloud 서버를 사용하면 되지않을까?!

사용하자 FireStore


생각을 해보니 Google이 FirebaseFireStore을 밀어주고있었다.

FireStore란?

NoSQL 클라우드 데이터베이스로 데이터를 저장하고 동기화할수있다.
모든 클라이언트에서 실시간으로 데이터가 동기화되고 앱이 오프라인일 때도 데이터를 사용할 수 있다.

심지어 인증과 보안까지 FireStore가 알아서 관리 해주니 이처럼 괜찮은 선택지가 있을까?

그래서 이DB에 암호화된 핸드폰번호와 앱의 버전을 하나의 collection으로 만들었다.

보안상의 이유로 보여줄수는 없지만 이런식으로 만들었다.

결말은 언제나 해피엔딩

이렇게 나는 또하나의 문제를 일으켰으며,
썩 나쁘지않게 예방하였으니 나쁘지않은 경험이였다고 생각한다. 그럼.. 이만~! 😘

profile
쉽게 가르칠수 있도록 노력하자

0개의 댓글