안정성 문제 진단

불필요하거나 과도한 리컴포지션으로 인해 성능 문제가 발생하는 경우 앱의 안정성을 디버그해야 합니다. 이 가이드에서는 앱의 안정성을 디버그하는 여러 방법을 설명합니다.

Layout Inspector

Android 스튜디오의 Layout Inspector를 사용하면 앱에서 재구성되는 컴포저블을 확인할 수 있습니다. Compose가 구성요소를 재구성하거나 건너뛴 횟수가 표시됩니다.

Layout Inspector의 리컴포지션 및 건너뛰기 횟수

Compose 컴파일러 보고서

Compose 컴파일러는 검사를 위해 안정성 추론 결과를 출력할 수 있습니다. 이 출력을 사용하여 건너뛸 수 있는 컴포저블과 건너뛸 수 없는 컴포저블을 확인할 수 있습니다. 다음 하위 섹션에서는 이러한 보고서를 사용하는 방법을 요약하지만 자세한 내용은 기술 문서를 참고하세요.

설정

Compose 컴파일러 보고서는 기본적으로 사용 설정되지 않습니다. 컴파일러 플래그를 사용하여 활성화할 수 있습니다. 정확한 설정은 프로젝트에 따라 다르지만 Compose 컴파일러 Gradle 플러그인을 사용하는 프로젝트의 경우 각 모듈의 build.gradle 파일에 다음을 추가할 수 있습니다.

  android { ... }

  composeCompiler {
    reportsDestination = layout.buildDirectory.dir("compose_compiler")
    metricsDestination = layout.buildDirectory.dir("compose_compiler")
  }

이제 프로젝트를 빌드할 때 Compose 컴파일러 보고서가 생성됩니다.

출력 예

reportsDestination는 세 개의 파일을 출력합니다. 다음은 JetSnack의 출력 예시입니다.

  • <modulename>-classes.txt: 이 모듈에 있는 클래스의 안정성에 관한 보고서입니다. 샘플
  • <modulename>-composables.txt: 모듈에서 컴포저블이 다시 시작 가능하고 건너뛸 수 있는 방법에 관한 보고서입니다. 샘플
  • <modulename>-composables.csv: 스프레드시트로 가져오거나 스크립트를 사용하여 처리할 수 있는 컴포저블 보고서의 CSV 버전입니다. 샘플

컴포저블 보고서

composables.txt 파일은 매개변수의 안정성, 다시 시작 가능 여부, 건너뛸 수 있는지 여부 등 지정된 모듈의 각 컴포저블 함수를 자세히 설명합니다. 다음은 JetSnack의 가상 예시입니다.

restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SnackCollection(
  stable snackCollection: SnackCollection
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
  stable index: Int = @static 0
  stable highlight: Boolean = @static true
)

SnackCollection 컴포저블은 완전히 다시 시작 가능하고, 건너뛸 수 있으며, 안정적입니다. 이는 일반적으로 바람직하지만 필수는 아닙니다.

다른 예를 살펴보겠습니다.

restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  stable index: Int
  unstable snacks: List<Snack>
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
)

HighlightedSnacks 컴포저블은 건너뛸 수 없습니다. Compose는 리컴포지션 중에 이를 건너뛰지 않습니다. 매개변수가 변경되지 않은 경우에도 발생합니다. 이는 unstable 매개변수 snacks 때문입니다.

수업 보고서

classes.txt 파일에는 지정된 모듈의 클래스에 관한 유사한 보고서가 포함되어 있습니다. 다음 스니펫은 Snack 클래스의 출력입니다.

unstable class Snack {
  stable val id: Long
  stable val name: String
  stable val imageUrl: String
  stable val price: Long
  stable val tagline: String
  unstable val tags: Set<String>
  <runtime stability> = Unstable
}

참고로 Snack의 정의는 다음과 같습니다.

data class Snack(
    val id: Long,
    val name: String,
    val imageUrl: String,
    val price: Long,
    val tagline: String = "",
    val tags: Set<String> = emptySet()
)

Compose 컴파일러가 Snack를 불안정하다고 표시했습니다. tags 매개변수의 유형이 Set<String>이기 때문입니다. MutableSet이 아니므로 변경 불가능한 유형입니다. 하지만 Set, List, Map와 같은 표준 컬렉션 클래스는 궁극적으로 인터페이스입니다. 따라서 기본 구현은 여전히 변경 가능할 수 있습니다.

예를 들어 val set: Set<String> = mutableSetOf("foo")를 작성할 수 있습니다. 변수는 상수이고 선언된 유형은 변경할 수 없지만 구현은 여전히 변경할 수 있습니다. Compose 컴파일러는 선언된 유형만 확인하므로 이 클래스의 불변성을 확신할 수 없습니다. 따라서 tags을 불안정으로 표시합니다.