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

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

APK 크기 및 빌드 시간

이 섹션에서는 뷰 기반 앱을 Compose로 이전하는 권장사항을 보여주는 앱인 Sunflower 샘플 앱을 살펴보고 APK 크기와 빌드 시간에 미치는 영향을 살펴봅니다.

APK 크기

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

보기 전용 뷰와 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와 같은 사용되지 않는 뷰 종속 항목을 삭제했기 때문입니다.

빌드 시간

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

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

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

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

요약

Compose를 채택하면 앱의 APK 크기가 효과적으로 증가하고 Compose 코드의 컴파일 프로세스로 인해 앱의 빌드 시간 성능이 향상됩니다. 그러나 이러한 장단점은 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는 스마트 리컴포지션을 제공하여 개발자가 변경할 필요가 없는 경우 이전에 그린 결과를 재생합니다.

다중 레이아웃 패스

기존 ViewGroup은 측정 및 레이아웃 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 앱의 시작 시간과 버벅거림을 줄이는 프로필 설치 규칙을 제공합니다.