Compose 측정항목과 뷰 측정항목 비교

Jetpack Compose는 UI 개발을 가속화하고 Android 개발을 개선합니다. 하지만 기존 앱에 Compose를 추가하면 앱의 APK 크기, 빌드, 런타임 성능과 같은 측정항목에 어떤 영향을 미칠 수 있는지 고려해야 합니다.

APK 크기 및 빌드 시간

이 섹션에서는 뷰 기반 앱을 Compose로 이전할 때의 권장사항을 보여주는 앱인 Sunflower 샘플 앱을 살펴봄으로써 APK 크기와 빌드 시간에 미치는 영향을 설명합니다.

APK 크기

프로젝트에 라이브러리를 추가하면 APK 크기가 커집니다. 다음은 각 프로젝트의 축소된 출시 APK 결과입니다. R8 전체 모드로 리소스 및 코드 축소가 사용 설정되었으며 APK Analyzer로 측정되었습니다.

보기 전용 뷰와 Compose 혼합 Compose 전용
다운로드 크기 2,252 KB 3,034 KB 2,966 KB

Sunflower에 Compose를 처음 추가했을 때 APK 크기가 2,252KB에서 3,034KB로 782KB 증가했습니다. 생성된 APK는 뷰와 Compose가 혼합된 UI 빌드로 구성되었습니다. Sunflower에 종속 항목이 추가되었으므로 이러한 증가는 예상된 바입니다.

반대로 Sunflower가 Compose 전용 앱으로 이전되었을 때 APK 크기가 3,034KB에서 2,966KB로 줄어 68KB 감소했습니다. 이는 AppCompatConstraintLayout와 같이 사용하지 않는 View 종속 항목이 삭제되었기 때문입니다.

빌드 시간

Compose를 추가하면 Compose 컴파일러가 앱에서 컴포저블을 처리하므로 앱의 빌드 시간이 늘어납니다. 다음 결과는 Sunflower의 디버그 빌드 기간에 대한 평균 빌드 시간을 얻을 수 있도록 빌드를 여러 번 실행하는 독립형 gradle-profiler 도구를 사용하여 얻은 것입니다.

gradle-profiler --benchmark --project-dir . :app:assembleDebug
조회수만 뷰와 Compose 혼합 Compose 전용
평균 빌드 시간 299.47밀리초 399.09밀리초 342.16 ms

Sunflower에 Compose를 처음 추가했을 때 평균 빌드 시간이 299ms에서 399ms로 증가하여 100ms 증가했습니다. 이 기간은 Compose 컴파일러가 프로젝트에 정의된 Compose 코드를 변환하기 위해 추가 작업을 실행하기 때문입니다.

반대로 Compose의 Sunflower의 이전이 완료되었을 때 평균 빌드 시간은 342밀리초로 57밀리초 감소되었습니다. 이러한 감소는 데이터 결합 삭제, kapt를 KSP로 사용하는 종속 항목 이전, 여러 종속 항목을 최신 버전으로 업데이트하는 등 빌드 시간을 총체적으로 줄이는 여러 요소에 기인합니다.

요약

Compose를 채택하면 Compose 코드의 컴파일 프로세스로 인해 앱의 APK 크기가 효과적으로 증가하고 앱의 빌드 시간 성능도 증가합니다. 그러나 이러한 장단점은 Compose의 이점, 특히 Compose 채택 시 개발자 생산성 증가와 비교하여 감안해야 합니다. 예를 들어 Play 스토어팀UI를 작성할 때 필요한 코드가 훨씬 적기(때로는 최대 50%)로 인해 코드의 생산성과 유지 관리 효율성이 높아진다는 사실을 발견했습니다.

팀용 Compose 채택에서 우수사례를 자세히 알아보세요.

런타임 성능

이 섹션에서는 Jetpack Compose의 런타임 성능과 관련된 주제를 다루므로 Jetpack Compose와 뷰 시스템 성능의 비교 결과 및 측정 방법을 이해할 수 있습니다.

스마트 재구성

UI의 일부가 잘못된 경우 Compose는 업데이트해야 하는 부분만 재구성하려고 합니다. 자세한 내용은 컴포저블의 수명 주기Jetpack Compose 단계 문서를 참고하세요.

기준 프로필

