본문 바로가기
Android

[Android] LiveData vs StateFlow: 안드로이드 상태 관리의 진화

by 중곰 2025. 2. 5.

안녕하세요. 중곰입니다.

 

오늘은 ViewModel에서 데이터 처리 시 변경 데이터를

어떻게 관찰하고 동작하는지를 볼 수 있는

LiveData와 StateFlow를 살펴볼려고 합니다.

 

개념 정도를 살펴보면서 어떤 형태이며

언제 사용하면 좋은지까지 살펴보려 합니다.

먼저 LiveData와 StateFlow에 대해 간단히 살펴 봅니다.

LiveData?

  • LiveData
    • 관찰 가능한 데이터 홀더 클래스이며, 수명주기를 인식함
    • 액티비티, 프래그먼트, 서비스 등 다른 앱 구성요소의 수명 주기를 고려
    • 수명 주기 인식을 통해 LiveData는 활동 수명 주기 상태에 있는 앱 구성요소 관찰자만 업데이트
    • 쉽게 말해 데이터가 변경될 때 화면을 자동으로 업데이트해주는 마법 상자
  • Observer 클래스
    • 관찰자의 수명주기가 STARTED or RESUMED 상태일때 LiveData 관찰자를 활성 상태로 간주
    • 활성 관찰자에게만 업데이트 정보 알림
  • LifeCycleOwner 인터페이스를 구현하는 객체와 페이링된 관찰자를 등록 할 수 있음
    • 관찰자에 대응되는 Lifecycle 객체의 상태가 DESTORYED 시 관찰자를 삭제 할 수 있음
  • 액티비티와 프래그먼트는 LiveData 객체를 안전하게 관찰
  • 수명주기가 끝나는 즉시 수신 거부되어 누수를 걱정하지 않아도 됨
  • 간단한 예시
  • 특징
    • Observer 패턴을 기반으로 동작
    • 항상 최신 데이터만 유지
    • 안드로이드 생명주기와 통합
    • 자동으로 메모리 누수 방지
  • 장점
    • 생명주기 자동 관리 (메모리 누수 걱정 없음)
    • 설정 변경(화면 회전 등) 자동 처리
    • 안드로이드 플랫폼과의 완벽한 통합
    • 간단한 구현
  • 단점
    • 메인 스레드에서만 값 변경 가능
    • 코루틴 지원 제한적
    • 안드로이드 플랫폼 의존적
class MainViewModel : ViewModel() {
    // LiveData 생성되며, 내부에서만 변경 가능
    private val _count = MutableLiveData<Int>(0)
    // LiveData 외부에 노출되는 읽기 전용
    val count: LiveData<Int> = _count
    
    fun increment() {
        _count.value = (_count.value ?: 0) + 1
    }
}

// Activity/Fragment에서
viewModel.count.observe(viewLifecycleOwner) { count ->
    textView.text = count.toString()
}

StateFlow

  • 현재 상태와 새로운 상태 업데이트를 수집기에 내보내는 관찰 가능한 상태 홀더 흐름
  • value 속서을 통해서도 현재 상태를 값을 읽을 수 있음
  • 상태를 업데이트하고 흐름을 전송하려면 MutableStateFlow 클래스의 value 속성에 새 값을 할당
  • 쉽게 보면, LiveData의 “업그레이드 버전” 이라 생각하면 되는데, 코루틴 기반의 핫 스트림으로 동작하는 상태 홀더
  • 간단한 예시
class MainViewModel : ViewModel() {
    private val _count = MutableStateFlow<Int>(0)
    val count: StateFlow<Int> = _count.asStateFlow()
    
    fun increment() {
        viewModelScope.launch {
            _count.value = _count.value + 1
        }
    }
}

// Activity/Fragment에서
lifecycleScope.launch {
    viewModel.count.collect { count ->
        textView.text = count.toString()
    }
}
  • 특징
    • Hot Stream (구독자가 없어도 데이터 발행)
    • 항상 값을 가짐 (null 불가)
    • 중복 값 발행
    • distinctUntilChanged() 내장
  • 장점
    • 코루틴과 완벽한 통합
    • 백그라운드 스레드에서 값 변경 가능
    • Flow 연산자 사용 가능 (map, filter 등)
    • 플랫폼 독립적
    • Hot Stream (항상 최신 값 유지)
  • 단점
    • 생명주기 수동 관리 필요
    • 초기값 필수
    • LiveData보다 약간 복잡한 설정

🤔 뭘 써야할까요?

LiveData를 쓰면 좋을 때

  • 간단한 화면 업데이트가 필요할 때
  • 생명주기 관리를 자동으로 하고 싶을 때
  • 기존 안드로이드 앱을 유지보수할 때

StateFlow를 쓰면 좋을 때

  • 복잡한 데이터 처리가 필요할 때
  • 백그라운드 작업이 많을 때
  • 최신 안드로이드 기술을 사용하고 싶을 때

개인적 생각으로 사용 추천한다면?

  • 단순 UI 상태 관리: LiveData
  • 복잡한 데이터 스트림/비동기 처리: StateFlow
  • 코루틴 사용이 많은 프로젝트: StateFlow
  • 레거시 프로젝트 유지보수: LiveData

💡 실제 사례로 이해하기

게임 앱을 만든다고 생각해볼까요?

// LiveData 사용 - 간단한 점수 표시
class SimpleGameViewModel : ViewModel() {
    private val _score = MutableLiveData(0)
    val score: LiveData<Int> = _score
    
    fun addScore() {
        _score.value = (_score.value ?: 0) + 10  // 메인 스레드에서 실행
    }
}

// StateFlow 사용 - 복잡한 게임 상태 관리
class AdvancedGameViewModel : ViewModel() {
    private val _gameState = MutableStateFlow(GameState())
    val gameState = _gameState.asStateFlow()
    
    fun processGameAction(action: GameAction) {
        viewModelScope.launch(Dispatchers.IO) {
            // 복잡한 게임 로직 처리
            val newState = calculateNewState(action)
            _gameState.value = newState
        }
    }
}

🎯 핵심 포인트

  • LiveData는 UI 업데이트에 최적화되어 있고, 안드로이드에 종속적
  • StateFlow는 복잡한 데이터 처리에 강점
  • LiveData는 안드로이드 생명주기에 특화된 관찰 가능한 데이터 홀더이고, StateFlow는 코루틴 기반의 반응형 스트림
  • 둘 다 데이터 변경을 관찰하는 도구
  • 프로젝트 상황에 맞게 선택하면 됨

 

글을 읽어주셔서 감사합니다.

 

 

 

참고문헌:

 

 

 

 

 

 

 

 

반응형