기존의 다른 함수들과는 다르게 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 |
---|