티스토리 뷰

혹시 Proguard로 난독화하고 릴리즈한 APK를 실험해보았는지 의심해보자!

혹시 Retrofit을 쓰고 있다면?


어제 오후 Google Play Store에 1차 배포를 완료한 후 신나게 퇴근하고 집에 들어와 배포 버전을 다운받으니 앱이 시작하자마자 죽어버리는 도저히 이해할 수 없는 일이 또 하나 늘었다.

앱은 그다지 복잡한 기능도 가지고 있지 않았고 심지어 켜자마자 인트로 페이지에서 죽어버려서 디버깅을 하느라 애를 먹었는데 

신기하게도 한번 죽고 나면 그 다음은 죽지 않고 인트로 페이지에서 멈춰 있었는데 (이때 초기에 세션 정리하는 로직이 서버로 아예 오지 않아 Retrofit을 의심했었는데! 바보같이!)

다행히 몇 시간의 삽질과 소 뒷걸음질치듯 우연찮게 건드려본 곳에서 원인을 발견했다.


일단 첫 번째 의심을 했던 부분은 Google의 Place API를 쓰고 있었는데 KEY를 릴리즈용으로 등록하지 않았나? 였는데 레퍼런스 다큐먼트와 튜토리얼 페이지를 다시 천천히 훑어가며 빼먹은 부분이 없나 샅샅이 뒤졌지만 여기서 문제가 생길리 없다는 결론을 얻었다.


두 번째는 에러 메시지를 일단은 확인해봐야겠다 싶어서 

그동안 배포버전에서 앱이 죽은 적은 없었기 때문에 한 번도 사용해보지 못했던 앱이 중지되었을 때 '신고'하는 기능을 사용하였는데 놀랍게도 몇 초안에 구글 플레이 콘솔에 '비정상 종료 및 ANR' 페이지로 에러 코드가 넘어오네! 

그런데 배포하기직전 proguard로 난독화를 시켜놔서 클래스고 메서드고 이름이 다 바뀌어 있어서 볼 수가 없어서 proguard를 풀고 릴리즈 APK를 만드는 상황까지 도달했다. 왜냐하면 디버깅용 APK는 무조건 문제가 없었기 때문에 일단은 릴리즈 시켜서 에러를 확인하자는 목적이었거든


아니 근데! 이번에는 실행이 잘 되는거다. 결국 여차저차 어쩌다 원인이 proguard라는 걸 발견했는데

문제는 앱에서 retrofit2를 쓰고 있었다는 것. 

사실 Retrofit 홈페이지에는 proguard를 위한 configuration에 대한 설명이 잘 나와있다.


나는 '일단 아직 배포는 멀었으니까 나중에 넣어야지' 라고 0.1초 생각하고 완전히 까먹고 있었는데 다행히 아무런 설정도 하지 않으면 빌드조차 할 수 없이 에러가 뜬다. 그래서 아무 생각없이 홈페이지의 설정 코드를 복붙한 게 문제였다.

Retrofit은 Json으로 데이터를 받아 자동으로 Model이라 하는 POJO형식의 클래스에 바인딩을 시키는데

proguard가 난독화를 시키는 바람에 바인딩이 되지 않았던 것이다...


놀랍게도 동일한 문제와 해결 방법을 쓴 블로거 한 분이 계셨고

http://bigmatch.i-um.net/2016/08/retrofit2-rxjava-proguard-settings/


위의 링크를 참고한

해결방법은 설정파일에 Model은 난독화가 되지 않도록 -keep 시키는 것이었다.

나는 Model과  Model안의 Inner Class까지 유지하기 위해 다음과 같이 설정을 추가했다.

-keep class 내패키지.model.** { *; }
-keepclassmembers class 내패키지.model.** { *; }

앱 패키지 명에 Model들은 모두 model 패키지 안에 있었기 때문에 이 패키지 안의 클래스들은 난독화 되지 않는다.

proguard 공식 홈페이지로 가면 그 외의 설정 문법들을 예제와 함께 설명해주고 있다.


배포할 때는 Proguard 가 Java Bytecode를 최적화시켜 앱을 최대 90퍼센트 크기를 줄이고 20퍼센트까지 빠르게 만들어 준다. 게다가 난독화 기술은 리버스 엔지니어링으로 얼마든지 실제 코드를 가질 수 있어 [그냥 배포할 경우 오픈 소스나 다름 없는] APK 파일을 보호해주는 최소한의 보호기술이라고 proguard 홈페이지에서 그렇게 말하고 있다. 

하지만 찾아보면서 proguard의 난독화와 문제를 빚는 라이브러리들이 꽤 있음을 알게 되었는데 그 중에서도 Retrofit은 몇 가지 클래스를 보존해주어야 하는 특별한 케이스에 속한다. proguard를 포기할 수는 없기 때문에 배포전에 이런 이슈들을 알고 있다면 적어도 한번은 릴리즈 키를 직접 설치해 검사해보도록 하자.


참고문헌

proguard, https://www.guardsquare.com/en/proguard

같은 문제 다른 해법, http://stackoverflow.com/questions/35506111/retrofit-2-not-sending-data-when-proguard-is-enabled


댓글