기준 프로필은 일반적인 사용자 여정의 속도를 높이는 데 효과적인 방법입니다. 앱에 기준 프로필을 포함하면 포함된 코드 경로의 해석과 JIT (just-in-time) 컴파일 단계를 피하여 최초 실행 후 코드 실행 속도를 약 30% 개선할 수 있습니다.

Jetpack Compose 라이브러리에는 자체 기준 프로필이 포함되어 있으며 앱에서 Compose를 사용하면 이러한 최적화가 자동으로 적용됩니다. 그러나 이러한 최적화는 Compose 라이브러리 내의 코드 경로에만 영향을 미치므로 Compose 외부의 코드 경로를 처리하도록 앱에 기준 프로필을 추가하는 것이 좋습니다.

View 시스템과의 비교

Jetpack Compose는 뷰 시스템에 비해 많은 개선사항이 있습니다. 이러한 개선사항은 다음 섹션에 설명되어 있습니다.

View 시스템 확장

TextView, Button 또는 ImageView와 같이 화면에서 그리는 모든 View에는 메모리 할당과 명시적 상태 추적을 비롯하여 모든 사용 사례를 지원하는 다양한 콜백이 필요합니다. 또한 맞춤 View 소유자는 다시 그릴 필요가 없는 경우(예: 반복 데이터 처리) 이를 방지하는 명시적인 로직을 구현해야 합니다.

Jetpack Compose에서는 여러 가지 방법으로 이러한 문제를 해결했습니다. Compose에는 뷰를 그리기 위한 명시적 업데이트 가능 객체가 없습니다. UI 요소는 정보를 재생 가능한 방식으로 컴포지션에 작성하는 간단하고 구성 가능한 함수입니다. 이렇게 하면 명시적 상태 추적, 메모리 할당 그리고 주어진 View 유형을 모두 확장하는 대신 언급된 기능만 요구하는 컴포저블 콜백을 줄일 수 있습니다.

또한 Compose는 스마트 재구성을 제공하여 변경할 필요가 없으면 이전에 그린 결과를 다시 보여줍니다.

다중 레이아웃 패스

기존 ViewGroups는 측정 및 레이아웃 API의 표현력이 뛰어나서 다중 레이아웃 패스가 발생하기 쉽습니다. 이러한 다중 레이아웃 패스가 뷰 계층 구조의 특정 중첩 지점에서 실행되면 지수 작업이 발생할 수 있습니다.

Jetpack Compose는 API 계약을 통해 모든 레이아웃 컴포저블에 단일 레이아웃 패스를 적용합니다. 이를 통해 Compose는 깊은 UI 트리를 효율적으로 처리할 수 있습니다. 여러 측정이 필요한 경우 Compose에는 내장 측정이 있습니다.

View 시작 성능

View 시스템이 특정 레이아웃을 처음 표시할 때는 XML 레이아웃을 확장해야 합니다. 레이아웃은 Kotlin으로 작성되고 앱의 나머지 부분과 마찬가지로 컴파일되므로 Jetpack Compose에서는 이 비용이 절감됩니다.

Compose 벤치마크

Jetpack Compose 1.0에서는 debug 모드와 release 모드의 앱 성능 사이에 큰 차이가 있습니다. 앱을 프로파일링할 때 대표적인 시간 측정에는 항상 debug 대신 release 빌드를 사용합니다.

Jetpack Compose 코드의 성능을 확인하려면 Jetpack Macrobenchmark 라이브러리를 사용하면 됩니다. Jetpack Compose와 함께 이 라이브러리를 사용하는 방법은 MacrobenchmarkSample 프로젝트를 참고하세요.

Jetpack Compose팀에서도 Macrobenchmark를 사용하여 발생할 수 있는 모든 회귀를 포착합니다. 예를 들어 지연 열 벤치마크대시보드를 참고하여 회귀를 추적할 수 있습니다.

Compose 프로필 설치

Jetpack Compose는 번들되지 않은 라이브러리이므로 뷰 시스템의 UI 툴킷 클래스와 드로어블을 미리 로드하는 Zygote의 이점이 없습니다. Jetpack Compose 1.0은 출시 빌드에 프로필 설치를 활용합니다. 프로필 설치 프로그램을 사용하면 앱이 설치 시 AOT (Ahead-Of-Time)로 컴파일할 중요 코드를 지정할 수 있습니다. Compose는 Compose 앱의 시작 시간과 버벅거림을 줄이는 프로필 설치 규칙을 제공합니다.