Developing Myself Everyday
article thumbnail

사진: UnsplashEmily Morter

 

 

 

저는 요즘 Compose를 배우고 사용하면서 Compose에 매력에 깊게 빠져 있습니다. 그래서 기존의 프로젝트를 Compose로 다시 만들어보기도 하고, 새로운 프로젝트도 거의 Compose로 진행하고 있습니다.

 

다만, Compose로 만든 앱을 실행해 보면, 이상하게 버벅거리는 것들이 있었습니다. 리스트를 스크롤할 때나 애니메이션을 구성했을 때가 특히 그랬습니다.

 

이번 게시글에서는 코드와는 상관없이 버벅거림에 대한 해결방안과 이유에 대해 알아보고자 합니다.


 

 

 

해결방안


가장 간단하게 Compose로 구성한 화면의 버벅거림을 해결하는 방법은 Release mode와 R8을 사용하여 빌드하는 것입니다.

 

이를 이야기 하기 위해서는 먼저 안드로이드의 2가지 빌드 방식인 Debug ModeRelease Mode에 대해 설명해야 할 것 같습니다. 

 

Debug Mode

Debug Mode는 앱을 빌드할 때 발생할 수 있는 오류를 잡기 위한 모드입니다. 그렇기 때문에 Log, 오류를 잡기 위한 시스템, 데이터 추적 및 관리 등의 여러 가지 것들을 포함해야 합니다. 

 

그럼 자연스럽게 빌드 결과의 크기가 커지게 되고, 속도 또한 당연히 느릴 것입니다.

 

 

Release Mode

Release라는 이름에 걸맞게 해당 모드는 애플리케이션을 배포하기 위해 빌드할 때 사용되는 모드입니다. 

 

Debug Mode에 있는 모든 기능은 Release Mode에서는 필요하지 않습니다. 또한 R8 같은 컴파일러를 사용해 앱에 대한 속도와 관련된 최적화도 가능하며, 앱이 더 빠르고 반응성이 좋아지게 됩니다.

R8 컴파일러
가장 최신의 안드로이드 빌드 과정은 R8 컴파일러에 의해 진행됩니다. .dex 파일로 변환되는 과정에서 진행되는 앱의 최적화는 이전에는 Proguard에 의해 진행되었습니다.
현재는 여러한 이유 때문에 D8을 거쳐 R8을 사용하고 있습니다.

 

 

 

이러한 모드를 변경할 수 있는 방법은 `Build Variants`에서 `Active Build Variant`를 변경하면 됩니다.

 

 

 

 

 

이유


그럼 XML에서는 그런 적이 없었는데 Compose로 개발하면 왜 화면이 버벅거리는 걸까요? 

 

 

이에 대한 대답은 아래의 게시글에서 확인할 수 있었습니다.

 

Why should you always test Compose performance in release?

When discussing performance related to Compose, you’ll find that the guidance states “always test in release mode with R8 enabled”. You…

medium.com


 

 

 

먼저 아래의 그래프를 보겠습니다. 이 그래프는 각각의 방식에서 첫 프레임을 렌더링하는 데 걸리는 시간을 나타냈습니다.

 

그래프로 알 수 있는 것은, Compose가 다른 방식보다 Debug Mode에서 훨씬 느리게 수행되는 것을 확인할 수 있습니다. View 기반 Activity도 느리게 수행되지만 이는 Compose에서 특히 도드라집니다.

 

 

Compose가 특히 느린 이유

Compose가 특히 느린 이유는 Compose는 앱에 번들되지 않았고, 앱에서 라이브러리를 정적으로 연결한다는 것입니다.

 

Compose는 라이브러리로 제공되며, 시스템 프레임워크와 분리되어 있습니다. 이런 점에서 시스템 프레임워크에 번들로 제공되는 View 시스템과 차이가 나타나게 됩니다.

 

이러한 차이는 안드로이드의 실행 환경의 특성에서 두 시스템간의 시간의 차이를 발생시킵니다.

 

 

 

 

위의 그림에서 Compose와 View 시스템간의 시간 차이를 발생시키는 부분은 AOT(JIT, Interpreter)입니다.

 

안드로이드에서는 앱을 실행하기 전에 바이트 코드를 미리 컴파일하는 AOT(Ahead-Of-Time) 컴파일 방식과 바이트 코드를 선택하여 이를 Interpreter로 기계 코드로 변환하면서, 반복되는 부분을 JIT(Just In Time) 컴파일러로 처리하는 방식으로 나뉩니다. 

 

Compose는 라이브러리이기 때문에 실행 시점에서 모든 코드가 Interpreter에 의해 번역되어야 하므로 AOT 컴파일 방식을 사용해서 미리 컴파일할 수 없습니다.

 

그렇기에 Interpreter와 JIT를 사용해야 하는데, 이러한 방식은 당연하게도 AOT에 비해 많은 시간과 성능을 요구하게 됩니다.

 

View 시스템과 같은 코드들은 이미 Release로 빌드되어 Android OS와 함께 제공되기 때문에 Interpreter에 의해 번역되지 않습니다. 

 

 

 

 

그래서


이런 문제들은 앱을 Release Mode로 컴파일 하는 것으로 부분적으로 해결할 수 있습니다. 앱은 더 이상 Debug 되지 않으므로 Interpreter가 없이 실행될 수 있고 이는 Lazy 하게 실행됩니다.

 

ART는 모든 코드를 Interpreter Mode로 실행한 다음, 중요한 코드를 효율적으로 실행될 수 있도록 다음번에 실행될 때 컴파일합니다.

 

다만 아래의 그림을 보면 Release Mode로 실행하더라도 상당한 시간이 걸린다는 것을 확인할 수 있습니다.

 

이는 R8을 통해 최적화 하는 과정에 의해 해결됩니다. 또한 Compose는 Baseline Profiles이 함께 제공되는데 이는 Compose로 구성된 앱을 실행할 때, Compose에서 자주 사용되는 라이브러리를 표시하고 Interpreter에 의해 해석되지 않아도 될 수 있게 컴파일할 메서드로 표시합니다.

 

Android Studo에서는 이러한 Baseline Profiles이 제공되지 않기 때문에 Release 모드로 실행하더라도 실제 앱에 비해 떨어져 보일 수 있습니다.

 

 

 

 

마무리하며


이렇게 해서 Compose로 개발한 앱의 화면이 버벅거리는 이유에 대해 살펴보았습니다. 안드로이드의 실행 환경, 다양한 요인들로 인해 View 시스템과의 차이가 발생하여 버벅거리게 되지만, 구글에서는 이를 해결하기 위해 많은 노력을 하고 있다는 것 또한 알 수 있었습니다.

 

 

 

 

Reference

 

Compose 성능  |  Jetpack Compose  |  Android Developers

Compose 성능 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Jetpack Compose의 목표는 처음부터 우수한 성능을 제공하는 것입니다. 이 페이지에서는 최고의 성능

developer.android.com

'Android > Compose' 카테고리의 다른 글

Compose의 Remember, RememberSaverable 정복하기  (0) 2024.03.06
Compose의 버전 관리: BOM!!  (0) 2024.02.19
Compose의 Layout 단계  (0) 2023.10.24
Compose에서의 State(상태)  (1) 2023.10.05
JetPack Compose에 대한 이해  (1) 2023.10.04
profile

Developing Myself Everyday

@배준형

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!