시배's Android

Compose | Recomposition Optimistic 본문

Android/Compose

Compose | Recomposition Optimistic

si8ae 2023. 7. 10. 01:03

Recomposition

Compose의 recomposition은 UI를 업데이트하기 위해 필요한 변경 작업을 식별하고 수행하는 과정을 의미합니다. Recomposition은 선언적인 방식으로 작성된 Composable 함수들이 동작하는 핵심 메커니즘 중 하나입니다.

 

Compose에서는 UI를 구성하는 각각의 Composable 함수는 독립적인 단위로 작동합니다. Composable 함수는 입력된 상태(State)에 따라 UI를 그리고 업데이트하는 역할을 담당합니다. Composable 함수는 상태가 변경될 때마다 자동으로 호출되고, 변경된 부분만 다시 그리고 업데이트합니다.

 

Recomposition Composable 함수가 동일한 입력에 대해 동일한 출력을 생성하는지 확인하기 위해 수행됩니다. Compose 상태가 변경되면 해당 상태를 사용하는 Composable 함수들을 추적하고, 변경된 상태에 영향을 받는 Composable 함수들을 재귀적으로 호출하여 UI 업데이트합니다. 이때 변경된 부분만 다시 그리고 업데이트하여 효율적인 UI 업데이트를 수행합니다.

Recomposition Optimistic

@Composable
fun Body(){
    var title1 by remember { mutableStateOf(0) }
    var title2 by remember { mutableStateOf(0) }
    var title3 by remember { mutableStateOf(0) }

    Log.e("ABC", "ABC")

    Column {
        Text(text = title1.toString())
        Text(text = title2.toString())
        Text(text = title3.toString())
        Button(
            onClick = {
                title1++
                title2++
                title3++
            }
        ) {
            Text(text = "클릭")
        }
    }
}

해당 함수에서는 각자의 state를 가지는 Text가 3개가 있고 Button의 클릭을 통해 각자의 state를 변경하고 있다. 만약 이 경우에는 recomposition이 3번 일어나게 될 텐데 Log는 몇 번 호출이 될까?

 

실행 결과 Log는 한번만 찍힌다.

 

@Composable
fun Body(){
    var title1 by remember { mutableStateOf(0) }
    var title2 by remember { mutableStateOf(0) }
    var title3 by remember { mutableStateOf(0) }

    val scope = rememberCoroutineScope()

    Log.e("ABC", "ABC")

    Column {
        Text(text = title1.toString())
        Text(text = title2.toString())
        Text(text = title3.toString())
        Button(
            onClick = {
                scope.launch {
                    title1++
                    delay(20)
                    title2++
                    delay(20)
                    title3++
                }
            }
        ) {
            Text(text = "클릭")
        }
    }
}

만약 이렇게 state를 변경하는 것을 delay를 줘서 실행하면 Log가 몇 번 찍힐까?

 

이렇게 3번이 찍힐 때도 있고 2번이 찍힐 때도 있다.

 

이렇게 동작의 차이가 나는것은 Android Developer에서 찾아볼 수 있었다.

 

https://developer.android.com/jetpack/compose/mental-model#optimistic

 

Compose 이해  |  Jetpack Compose  |  Android Developers

Compose 이해 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Jetpack Compose는 Android를 위한 현대적인 선언형 UI 도구 키트입니다. Compose는 프런트엔드 뷰를 명령

developer.android.com

Recomposition은 Compose에서 특정 Composable의 매개변수가 변경될 수 있다고 판단될 때 시작됩니다. Recomposition은 낙관적인 방식으로 수행되며, Compose는 recomposition이 끝나기 전에 매개변수가 다시 변경될 것을 예상합니다. 하지만 recomposition이 끝나기 전에 매개변수가 변경된다면, Compose는 recomposition을 취소하고 새로운 매개변수로 다시 시작할 수 있습니다.
Recomposition이 취소되면, Compose는 해당 recomposition의 UI 트리를 폐기합니다. 만약 UI에 의존하는 부수 효과(side-effect)가 있다면, recomposition이 취소되어도 부수 효과가 적용됩니다. 이는 일관되지 않은 앱 상태로 이어질 수 있습니다.
낙관적인 recomposition을 처리하기 위해 모든 Composable 함수와 람다가 idempotent 하고 부수 효과가 없도록 보장해야 합니다.

즉 Compose는 recomposition 진행중에 새로운 recomposition이 발생하면 기존의 recomposition을 취소하고 새롭게 시작한다는 것을 알 수 있다.