본문 바로가기

안드로이드/Compose

Recomposition

기존의 다른 함수들과는 다르게 Compoable 함수는 한 번 호출되어 Composition이 발생된 이후에도 재생성 될 수 있는데, 이를 Recomposition이라고 한다.

Recomposition 발생 이유

1. Composable 함수의 매개변수 변경

@Composable
fun UserPofile(name: String, phone: String) {...}

2. 관찰 중인 State의 변경

var text by rembember { mutableStateOf("") }

Compose 데이터 타입

Composable 함수의 매개변수 데이터는 두 가지의 타입으로 분류할 수 있다.

1. Stable

  • 원시 타입 (Primitive Types)
  • lamda 함수
    • 외부의 참조 데이터가 없을 경우
    • 참조 데이터가 Stable 한 경우
  • (data) class의 public 프로퍼티가 모두 불변이거나 Stable 한 경우
  • (data) class에 @Stable 또는 @Immutable 어노테이션으로 정의한 경우

2. Unstable

  • 인터페이스
    • Collection: List, Map 등
  • 추상 클래스
  • (data) class의 public 프로퍼티 중 하나 이상이 가변적(var)이거나 Unstable 한 경우

다만 Compose Compiler에게 해당 클래스가 불변임을 알려주면 해당 클래스가 인터페이스 또는 추상 클래스를 상속받고 있더라고 Stable한 타입으로 인식된다.

// Consider LocalDateTime stable
java.time.LocalDateTime
// Consider my datalayer stable
com.datalayer.*
// Consider my datalayer and all submodules stable
com.datalayer.**
// Consider my generic type stable based off it's first type parameter only
com.example.GenericClass<*,_>

// build.gradle
composeCompiler {
  stabilityConfigurationFile = rootProject.layout.projectDirectory.file("stability_config.conf")
}

Kotlinx Immutable Collections 또한 인터페이스를 상속 받고 있지만 Compiler 내부적으로 지원하고 있기 때문에 Stable 타입으로 인식된다.

Stable vs Unstable

  • 데이터가 Stable한 경우, 이전 데이터와 비교(equals)하여 true이면 recomposition을 생략한다.
  • 데이터가 Stable하지만 이전 데이터와 비교(equals)했을 때 false이면 recomposition을 실행한다.
  • 매개변수가 Unstable한 경우, recomposition을 실행한다.

Composable 함수의 유형

Restartable

  • Recomposition 발생할 수 있음

Skippable

  • Recomposition 생략 가능

Movable

  • 고유성을 잃지 않고 트리 내에서 옮겨 다닐 수 있는 함수

Compose Compiler Metrics : 어떤 클래스가 Stable 한지, 어떤 컴포저블 함수가 Stable한지 확인 가능


우리는 위와 같은 내용을 바탕으로 상태를 관리하여 보다 효율적으로 상태를 관리하여 불필요한 Recomposition을 줄여야 한다.

상태 관리에 도움이 되는 어노테이션

@Immutable

변경이 없음을 확신할 때 사용

@Immutable
data class User {
	val name: String,
	val age: Int,
	val images: List<Image> // images의 데이터 변경이 일어나지 않음을 확신한 경우
}

@Stable

public properies들은 불변이지만 실제로 변경 될 가능성이 있는 경우 사용

@Stable
data class User {
	val name: String,
	val age: Int,
	val images: List<Image> // images의 데이터가 변경될 가능성이 있는 경우
}

@NonRestartableComposable

  • 해당 Composable 함수에 Restartable 속성을 부여하지 않음
  • 따라서 Recomposition이 일어나지 않음
  • Composable 함수 중 Recomposition이 일어나면 안되는 경우에 사용해주면 좋음
  • 대표적으로는 상태 관리 및 사이드 이펙트 처리 및 표준 함수만을 사용하는 경우
@Composable
@NonRestartableComposable
fun LaunchedEffect(){
	...
}

 

참고

https://velog.io/@skydoves/compose-stability

 

Jetpack Compose 성능 최적화를 위한 Stability 이해하기

\_원문은 Optimize App Performance By Mastering Stability in Jetpack Compose(https://getstream.io/blog/jetpack-compose-stability/이 포스트의 내용을 심층적으로 다루는

velog.io

 

'안드로이드 > Compose' 카테고리의 다른 글

Compose 동작 원리  (0) 2025.01.21