Compose의 개발자 에르고노믹스

Jetpack Compose는 UI 개발을 가속화하고 Android 엔지니어의 생산성을 높여줍니다. 하지만 APK를 비롯하여 빌드와 런타임 성능에 영향을 줄 수 있으므로 프로젝트에 새 도구를 추가하는 경우에는 주의해야 합니다.

APK 크기 및 빌드 시간

이 섹션에서는 Jetpack Compose에 추가하거나 이전할 때 두 가지 앱이 어떻게 영향을 받았는지 비교합니다.

  • Tivi가 Compose로 완전히 이전되었으며 AppCompat 및 머티리얼 디자인 구성요소 라이브러리가 삭제되었습니다.
  • Sunflower (compose_recyclerview 분기)는 RecyclerView의 항목에 사용하는 Compose를 추가합니다. 다른 모든 종속 항목은 동일합니다.

APK 크기

프로젝트에 라이브러리를 추가하면 APK 크기가 영향을 받습니다. Compose가 위에 언급한 프로젝트의 크기에 어떻게 영향을 미치는지 살펴보겠습니다. 다음은 각 프로젝트의 축소된 출시 APK의 결과입니다. R8 전체 모드로 리소스 및 코드 축소가 사용 설정되었으며 APK Analyzer로 측정되었습니다.

Tivi의 APK 크기가 4.49MB에서 2.39MB로 46% 감소했습니다. 또한 Compose로 완전히 이전한 후 메서드 개수도 17% 감소했습니다. XML 코드 행이 76% 감소했습니다.

Compose가 프로젝트에 추가됐을 때 Sunflower의 APK 크기가 2,407KB에서 2,982KB로 575KB 증가했습니다. Compose는 해당하는 Sunflower 분기에서 거의 사용되지 않으므로 프로젝트에서 AppCompat 종속 항목을 삭제하는 것과 같은 Compose 전용 APK 크기의 이점을 누리지 못합니다.

빌드 시간

동일한 프로젝트를 사용하여 Compose가 빌드 성능에 미치는 영향을 측정해보겠습니다.

여기에서는 개발 시 신경을 많이 쓰는 디버그 빌드 시간을 고려합니다.

Compose로 이전하기 전 Tivi의 평균 빌드 시간은 108.71초였습니다. Compose로 완전히 이전한 후 평균 빌드 시간이 76.96초로 감소했습니다. 빌드 시간이 29% 감소한 것입니다. 이러한 시간 감소는 kapt 주석 프로세서를 사용하는 프로젝트에서 데이터 결합Epoxy를 삭제할 수 있고, HiltAGP 7.0에서 더 빠르다는 사실에 영향을 많이 받습니다.

그러나 Sunflower는 빌드 시간 중앙값이 11.57초에서 12.45초로 7.6% 증가했습니다.

마치면서

앱에서 Compose를 채택하면 APK 크기와 빌드 시간이 증가할 수 있습니다. 늘어난 APK 크기와 빌드 시간은 프로젝트가 Compose로 완전히 이전하면 줄어들어 원래 측정항목을 초과합니다.

런타임 성능

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

스마트 재구성

UI의 일부가 잘못된 경우 Compose는 업데이트해야 하는 부분만 재구성하기 위해 최선을 다합니다. 이 주제에 관한 자세한 내용은 컴포저블의 수명 주기 가이드를 참고하세요.

View 시스템과의 비교

디자인과 View 시스템에서 학습한 내용 덕분에 Jetpack Compose의 성능은 View 시스템을 능가합니다.

View의 확장인 모든 항목

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

Jetpack Compose에서는 여러 가지 방법으로 이러한 문제를 해결했습니다. Compose에는 그리기 뷰를 위한 명시적 업데이트 가능 객체가 없습니다. UI 요소는 정보를 재생 가능한 방식으로 Composition에 작성하는 간단하고 구성 가능한 함수입니다. 이렇게 하면 명시적 상태 추적, 메모리 할당, 그리고 주어진 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팀은 이 메서드를 사용하여 발생할 수 있는 모든 회귀를 포착합니다. 예를 들어 이 지연 열 벤치마크대시보드를 참고하여 회귀를 추적할 수 있습니다.

Compose 프로필 설치

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