본문 바로가기
안드로이드/Android

[Android] LiveData, Flow

by jinwo_o 2024. 12. 22.

LiveData

  • Lifecycle 라이브러리 중 하나로, 안드로이드 공통의 라이프사이클과 관련된 문제를 해결할 수 있게 해 주면서 앱 개발시 보다 더 유지보수하기 쉽게, 테스트하기 쉽게 만들어주는 라이브러리
  • 옵저버 패턴을 활용하여 구현되었으며, 관찰 가능한 일반 클래스인 ObservableXXX 클래스와는 달리 LiveData 는 생명주기의 변화를 인식하는 데이터 홀더 클래스이다.
    • 즉, Activity, Fragment, Service 등 안드로이드 컴포넌트의 생명 주기 인식을 통해 Active 상태에 있는 컴포넌트에서만 업데이트한다.
  • Activity 와 Fragment 는 LiveData 객체를 안전하게 관찰할 수 있고, 생명 주기가 끝나는 즉시 관찰을 멈추기 때문에 누수를 걱정하지 않아도 된다.
  • LiveData 는 옵저버 패턴을 따르기 때문에, 데이터가 변경될 때 Observer 객체에 알린다. 이러한 Observer 를 통해 UI 가 자동으로 업데이트되므로, 개발자가 직접 업데이트할 필요가 없다.
  • Activity 가 Back Stack 에 있을 때를 비롯하여 Observer 의 생명 주기가 비활성 상태에 있으면 Observer 는 어떤 LiveData 이벤트도 받지 않아 비정상 종료가 발생하지 않게 된다.
  • 생명 주기가 비활성화(InActive)되었다가 다시 활성화(Active)될 때 최신 데이터를 수신한다.
  • 즉, LiveData 는 구성 변경 시에 안전성으 렞공하고 최신 데이터를 View 로 전달하는 역할을 한다.
  • Data Layer 클래스에서 LiveData 객체를 작업하고 싶을 수 있지만, LiveData 는 비동기 데이터 스트림을 처리하도록 설계되지 않았다.
    • LiveData transfromation 과 MediatorLiveData 등을 통해 이를 처리하게 할 수는 있겠지만, 모든 LiveData 의 관찰은 오직 Main Thread 에서만 진행되기 때문에 한계점을 갖고 있다.
    • Repository 에서는 LiveData 를 사용하지 않도록 권장하면서 동시에 Kotlin Flow 를 사용하도록 권장하고 있다.
  • UI 와 밀접하게 연관되어 있기 때문에, Data Layer 에서 비동기 방식으로 데이터를 처리하는 자연스러운 방법이 없다.
  • 안드로이드 플랫폼에 속해 있기 때문에, 순수 Java /Kotlin 을 사용하는 Domain Layer 에서 사용하기에는 적합하지 않다.

 

Flow

  • 코루틴 상에서 단일 값만 반환하는 suspend function(정지 함수)과 달리, 여러 값을 순차적으로 내보낼 수 있는 데이터 스트림이며, *리액티브 프로그래밍을 지원하기 위한 구성요소
    • 리액티브 프로그래밍
      • 데이터가 변경될 때 이벤트를 발생시켜 지속적으로 데이터를 전달하는 프로그래밍 방식
      • 하나의 데이터를 발행하는 발행자가 있고, 해당 발행자는 데이터 소비자에게 지속적으로 데이터를 전달하는 역할을 한다.
        • 이러한 흐름을 데이터 스트림이라고 한다
      • 기존의 명령형 프로그래밍에서는 데이터 소비자가 데이터를 요청한 후, 받은 결괏값을 일회성으로 수신한다.
        • 이러한 방식은 데이터가 필요할 때마다 결괏값을 매번 요청해야 하므로 매우 비효율적이다.
  • 코루틴 상에서 Flow 는 리액티브 프로그래밍을 지원하기 위해 만들어진 구현체이다.
    • 코루틴에서 데이터 스트림을 구현하기 위해서는 Flow 를 사용해야 한다.
  • 데이터의 흐름(flow)를 발생시키기만 할 뿐 데이터가 저장되지 않는다.
  • 데이터 스트림의 구성 요소는 Producer(생산자), Intermediary(중간 연산자), Consumer(소비자)로 이루어져 있다.
  • UseCase, Repository, DataSources Layer 와 긴밀하게 작동해 데이터를 수집 및 처리해서 서로 다른 코루틴 범위에서 작업을 실행한다.
  • 스스로 안드로이드 생명주기에 대해 알지 못하기 때문에, 라이프사이클에 따른 중지나 재개가 어렵다.
  • 상태가 없어 값이 할당된 것인지, 현재 값은 무엇인지 알기가 어렵다.
  • Cold Stream 방식으로, 연속해서 계속 들어오는 데이터를 처리할 수 없으며 collect 되었을 때만 생성되고 값을 반환한다.
    • 하나의 Flow 빌더에 여러 개의 collector 가 있을 경우, 각 collector 가 독립적으로 데이터를 호출하게 되므로, 업스트림 로직이 비용이 많이 드는 DB 접근이나 서버 통신을 포함한다면 여러 번 리소스를 요청하게 될 수 있다.

 

