안드로이드 앱 사이즈 50% 감소를 이뤄낸 이야기

참조 기기 기준 22.7MB였던 앱이 6개월 만에 10.8MB가 되었다. 무려 절반 이상 가까이 감소한 수치이다. 어떻게 앱 사이즈가 이렇게 줄어들 수 있었는지 소개한다.

안드로이드 앱 사이즈 50% 감소를 이뤄낸 이야기
반년 만에 참조 기기 기준 22.7MB에서 10.8MB로 절반 이상 감소

지난 2022년 11월 참조 기기 기준 22.7MB였던 앱이 반년 만에 10.8MB가 되었다. 무려 절반 이상 가까이 감소한 수치이다. 어떻게 앱 사이즈가 이렇게 줄어들 수 있었는지 3가지 사건(?)과 앱 사이즈에 대한 개인적인 생각을 작성했다.

채널톡 sdk 제거

채널톡은 고객과의 커뮤니케이션을 도와주는 서비스이며, 최근 접한 서비스들 중 채널톡을 사용하지 않는 곳을 본 적이 없을 정도로 널리 사랑받고 있는 제품이다. 우리도 역시 채널톡을 이용하며 편리한 환경 속에서 구매 전환을 이끌어내고 원활하게 고객과 소통 할 수 있었다.

그러나 채널톡 sdk와 관련하여 몇몇 이슈를 겪으며 문제점을 느끼게 되었다.

Jetifier 관련 이슈

내가 처음으로 채널톡 sdk에 관심을 가지게된 사소한 이슈가 있었다. 채널톡에서 사용하는 ExoPlayer의 버전이 오래되어 생기는 문제였고, 제보를 통해 현재는 개선이 되었다.

22년 11월, 10.0.6 버전에서 해결

성능 이슈(?)

Compose의 baseline profile을 적용하며 Macrobenchmark module을 만들고 앱 시작 시간을 측정하던 중 채널톡 sdk가 시간을 많이 잡아먹는다는 사실을 발견했다. 실제로 sdk를 제거하고 비교해보니 950ms -> 450ms로 적지 않은 비중을 차지하고 있었다.

개인적으로 performance 측정 결과는 숫자에 불과하다고 생각한다. 그럼에도 불구하고 안드로이드에서 제공하는 도구를 통해 측정된 결과의 절반 이상을 차지한다는건 눈여겨 볼 필요가 있었다.

생각보다 큰 라이브러리 사이즈, 그리고 난독화

아래는 채널톡 sdk 문서의 proguard rule인데 모든 라이브러리 코드를 keep하도록 되어 있었다.

-keep class com.zoyi.**{ *; } 
-keep class io.channel.**{ *; } 
-dontwarn com.zoyi.** 
-dontwarn io.channel.**

당시 가장 최근 빌드된 apk의 class.dex 파일로부터 com.zoyi , io.channel package를 찾았는데 각각 3.2MB, 2MB에 달했다.

결론은 WebView

WebView 가이드와 javascript sdk 문서, @JavascriptInterface로 구현한 결과물

그 뒤 채널톡 문의를 통해 1) lazy한 초기화 2) 난독화 등에 대해 이야기를 나누었다. 고객사가 많다보니 쉽게 변경될 수 있는 부분이 아니라는 생각이 들었고 다른 대체 수단을 찾아보게 되었다.

그 결과, 잘 작성되어있는 채널톡의 문서를 보고 WebView와 채널톡 javascript sdk를 사용, 나만의 채널톡 lite sdk를 만들 수 있었다. 또한@JavascriptInterface를 통해 sdk를 사용할 때와 같이 고객 정보(이름, 연락처, 이메일, userAgent 등)를 잘 전달 할 수 있었다.

3.2MB(com.zoyi.*) + 2MB(io.channel.*) = 5.2MB여야하는데…🤔

위와 같은 과정을 통해 채널톡 sdk를 제거, 앱 용량은 3.2MB정도 감소했다.

R8 Full mode 적용

R8 Full mode를 적용하게 되었는데, 구글 문서에서는 R8 Full mode를 More aggressive optimization 이라 표현한다. 그에 걸맞게 안쓰이는 내부 코드가 많이 제거되었다. Play Console에서 apk를 다운로드 받아 비교해보니 Jetpack, Play Service, Firebase 와 같은 라이브러리들의 용량이 많이 감소했다.

앱 사이즈는 최종적으로 4.2MB 가량 줄어들었다.

