본문 바로가기
Android/Coroutine

[Android/Coroutine] SharingStarted.WhileSubscribed(): 효율적인 Flow 공유 전략

by quessr 2025. 3. 20.

 

Flow를 UI에서 구독할 때 불필요한 리소스 낭비를 방지하는 것이 중요합니다.
SharingStarted.WhileSubscribed()를 사용하면 구독자가 있을 때만 데이터를 방출하고, 없으면 정지하는 방식으로 Flow를 최적화할 수 있다는 것을 알게 되었습니다.

이번 글에서는 SharingStarted.WhileSubscribed()가 무엇인지, 그리고 어떤 상황에서 유용한지 공부한 내용을 정리해두겠습니다.


1. SharingStarted란?

SharingStarted는 Flow를 여러 곳에서 공유할 때 흐름을 언제 시작하고, 언제 중지할지를 결정하는 전략입니다.
이를 활용하면 ViewModel에서 Flow 데이터를 공유하고, UI에서 구독할 때 불필요한 연산을 줄일 수 있습니다.

SharingStarted 옵션 비교

옵션 동작 방식
Eagerly 앱이 실행되면 즉시 Flow를 시작하고 항상 유지합니다.
Lazily 구독이 생길 때만 시작하지만, 구독이 없어지면 정지됩니다.
WhileSubscribed() 구독이 있을 때만 데이터를 방출하고, 없으면 정지됩니다.

이 중 WhileSubscribed()는 UI에서 구독자가 있을 때만 Flow를 유지하고, 구독자가 없어지면 정지하여 리소스를 절약하는 데 효과적입니다.


2. WhileSubscribed()의 기본 사용법

예를 들어, 1초마다 새로운 데이터를 방출하는 Flow를 UI에서 StateFlow로 변환하여 사용할 때, WhileSubscribed()를 적용할 수 있습니다.

ViewModel에서 Flow를 공유하는 코드

class MyViewModel : ViewModel() {
    private val _dataFlow = flow {
        while (true) {
            emit("New Data: ${System.currentTimeMillis()}")
            delay(1000) // 1초마다 데이터 방출
        }
    }

    val sharedFlow = _dataFlow
        .stateIn(
            viewModelScope,
            SharingStarted.WhileSubscribed(5000), // 5초 동안 구독자가 없으면 정지
            "Initial Data"
        )
}

설명

  • _dataFlow는 1초마다 새로운 데이터를 방출하는 Flow입니다.
  • stateIn()을 사용하여 Flow를 StateFlow로 변환하여 UI에서 활용할 수 있습니다.
  • SharingStarted.WhileSubscribed(5000)을 적용하면
    구독자가 없으면 5초 뒤 Flow가 정지됩니다.
    5초 이내에 구독자가 다시 생기면 흐름이 유지됩니다.

3. WhileSubscribed()가 동작하는 방식

구독자 변화에 따른 Flow의 상태

시점 Flow 상태
ViewModel이 생성됨 Flow가 아직 시작되지 않음
UI에서 sharedFlow 구독 시작 데이터 방출 시작
UI에서 구독 중단 (예: 화면 이동) 5초 대기 후 Flow 정지
다시 구독 시작 데이터 방출 재개

구독이 있을 때만 데이터를 유지하고, 없으면 정지하여 불필요한 연산을 방지할 수 있습니다.


4. stopTimeoutMillis 옵션 활용하기

SharingStarted.WhileSubscribed(stopTimeoutMillis = 5000)

이 옵션의 역할

  • 구독이 끊긴 후에도 일정 시간(5초) 동안 Flow를 유지합니다.
  • 5초 이내에 다시 구독이 시작되면 Flow를 중단하지 않고 그대로 유지됩니다.
  • 네트워크가 순간적으로 끊기거나, UI가 잠깐 변경되더라도 부드러운 데이터 유지가 가능합니다.

예제: stopTimeoutMillis 설정을 활용한 부드러운 전환

val sharedFlow = _dataFlow.stateIn(
    viewModelScope,
    SharingStarted.WhileSubscribed(3000), // 3초 후 정지
    "Initial Data"
)

 

구독이 없어지더라도 3초 이내에 다시 구독이 시작되면 Flow를 유지합니다.
너무 짧은 값(예: 0ms)으로 설정하면 UI 이동 시 데이터 흐름이 끊길 수 있으므로 적절한 값 설정이 필요합니다.


결론

  • WhileSubscribed()는 UI에서 Flow를 사용할 때 리소스를 절약하는데 유용한 전략입니다.
  • 구독이 있을 때만 데이터를 방출하고, 구독이 끊기면 정지하여 불필요한 작업을 방지할 수 있습니다.
  • stopTimeoutMillis 옵션을 사용하면 부드러운 상태 전환이 가능합니다.
반응형