본문 바로가기
개발/Android

[Android] Compose 성능 개선 - Compose Compiler Metrics Report와 Restartable, Skippable

by du.it.ddu 2025. 2. 17.

안드로이드 개발을 하시는 분이라면 Compose로 개발을 하고 계시거나 개발할 계획이 있을 것입니다.
Compose는 안드로이드 앱에서 UI를 만들기 위해 사용하는 도구이기 때문에, 사용자에게 안정적이고 빠른 화면을 보여주기 위해 성능을 고려해야 합니다.

이를 위해선 Compose가 어떻게 동작하는지에 대한 이해, 그리고 그 이해를 바탕으로 효과적으로 동작할 수 있도록 코드를 작성하는 것이 중요할 것입니다.

하지만 나름대로 이해도 해보고 잘 작성했다고 하더라도 실제로 잘 한게 맞는지를 확인하기 위해선 어떤 지표를 확인하는게 좋겠죠.
이 포스팅에선 지표를 확인하고 이해해보는 것을 다루겠습니다.

 

Compose Compiler Metrics Report

UI를 효율적으로 작성한다는 것은 그려내는 시간을 단축하는 것도 좋지만, 불필요한 갱신이 발생하지 않도록 하는것도 매우 중요한 부분입니다.
Compose는 최초 화면에 나타난 이후, 상태의 변화에 따라 0번 이상 리컴포지션(Recomposition)이 발생하게 됩니다.
화면에 표현해야할 데이터(상태)가 변경되면 당연히 리컴포지션을 거쳐 다시 그려내는게 맞지만 그렇지 않은 상황에서도 다시 그려낸다면 비효율이 발생하여 결국 성능에 영향을 미치게 됩니다.

자, 그럼 어디에서 불필요한 리컴포지션이 발생하는지를 알아야겠죠. 이 때 활용할 수 있는 것이 Compose Compiler Metrics Report입니다.
안드로이드 프로젝트에 다음과 같은 코드를 추가합시다.

// build.gradle.kts (:app)
android {

    ...
    
    kotlinOptions {
        freeCompilerArgs += listOf("-P",
            "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=${rootProject.file(".").absolutePath}/compose-metrics"
        )
        freeCompilerArgs += listOf("-P",
            "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${rootProject.file(".").absolutePath}/compose-reports"
        )
    }
}

위 명령어는 빌드 시에 Compose compiler가 프로젝트의 Composable에 대한 지표와 세부적인 보고서를 생성해줍니다.
빌드를 해 봅시다.

최상위 디렉토리로 이동하면 compose-metrics와 compose-reports 폴더가 생성되었고, 그 내부에 무언가 파일들이 많이 생성된 것을 알 수 있습니다.
UnitTest, AndroidTest는 제외하고 각각의 내용에 대해 확인해보겠습니다.

app-debug-module.json

compose-metrics는 프로젝트에 존재하는 Composable 함수들에 대한 수치적인 지표를 생성해줍니다.
전체 Composable 함수는 몇 개인지, Skippable, Restartable 에 해당하는 Composable 함수는 무엇인지와 같은 지표가 있습니다.

RestartableComposables

이것에 해당하는 Composable 함수들은 Compose 함수의 상태가 변경되어 리컴포지션(Recomposition)이 발생했을 때 재시작될 수 있는 함수를 의미합니다.

 

SkippableComposables

이것에 해당하는 Composable 함수들은 Compose 함수의 상태가 변경되어 리컴포지션(Recomposition)이 발생했을 때, Composable 함수가 추적하는 파라미터(상태)가 이전과 동일하다면 스킵할 수 있는 함수들을 의미합니다.
우리는 리컴포지션이 발생하더라도 상태가 변경되지 않으면 Skip될 수 있도록 Composable을 구성하는 것을 목표로 해야 합니다.

 

app-debug-classes.txt

이 파일은 프로젝트에서 사용되는 클래스들의 Stable 여부를 파악해줍니다.
위 예시에서 어떤 클래스는 stable claass로, 어떤 클래스는 unstable class로 나타나 있습니다.

https://developer.android.com/develop/ui/compose/performance/stability?hl=ko

 

Compose의 안정성  |  Jetpack Compose  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. Compose의 안정성 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Compose는 유형을 안정적이거나 불안정

developer.android.com

Compose의 Stability(안정성)은 Composable 함수의 리컴포지션에 아주 중요한 역할을 합니다.
Composable는 관찰하고 있는 파라미터(상태)의 변화에 따라 리컴포지션을 수행하는데, 리컴포지션이 발생했을 때 자신이 관찰하고 있는 파라미터(상태)가 변경되지 않았다면 생략(Skip)될 수 있습니다. 이 때, "변경되지 않았다"의 기준은 값 자체가 변경되지 않는 것도 맞지만, 그 값이 안정적인(Stable) 상태가 아니라면 생략하지 못합니다.

즉, Composable의 생태에 해당하는 값, 클래스를 Compose Compiler가 stable로 인지해야 합니다.
이것에 대해서는 다음 기회에 좀 더 상세히 다루겠습니다. 궁금하시다면 구글의 공식 문서를 참고해보시는 것을 추천합니다.

 

app_debug-composables.csv

이 파일은 Composable 함수의 이름과 Skippable, Restartable 인지에 대한 여부가 표시되어 있습니다.
1이라면 true를 의미합니다.
우리는 여기서 Restartable이 1이지만 Skippable이 0 인 Composable 함수를 찾아 개선할 수 있을 것입니다.

 

app_debug-composables.txt

이 파일은 Composable 함수들의 restartable, skippable 여부, 그리고 함수의 파라미터(상태)들이 stable, unstable 여부를 나타냅니다.
위 예시에서 OkCancelDialog를 보면 함수 자체는 restartable, skippable 이지만 unstable 파라미터가 존재하는 것을 알 수 있습니다.
우리는 Composable 함수의 파라미터들이 모두 stable한 것이 좋으므로 이 파일을 확인하여 stable한 파라미터가 될 수 있도록 개선할 수 있을 것입니다.

 

마치며

Compose의 동작 방식을 이해하고 Stability를 신경쓰며 개발한다고 해도 놓치는 부분이 생길 수 있습니다.
사실 이 포스팅의 예시를 만들기 위해 일부로 바꾼 부분도 있지만, 놓친 부분이 있었거든요.

주기적으로 오늘 학습했던 지표들을 활용해 Composable 함수들을 분석하고 개선해 간다면, 앱의 품질과 성능을 개선하고, 앞으로 더 신경써서 개발할 수 있는 기반을 마련하면 좋을 것 같습니다. :)

반응형