난독화는 runtime 오류를 일으키는 범인 중 하나인데 적용하던 중 써드파티 라이브러리들에서 문제가 발생했고, 공식 FAQ를 포함하여 여러 라이브러리 github repository 내 issue 등을 참고하여 문제를 해결했다.

Azure Storage sdk for android (feat. ktor)

내가 개발하던 서비스는 파일 저장소로 Azure Storage를 사용한다. 대용량 파일을 업로드하기 위해서는 파일을 조각내어 따로 업로드 한 뒤 뭔가 별도로 처리를 해주어야한다는 이야기를 듣고 ‘이건 sdk를 무조건 써야겠다…’라고 생각을 했다.

develop branch도 마찬가지 였습니다 ㅠ

그러나 내가 찾을 수 있는 Azure Storage + Android와 관련한 모든 문서들은 모두 관리가 되지 않는듯 했고, Azure Storage for java의 Wiki에서 간신히 Android Support라는 섹션을 찾을 수 있었다.

이마저도 들어가보면 샘플 앱은 4년 전…

오래된 문서였지만 참고하여 어찌저찌 구현에는 성공해냈다. 그러나 이 라이브러리는 안드로이드 지원이 고려되어있지 않은 상태였기 때문에 proguard rule을 직접 작성해야했다. 처음엔 최적화된 rule을 찾다가 모든 것을 keep하도록 하고 넘어갔다. 또한, 동작은 하지만 이렇듯 의도를 파악하지 못한 채 여러 dependency 관련 구문들을 더해줘야하는 것이 부담스러웠다.

시간이 흘러 파일 업로드 구현을 다시 돌아볼 기회가 생겼다. Azure storage for java 내부 구조와 Azure에서 제공하는 Rest API 문서를 토대로 ktor를 이용하여 구현에 성공했다. 특히

  • chunk를 병렬 업로드 - coroutine async, awaitAll,
  • xml serializer

같은 것들을 활용하여 간결하고 쉽게 구현할 수 있었다. 자체 구현한 파일 업로드로 구현을 바꾸고 라이브러리를 제거하니 4.1MB 용량이 감소되었다.

앱 사이즈, 줄여야 할까?

안드로이드 공식 홈페이지의 Reduce App Size 페이지에서는 아래와 같은 내용과 함께 앱 사이즈를 줄이는 방법에 대해 소개하고 있다.

  • 사용자는 용량이 큰 앱 다운로드를 피하는 경향이 있다.
  • 신흥 시장 (ex. 인도)와 같은 곳은 네트워크 환경이 열악하다

Open AI의 Chat GPT는 아래와 같은 답을 줬다.

  • 빠른 다운로드
  • 저장 공간 절약
  • 설치 비율 증가
  • 성능 향상
  • 업데이트 대역폭 절감
  • 사용자 유지율 증가

개인적으로는 ‘용량이 작으면 좋지만 높은 우선 순위로 삼을 것은 아니다’라고 생각한다. 한국 시장을 타겟으로 한다고 했을 때

  • 사용자는 네트워크가 열악한 환경에 놓여있지 않으며
  • 최신 플래그십은 256GB, 심지어 보급형 기기도 128GB의 용량을 가진다.

또한 개인적인 경험을 비추어볼 때 어떤 앱을 다운로드 받냐 마냐 결정하는 가장 큰 요인은 그 앱을 써야할 일이 있기 때문이다. 앱 사이즈와 관련해서 주변 친구들에게 물어봤더니 다들 별 생각이 없는 것이 현실이었다. 더 넓고 다양한 시장을 타겟으로 하는 앱을 개발할 때는 다르게 생각할 수도 있을 것 같다.

마치며

사실 여기서 한번 더 줄일 수 있는 기회가 남아있는데… 바로 Pretendard 폰트의 Google Font 지원이다. 폰트 파일 3개에 해당하는 3.2MB를 더 줄일 수 있을 것 같다. 모두 함께 응원을🙌

위에서 언급했듯이 나는 앱 사이즈를 줄이는 것 자체는 중요한 요소가 아니라 생각한다. 사실 이번 글의 진짜 목적은 ‘동작하면 되었지’라고 넘길만한 사소한 부분들을 파고든 경험을 공유하는 것이었다. 앱 사이즈 감소는 이런 삶의 자세로 인한 부수적인 결과물이었다. 나는 앞으로도 이런 자세를 이어나가볼까 한다.😎