요즘 회사에서 코틀린으로 어플을 만들고 있는데(정확히 말하면 수정이지만), 디버깅 모드로 테스트하던 어플이 릴리즈 모드를 통해 다른 회사 사람들에게 테스트용으로 전달했더니 여러가지 기능들이 먹히지 않는 문제를 발견했습니다.
기본적으로 이것저것 검색해본 결과로는 디버그 모드가 릴리즈 모드보다 디버깅 관련 데이터를 포함하면서 실행이 되기 때문에 속도 차이가 현저하다는 얘기들이 있습니다.
실제로 제가 안드로이드 apk 파일을 만들었을 때, 디버깅 모드는 11Mb, 릴리즈 모드는 8Mb 정도로 데이터 크기부터 차이가 나는 것을 확인했습니다.
속도나 다른 부분에서는 큰 용량의 데이터를 주고 받지 않는다면 크게 체감할 수 없지만, 휴대폰의 사양을 낮췄을 때는 휴대폰이 데이터를 받지 못해 프로그램을 꺼버리는 등의 문제가 확실히 생기는 부분입니다.
그리고 결정적으로 구글플레이나 앱스토어에서는 릴리즈 버전의 apk 파일만 전달받으니 디버깅 모드로 문제가 없다고 해서 어플리케이션 배포를 디버깅 모드로 할 수는 없겠죠.
결국 릴리즈 모드를 해야하는데, 이러한 릴리즈 모드로 apk 파일을 만들어 배포를 했을 때, 어플이 제대로 작동하지 않는 문제가 발생할 수 있습니다. 이러한 문제는 어플리케이션을 제작한 IDE별로도 다를 수 있고, 실제 어플의 어떤 부분에서 문제가 일어났는지 확인하기는 어렵다는 결론이 나왔습니다.
사실 회사에서 만든 배포용 어플이 겨우 코드 수천줄 정도에 수십개 정도의 클래스 정도로 가볍지는 않을 것이고, 그렇게 가볍다면 에러가 날 확률이 극악에 가까우니 말이죠.
만약 아직 에러가 나지 않았다면 안드로이드 프로젝트의 manifest에 들어가서
<application 속성 안에
android:debuggable="false" 라는 옵션을 넣어 디버깅 모드를 해제하고 틈틈히 코드를 진행해보는 것을 추천합니다. 그래야 릴리즈 모드에서 나오는 오류의 범위를 줄일 수 있으니까요.
하지만 이미 에러가 난 경우에는 어디서 문제가 났는지 메모장에 적힌 c언어 프로그램의 오류를 찾는 것처럼 IDE의 도움을 크게 기대하지 않고 찾아야 합니다. 그래도 프로그램이 꺼지는 문제라면 메모리 관련 이슈일 확률이 매우 높기 때문에 어디서 변수의 초기화가 제대로 이루어지지 않았는지, 혹은 과다 사용으로 인해 어디선가 메모리를 침범하지 않았는지 확인해볼 수 있습니다.
이러한 문제의 해결법이 하나라면 참 좋겠지만, 어플리케이션 마다 각각의 상호작용이 다르고 컴파일되는 방식이 다르기 때문에 명확하게 정답을 적어놓을 수는 없습니다. 하지만 결국 warning에서부터 하나하나 쳐다보면 분명 해결 방법을 찾을 수 있을 것입니다.
제목에 '그리고 proguard'라고 적혀져 있는 이유는 사실 제가 문제를 release 버전에서 발견했기 때문에 한참이나 debuging과 release의 차이점과 문제를 찾으려고 돌아다녔지만 제 문제는 release 버전을 만들면서 추가된 proguard 때문입니다.
proguard란 아래의 코드가 build.gradle 부분에 작성되어 있을 때 사용되는 것입니다.
buildTypes{
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
실제로 debug 모드에서도 proguard는 사용이 가능하지만 제가 받은 코드에서는 릴리즈 버전에서만 적용을 하고 있었습니다. 그래서 디버깅 모드에서는 proguard로 인해 생긴 문제점을 발견하지 못하고 코딩을 처리해서 릴리즈 버전에서 문제가 발생하게 되었죠.
이런 proguard는 기본적으로 미사용 클래스, 필드, 속성 등의 코드를 자르고 사용되지 않는 리소스등을 제거해 프로젝트의 전체적인 크기를 축소시키는 기능과 난독화라고 불리는, 클래스와 변수 등의 이름을 줄여 전체적인 크기를 줄이는 작업을 시행합니다. 특히 이 난독화는 코드를 읽기 어렵게 만들어 나중에 디컴파일시 어플리케이션의 코드를 카피하기 어렵게 만들어 주는 역할도 합니다.
점점 이런 기능들이 중요하게 여겨지지만, EventBus 라이브러리 처럼 IDE내에서 자체적으로 사용하지 않는 기능으로 판별하는 경우(실제로는 이벤트 버스 내에서 사용이 되지만), 이러한 과정에서 삭제시키기 때문에 미리 @keep 주석이나 -keep을 통해서 라이브러리 및 클래스를 유지시키는 작업이 필요합니다. 이러한 기능은 숙련도가 충분히 높아진 이후, 혹은 공부를 좀 더 해서 사용을 하는 것이 중요합니다.
그리고 gradle의 버전이 점점 높아지면서 proguard는 또 다시 R8과 같은 것들로 진화를 거듭하고 있으니 비슷한 기능이 다른 이름으로 작동하고 있는지도 잘 파악해서 코드의 오류를 고쳐야 할 것입니다.
'안드로이드 > 코틀린' 카테고리의 다른 글
(android-jetpack)AAC에서의 뷰모델 (0) | 2021.03.30 |
---|---|
(android - jetpack)데이터 바인딩 작업 (0) | 2021.03.22 |
(android) 스플래시 화면 만들기 (0) | 2021.03.11 |
Kotlin으로 만든 커스텀 버튼 (0) | 2021.02.09 |
Gson과 JSON의 toString (0) | 2021.01.23 |
댓글