Producer(생산자)

  • 데이터를 발행하는 역할을 한다.
  • Flow 에서의 Producer 는 flow { } 블록 내부에서의 emit()을 통해 데이터를 생성한다.
  • 안드로이드 상에서 생산자가 가져오는 데이터의 대표적인 DataSource 는 두가지이다.
    • 1. 서버의 데이터로 보통 REST API(Remote Source)를 이용해 가져오는 데이터
    • 2. 휴대폰 상의 DB(Local DataSource)에서 가져오는 데이터

 

Intermediary(중간 연산자)

  • 생산자가 데이터를 생성했으면 중간 연산자는 생성된 데이터를 수정한다.
  • map(데이터 변형), filter(데이터 필터링), onEach(모든 데이터마다 연산 수행) 등의 중간 연산자가 있다.
  • 중간 연산자는 생산자가 생성한 데이터를 변환하여 소비자에게 전달한다.

 

Consumer(소비자)

  • Flow 에서는 collect 를 이용해 전달된 데이터를 소비할 수 있다.

  • 방법 1 : Flow 로부터 collect 한 데이터를 ViewModel 에 저장하여 사용하기 위해, 별도의 데이터 홀더 변수를 만들어야 한다. 또한, 데이터 홀더 변수는 Reactive 하지 않기 때문에 UI 에서 해당 데이터 홀더 변수를 구독하기 위해서는 별도의 fetching(데이터를 가져오는) 로직을 만들어야 한다.
  • 방법 2 : Flow 로부터 collect 한 데이터를 ViewModel 에 저장하여 사용하기 위해, ViewModel 에서 데이터 홀더 변수와 Flow 를 함께 활용한다. Flow 를 구독하고, 데이터 홀더 변수는 Flow 에서 마지막으로 발행한 데이터를 저장하고 있으면 된다. 따라서, UI 에서는 Flow 에서 값을 발행하기 전, 데이터 홀더 변수의 데이터를 사용할 수 있다.
  • 하지만, 이 둘 모두 보일러 플레이트 코드를 만들어낸다.

 

StateFlow

  • 현재 상태와 새로운 상태 업데이트를 collector 에 내보내는 Observable 한 State Holder Flow
  • 데이터 홀더(저장소) 역할을 하면서 동시에 Flow 의 데이터 스트림 기능도 수행한다.
  • UI 에서 StateFlow 를 구독하여 UIState(UI를 위한 데이터)를 업데이트하면 화면이 재구성될 때마다 서버에 데이터를 요청할 필요가 없어진다.
  • MutableStateFlow 업데이트를 담당하는 클래스가 생산자고, StateFlow 에서 수집되는 모든 클래스가 소비자다.
  • StateFlow 가 항상 Flow 를 구독하면 메모리 누수가 발생할 수 있으므로, stateIn 함수를 사용하여 이 StateFlow 가 유지되어야 하는 CoroutineScope 를 명시해야한다.
  • 안드로이드 플랫폼에 종속적이었던 LiveData 와는 달리, StateFlow 는 순수 kotlin 라이브러리이기 때문에 Domain Layer 에서 사용할 수 있다.
  • 코루틴을 통해 Work Thread 에서도 비용이 많이 드는 데이터 스트림을 처리할 수 있기 때문에 Data Layer 에서 LiveData 를 사용하는 것보다 향상된 성능으로 사용 가능하다.
  • zip, flatMapMerge 등 다양한 Flow API 를 사용할 수 있기 때문에 LiveData 보다 풍부하게 활용할 수 있다.

 

[Coroutine Flow] 1. Flow란 무엇인가?

Coroutine의 Flow는 데이터 스트림이며, 코루틴 상에서 리액티브 프로그래밍 지원 하기 위한 구성요소이다. 이를 이해하기 위해서는 먼저 리액티브(반응형) 프로그래밍이 무엇인지, 그리고 Flow가 리

kotlinworld.com

 

[Coroutine Flow] 2. Flow와 StateFlow의 차이는 무엇인가?

Flow의 한계 Flow는 데이터의 흐름이다. Flow는 데이터의 흐름(flow)을 발생시키기만 할 뿐 데이터가 저장되지 않는다. 따라서 flow만을 이용해 안드로이드의 UIState를 업데이트 하기 위해서는 두가지

kotlinworld.com

 

[Coroutine Flow] 3. stateIn 사용하여 Flow를 StateFlow로 변환하기

Flow와 StateFlow 우리는 리액티브 프로그래밍을 할 때 여러 데이터 흐름(flow)를 하나로 합쳐 하나의 데이터 흐름(Flow)으로 만들어낸다. 예를 들어 아래의 그림3에서는 Flow가 3개 있고 이것이 합쳐져

kotlinworld.com

 

[Android] LiveData VS StateFlow, 왜 StateFlow 를 써야할까?

LiveData 는 Lifecycle 라이브러리 중 하나로, 안드로이드 공통의 라이프사이클과 관련된 문제를 해결할 수 있게 해 주면서 앱 개발시 보다 더 유지보수하기 쉽게, 테스트하기 쉽게 만들어주는 라이

readystory.tistory.com

 

[Android] Flow vs LiveData

Flow와 LiveData는 API를 통해 데이터를 받아올 때 자주 사용되는 요소들이다. MVVM 패턴으로 앱을 설계한 경우 뷰모델에서 데이터 바인딩을 통해 UI에 변경된 데이터를 표시할 수 있도록 뷰모델 안에

onlyfor-me-blog.tistory.com