Jetpack Compose(3) - 수명 주기

김재원·2022년 3월 14일

JetpackCompose

목록 보기
3/9
post-thumbnail

이 글은 JetpackCompose 공식문서 - 수명 주기를 읽어보면서 정리한 글 입니다.

Activity, Fragment등에는 수명 주기가 있습니다. Android 개발자들은 그 수명 주기에 맞춰 개발을 하곤 했습니다

Compose에도 이러한 수명 주기가 있습니다. 이 글에서는 Compose의 수명 주기에는 어떤것들이 있고, 어떻게 개발을 해야하는지에 대해 알아보도록 하겠습니다😌.

수명 주기 개요

Compose의 수명 주기는

  • 초기 컴포지션(Initial Composition)
  • 리컴포지션(ReComposition),
  • 컴포지션 종료(Leaving the Composition)
    세 가지로 구성됩니다.

Compose는 초기 컴포지션시 UI를 구현하기 위한 Composable함수를 추적합니다. 이후, 상태가 변경되면 리컴포지션을 예약합니다. 리컴포지션은 Composable함수를 다시 호출하여 새로운 상태를 표시하여 컴포지션을 업데이트하는 것입니다. 리컴포지션은 한번도 안일어날 수도 있고, 여러번 일어날 수도 있습니다.
컴포지션은 초기 컴포지션시 생성되고, 리컴포지션을 통해서만 업데이트할 수 있습니다.

컴포지션 내에 Composable 분석

Composable은 호출 사이트(호출한 소스코드 위치)기준으로 식별됩니다.
리컴포지션시 Composable함수 내에서 호출되거나 호출되지 않은 Composable을 식별합니다. 그중, 이전 컴포지션시에 호출되었던 Composable함수는 입력이 변경되지 않았다면 재구성(ReComposition)하지 않습니다.

@Composable
fun LoginScreen(showError: Boolean) {
    if (showError) {
        LoginError()
    }
    LoginInput()
}

@Composable
fun LoginInput() { /* ... */ }

LoginScreen에서 초기 컴포지션시에 LoginInput()을 호출한 후, showError이 변경(상태 변경)되어 리컴포지션하게 되면 LoginInput은 호출했었고, 변경된 매개변수가 없으므로 호출되지 않습니다.

스마트 리컴포지션에 도움이 되는 정보 추가

동일한 호출사이트에서 Composable을 여러번 호출(For문 등)하면 Compose는 호출 사이트 이외에도 호출 순서를 통해 Composable을 식별하게 됩니다.

@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            MovieOverview(movie) // 호출 순서로 다른 Composable임을 식별합니다.
        }
    }
}

movies의 마지막에 새로운 값이 추가했을때의 상태입니다. 색깔이 같음은 Composable함수를 재구성하지 않았음을 의미합니다.

하지만 movies의 처음 혹은 가운데에 값을 추가하거나, 재정렬하여 movies를 변경하면 매개변수가 달라진 모든 MovieOverview에서 재구성이 일어납니다.

이렇게 movie가 재정렬될 때, 모든 MovieOverview가 리컴포지션 되는것보다 MovieOverview도 재정렬 되는것이 이상적입니다. Compose에서는 이런 상황을 위해 key Composable를 사용해 Composable을 식별할 수 있습니다.

@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            key(movie.id) { // key Composable을 통해 key를 지정하였습니다.
                MovieOverview(movie)
            }
        }
    }
}

key는 호출사이트(여기서는 MoveisScreen)에서만 고유하면 되고, 다른 Composable에서는 동일한 key가 있어도 무방합니다.

이제 처음 혹은 중간에 값을 추가해도 MovieOverview에 movie의 id로 key를 부여했기 때문에 MovieOverview 인스턴트를 재사용합니다.

일부 Composable에는 key 컴포저블 기능이 내장되어있습니다. 그중 하나는 LazyColumn입니다.

@Composable
fun MoviesScreen(movies: List<Movie>) {
    LazyColumn {
        items(movies, key = { movie -> movie.id }) { movie ->
            MovieOverview(movie)
        }
    }
}

입력이 변경되지 않은 경우 건너뛰기

모든 입력이 안정적이고 변경되지 않은 경우 리컴포지션을 건너뜁니다. 동일한지 비교할때는equals메서드를 사용합니다.

안정된 타입은 다음과 같은 규칙을 준수합니다.

  • 두 인스턴스의 equals결과가 동일하면 항상 동일합니다.
  • 속성(프로퍼티)가 변경되면, Composition에 알립니다.
  • 모든 공개 속성들도 안정되어있습니다.

MutableState는 안정적이지만 변경가능한 타입입니다. 값이 변경되면 Compose에 알림이 가기 때문입니다.

Compose에서는 증명 가능한 타입만 안정적인것으로 간주합니다. 예를들어 인터페이스를 안정적이지 않은 것으로 간주하고, 구현을 변경할 수 없으며 변경할 수 있는 공개 속성(프로퍼티)이 있는 타입도 안정적이지 않은것으로 간주합니다.

안정적인 것으로 간주하게 하려면 @Stable주석을 달면 됩니다.

@Stable
interface UiState<T : Result<T>> {
    val value: T?
    val exception: Throwable?

    val hasError: Boolean
        get() = exception != null
}

@Statable 주석을 사용하지 않아도 Compose가 안정적인 것으로 간주하는 일반 유형이 있습니다.

  • 모든 원시 값 유형(Boolean, Int, Long, Float, Char 등)
  • 문자열
  • 모든 함수 유형(람다)

이렇게 Compose의 수명 주기에 대해 알아보았습니다. 다음글에서는 Compose의 수정자(Modifier)에 대해 알아보도록 하겠습니다. 끝까지 읽어주셔서 감사하고 즐거운 개발 되세요😌.

참고: 컴포저블 수명 주기

profile
항상 배울 것을 찾는 개발자입니다🔥.

0개의 댓글