
컴포즈의 사용 이유와 선언형 UI에 대해 알아보았다면, 이제 코드랩을 열어보자. 벌써부터 처음보는게 생긴다. 바로 컴포저블 ㅎ ㅎ .. ^^ 오늘은 컴포저블이 무엇인지 어떻게 쓰이는지 상태 관리는 어떻게 하는지에 대해 공부해보도록 하자.
용어 정리
- 컴포저블 함수
- 데이터를 수신할 수 있고, UI를 만들기 위해 수신받은 데이터를 사용하며, 사용자가 화면에서 볼 수 있는 UI 구성요소를 내보낸다.
- 컴포지션
- Jetpack Compose가 컴포저블을 실행할 때 빌드한 UI
- UI를 기술하는 컴포저블의 트리 구조
- 리컴포지션
- 데이터가 변경될 때 컴포지션을 업데이트하기 위해 컴포저블을 다시 실행하는 것
컴포저블의 생명 주기
컴포즈는 초기 컴포지션 시 처음으로 컴포저블을 실행할 때 컴포지션에서 UI를 표현하기 위해서 해당 컴포저블을 계속해서 추적한다. 그리고 앱의 상태가 바뀌면, 컴포즈는 리컴포지션을 스케줄한다.
따라서 요약하면 컴포저블의 생명주기는 다음과 같다.
- 컴포지션 진입
- 리컴포지션
- 컴포지션 종료

컴포지션은 초기 컴포지션으로만 생성되고 리컴포지션으로만 업데이트된다. 컴포지션을 바꾸는 유일한 방법은 리컴포지션임을 기억하자.
또 컴포저블에 대해 다음을 기억하자.
- 컴포저블 함수는 순서와 관계없이 실행할 수 있다
- 컴포저블 함수는 동시에 실행할 수 있다
- 컴포저블 함수는 애니메이션의 모든 프레임에서와 같은 빈도로 매우 자주 실행될 수 있다
리컴포지션
그렇다면 리컴포지션은 무엇일까 ? 먼저 배경에 대해 알아보자. 이전 포스트에서 말했듯이 컴포즈는 기존xml 뷰와 다르게 앱이 화면을 그리면 변경할 수 없다. 그러면 필요 시 어떻게 화면을 업데이트하냐고 ? 바로 컴포저블의 상태를 변경함으로서 구현한다.
먼저 예제를 살펴보자.
@Composable
private fun HelloContent() {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Hello!",
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.bodyMedium
)
OutlinedTextField(
value = "",
onValueChange = { },
label = { Text("Name") }
)
}
}
위 코드를 실행했을 때 OutlinedTextField(xml 기반에선 editText라고 생각하면 된다)에 텍스트를 입력하면 의도처럼 텍스트의 값이 변하지 않을 것이다. 이는 TextField가 자체적으로 업데이트되지 않고 value 매개변수가 변경될 때 업데이트되기 때문이다.
리컴포지션이란 데이터가 변경될 때 컴포지션을 업데이트 하기 위해 컴포저블을 다시 실행하는 것으로, 컴포저블의 입력값이 변경될 때만 실행된다. 이전 포스트에서 '컴포즈는 특정 시점에 UI의 어떤 부분을 다시 그려야 하는지를 지능적으로 선택할 수 있다' 라고 언급한 적이 있는데, 그게 바로 리컴포지션이다. 컴포즈는 변경된 컴포저블만 똑똑하게 리컴포지션할 수 있고, 이게 바로 전체 UI 트리를 재구성했던 기존의 명령형 UI (xml 기반 뷰)에 비해 효율적이라고 불리우는 이유이다.
리컴포지션은 일반적으로 State<T> 객체가 변경되면 트리거된다. Compose는 이러한 객체를 추적하고 컴포지션에서 특정 State<T>를 읽는 모든 컴포저블 및 호출하는 컴포저블 중 건너뛸 수 없는 모든 컴포저블을 실행한다.
또 리컴포지션에 대해 다음을 기억하자.
- 리컴포지션은 최대한 많은 수의 구성 가능한 함수 및 람다를 건너뛴다
- 리컴포지션은 낙관적이며 취소될 수 있다
remeber
리컴포지션까지 이해하고 나면 이런 궁금증이 들 수 있다.
만약 리컴포지션이 끝나기전에 동일한 컴포저블에 대하여 다른 리컴포지션이 필요한 경우 어떻게 될까 ?
아주 좋은 생각이다. 이 경우에 컴포저블은 리컴포지션을 취소하고 새 상태로 리컴포지션을 다시 시작한다.
또, 리컴포지션 시 이전의 데이터는 따로 저장해두지 않아도 유지가 될까 ? 아니다. 이게 앞으로 이야기할 remember의 등장배경이다.
컴포저블 함수는 remember API를 사용해 메모리에 객체를 저장할 수 있다. 이 remember에 의해 계산된 값은 컴포지션 중에 컴포지션에 저장되고, 저장된 값은 리컴포지션 중에 반환된다. remember는 변경 가능한 객체뿐만 아니라 변경할 수 없는 객체를 저장하는 데 사용할 수 있다. 그리고 이 remember를 호출한 컴포저블이 컴포지션에서 삭제되면 저장한 객체 또한 삭제한다.
런타임 시 컴포즈에서는 관찰 가능한 MutableState<T>를 생성하는 mutableStateOf를 관찰 가능하고, 컴포저블에서는 이 MutableState 객체를 관찰한다. 그리고 컴포저블에서 이 객체를 선언하는데는 세가지 방법이 있다.
- val mutableState = remember { mutableStateOf(default) }
- var value by remember { mutableStateOf(default) }
- val (value, setValue) = remember { mutableStateOf(default) }
또 화면 회전과 같이 구성 변경에까지 대응하는 데이터 저장에는 rememberSaveable 을 사용한다.
이렇게 remember와 mutableState를 활용하면 리컴포지션 시 데이터를 기억할 수 있다. 위의 예제는 이를 적용해 다음과 같이 변경하면 정상적으로 동작한다.
@Composable
fun HelloContent() {
Column(modifier = Modifier.padding(16.dp)) {
var name by remember { mutableStateOf("") }
if (name.isNotEmpty()) {
Text(
text = "Hello, $name!",
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.bodyMedium
)
}
OutlinedTextField(
value = name,
onValueChange = { name = it },
label = { Text("Name") }
)
}
}
이렇게 이번 포스트에서는 컴포저블과 컴포지션을 알아보면서 생명주기와 리컴포지션과 remember까지 공부해보았다. 이어서는 컴포저블의 상태에 대해서 알아보자.
참고자료
Compose 이해 | Jetpack Compose | Android Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. Compose 이해 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Jetpack Compose는 Android를 위한 현대적인 선언
developer.android.com
상태 및 Jetpack Compose | Android Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. 상태 및 Jetpack Compose 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 앱의 상태는 시간이 지남에 따라
developer.android.com
'안드로이드 > 컴포즈' 카테고리의 다른 글
| [Android][Compose] 컴포즈의 3단계, 상태, 컴포지션의 생명주기, 콜 사이트 (0) | 2025.02.27 |
|---|---|
| [Android][Compose] 선언형 UI 컴포즈, 컴포지션 (0) | 2025.02.26 |
| [Android][Compose] 네비게이션 구현하기 (0) | 2024.07.18 |
| [Android][Compose] State와 상태 호이스팅 (0) | 2024.07.05 |
| [Android][Compose] 컴포즈의 이해 (0) | 2024.07.04 |