Jetpack Compose의 produceState
Jetpack Compose의 produceState
produceState 함수는 컴포지션(Composition) 내부에서 코루틴을 실행하여 State 객체의 값을 생성하는 Compose API입니다. 네트워크 요청, 데이터베이스 쿼리, 장기 실행 연산 등 비동기 작업의 결과를 Compose의 반응형 상태(reactive state) 시스템에 연결하는 다리 역할을 합니다. 이 코루틴은 컴포지션의 생명주기에 맞춰 자동으로 관리되며, 컴포저블이 컴포지션을 벗어나면 자동으로 취소됩니다. 이번 면접 질문을 통하여 아래 내용들을 학습하실 수 있습니다.
produceState가 코루틴을 실행하고 컴포지션 내에서 상태를 업데이트하는 메커니즘keys매개변수가 코루틴 재시작 동작을 제어하는 방식LaunchedEffect와 별도의MutableState를 조합하는 방식 대비produceState가 더 적합한 상황- 컴포저블 함수에서 비동기 데이터 가져오기에
produceState를 올바르게 적용하는 방법
produceState의 동작 원리
produceState는 초기값, 선택적 키(key), 그리고 suspend 람다(producer lambda)를 인자로 받아 State<T> 객체를 반환합니다. 컴포저블이 반환하는 State<T> 객체를 관찰(observe)하면, 컴포저블이 컴포지션에 진입하는 시점에 프로듀서 코루틴이 시작되고, 컴포지션을 벗어나면 해당 코루틴이 자동으로 취소됩니다.
@Composable
fun <T> produceState(
initialValue: T,
vararg keys: Any?,
producer: suspend ProduceStateScope<T>.() -> Unit
): State<T>
프로듀서 람다 내부에서 value 프로퍼티를 업데이트하면, 반환된 상태를 읽고 있는 모든 컴포저블에서 리컴포지션(Recomposition)이 트리거됩니다. 이러한 구조 덕분에 비동기 작업의 결과가 UI에 자연스럽게 반영됩니다.
실전 예제
가장 대표적인 사용 사례는 네트워크에서 데이터를 가져와 UI에 반영하는 패턴입니다.
@Composable
fun UserProfile(userId: String) {
val userState by produceState<User?>(
initialValue = null,
key1 = userId
) {
value = fetchUserFromNetwork(userId) // 네트워크에서 사용자 정보 가져오기
}
if (userState == null) {
Text("Loading...")
} else {
Text("User: ${userState?.name}")
}
}
프로듀서 코루틴은 UserProfile이 컴포지션에 진입할 때 실행됩니다. userId가 변경되면 기존 코루틴이 취소되고 업데이트된 키로 새로운 코루틴이 실행됩니다. 초기값이 null인 동안 UI에는 "Loading..."이 표시되며, 네트워크 호출이 완료되면 사용자 이름이 화면에 나타납니다. 이처럼 produceState를 활용하면 비동기 로딩 상태와 결과 표시를 간결하게 처리할 수 있습니다.