면접 질문실전 질문꼬리 질문

컴포저블 함수에서 Flow를 안전하게 수집하기

skydovesJaewoong Eum (skydoves)||7분 소요

컴포저블 함수에서 Flow를 안전하게 수집하기

컴포저블(composable) 함수 내부에서 Flow를 수집하는 것은 UI 상태를 관리하고 데이터 변경에 반응하기 위해 매우 흔히 사용되는 패턴입니다. 그러나 이를 올바르게 관리하지 않으면 메모리 누수, 불필요한 백그라운드 작업, 과도한 리컴포지션(Recomposition) 등 다양한 문제가 발생할 수 있습니다. Jetpack Compose는 Flow를 관찰 가능한 상태(state)로 변환하기 위한 두 가지 핵심 API를 제공합니다. 바로 collectAsStatecollectAsStateWithLifecycle입니다. 이 두 API가 컴포지션 생명주기 및 안드로이드 Activity 생명주기와 각각 어떻게 상호작용하는지 이해하는 것은 효율적이고 메모리 누수 없는 UI를 구축하는 데 필수적입니다. 특히 실제 면접에서는 단순히 API 사용법만 아는 것이 아니라, 내부 동작 원리와 생명주기에 따른 동작 차이까지 설명할 수 있어야 하므로 꼼꼼히 학습하시길 권장합니다.

이번 면접 질문을 통하여 아래 내용들을 학습하실 수 있습니다.

  • collectAsStateFlow를 Compose State 객체로 변환하는 방식을 설명할 수 있습니다.
  • collectAsState가 UI가 백그라운드에 있을 때도 수집을 멈추지 않는 이유를 파악할 수 있습니다.
  • collectAsStateWithLifecycle이 안드로이드 생명주기에 Flow 수집을 연동하는 원리를 이해할 수 있습니다.
  • 생명주기 인식 여부에 따라 올바른 API를 선택하는 기준을 세울 수 있습니다.

collectAsState 사용법

collectAsStateFlow를 수집하여 새로운 값이 방출(emit)될 때마다 리컴포지션을 트리거하는 State 객체로 변환합니다. 컴포저블이 컴포지션에 진입하면 수집을 시작하고, 컴포지션에서 벗어나면 수집을 중단합니다.

@Composable
fun UserProfileScreen(viewModel: UserViewModel) {
    val userName by viewModel.userNameFlow.collectAsState(initial = "")

    Column {
        Text(text = "User: $userName")
    }
}

위의 예제에서 userNameFlow는 상태(state)로 수집되며, 새로운 값이 방출될 때마다 UI가 리컴포지션됩니다. 하지만 collectAsState는 안드로이드 생명주기를 인식하지 않는다는 점에 주의해야 합니다. 컴포저블이 메모리에 남아 있지만 실제로 화면에 표시되지 않는 상황, 가령 사용자가 다른 화면으로 이동한 경우에도 Flow 수집이 계속 진행됩니다. 네트워크 호출이나 센서 데이터 같은 비용이 높은 Flow에서는 불필요한 리소스 낭비가 발생할 수 있으므로, 이 점을 면접에서도 명확히 짚어주는 것이 좋습니다.

collectAsStateWithLifecycle 사용법

collectAsStateWithLifecycle은 생명주기를 인식하는 대안입니다. 호스트 Activity 또는 Fragment가 백그라운드로 이동하면 Flow 수집을 일시 중단하고, 포그라운드로 복귀하면 수집을 재개합니다.

@Composable
fun UserProfileScreen(viewModel: UserViewModel) {
    val userName by viewModel.userNameFlow
        .collectAsStateWithLifecycle(initialValue = "")

    Column {
        Text(text = "User: $userName")
    }
}

이 API는 호스트의 Lifecycle을 관찰하며, 기본적으로 생명주기가 최소 STARTED 상태일 때만 수집을 수행합니다. UI가 백그라운드로 이동하면 수집이 자동으로 중단되고, 포그라운드로 돌아오면 Flow가 마지막으로 중단된 지점부터 수집을 재개합니다. 이러한 동작 덕분에 사용자가 화면을 보고 있지 않을 때 불필요한 연산을 방지할 수 있습니다.

이 면접 질문은 구독자 전용입니다

Dove Letter를 구독하시면 안드로이드, 코틀린 개발 관련 독점 면접 질문의 전체 내용을 볼 수 있습니다.

구독하기