Flow의 한계
Flow는 데이터의 흐름이다. Flow는 데이터의 흐름(flow)을 발생시키기만 할 뿐 데이터가 저장되지 않는다.
따라서 flow만을 이용해 안드로이드의 UIState를 업데이트 하기 위해서는 두가지 방법이 가능했다.
- 화면이 재구성 될때마다 다시 서버 혹은 DB로부터 데이터 가져오기
- Flow로부터 collect한 데이터를 ViewModel에 저장해놓고 사용하기
1번 방법은 비효율적이다. 예를 들어 안드로이드에서는 화면이 회전되었을 때마다 onDestroy가 호출된 후 다시 onCreate이 호출되는데, 이때마다 새로운 데이터를 서버 혹은 DB로부터 가져와야 하기 때문이다.
2번 방법은 효율적이다. 아래 그림의 ViewModel이 살아있는 범위에서 볼 수 있듯이 ViewModel은 onDestroy가 호출되더라도 살아있고 ViewModel에서 해당 데이터를 저장하고 있으면 되기 때문이다.
하지만, 2번 방법에서 데이터를 저장하고 있으려면 별도의 데이터 홀더 변수를 만들어야 한다. 또한 데이터 홀더 변수는 Reactive하지 않기 때문에 UI에서 해당 데이터 홀더 변수를 구독하기 위해서는 별도의 fetching 로직을 만들어야 한다.
*fetching로직: 데이터를 가져오는 로직
2번을 구현하는 다른 방법은 ViewModel에서 데이터 홀더 변수와 flow를 같이 사용하는 것이다. flow를 구독하고 데이터 홀더 변수는 flow에서 마지막으로 발행한 데이터를 저장하고 있으면 된다. 따라서 UI에서는 flow에서 값을 발행하기 전에는 데이터 홀더 변수의 데이터를 사용하면 된다. 이 방식으로 만들면 데이터 홀더 변수가 마지막 데이터를 저장하고 있으므로 다시 서버로 데이터를 요청할 필요가 없어진다. 이 방법이 가장 적합하다.
하지만 문제는 이 둘 모두 보일러 플레이트 코드를 만들어낸다는 것이다. 안드로이드에서 수집하는 UIState(UI를 위한 데이터)가 한 두개가 아닌데 모두를 구독하기 위해서 비슷한 코드를 매번 작성해 가독성을 떨어트리는 것은 지양해야 한다.
*보일러 플레이트 : 비슷한 코드가 반복되는 것
이러한 문제점을 해결하기 위해 등장한 것이 바로 StateFlow이다.
StateFlow의 등장과 Flow의 한계 극복
StateFlow는 데이터 홀더(저장소) 역할을 하면서 Flow의 데이터 스트림 역할까지 한다. UI단에서 StateFlow를 구독해 UIState(UI를 위한 데이터)를 업데이트 하면 화면이 재구성될 때 마다 다시 서버로 데이터를 요청할 필요가 없어진다. UI는 단순히 StateFlow를 구독만 하고 있으면 되는 것이다.
이를 표시한 것이 바로 아래의 그림3이다.
다음 글 위 그림3을 해석하고 Flow를 StateFlow로 변환하는 과정에 대해 알아볼 것이다.
Kotlin Coroutines 공식 기술 문서 번역이 GitHub 오픈소스로 배포되었습니다. Starganizer가 되어 오픈소스를 지지해주세요.