Flow와 StateFlow는 좀 어렵긴한데 많은 차이가 있습니다.
대략 Flow -> StateFlow -> MutableStateFlow 이렇게 상속관계가 있는데요.
Flow는 자체상태유지가 없고, collector/observer 가 구독을 해줘야 flow가 실행됩니다.(cold라고 부릅니다.)
StateFlow는 이름에서 알수있듯 상태가 있고(async완료 전에도 리턴할게 필요하니까 초기값도 필요하죠), collector/observer가 없을수도 하나일수도 여러개가 붙어서 read할수도 있습니다(hot이라 부릅니다). Mutable까지 붙으면 여러군데서 write도 할수있구요.
Flow
- Cold Stream : collector/observer가 데이터를 subscribe 해주어야 실행된다.
- 데이터 흐름을 처리하지만, 상태를 유지하지 않고, 데이터를 생산하고 소비만 한다.
- 네트워크 요청, 파일 읽기, 데이터베이스 읽기 등 일회성 비동기 작업에 주로 사용한다
- 데이터 생산이 고비용 작업인 경우, Flow의 다중 구독은 동일한 작업을 반복하게 되어 비효율적이다 (다중 구독 X)
StateFlow
- Hot Stream : collector가 없어도 데이터를 보유하고 있고, 언제든지 상태를 읽을 수 있다.
- 다중 구독 가능 : 여러 개의 collector가 데이터를 subscribe 할 수 있다.
- 초기값이 필요하고, 항상 최신 상태를 유지한다
- 새로 구독을 시작하면, 마지막(최신) 상태부터 데이터를 받을 수 있다.
- Jetpack Compose와 함께 UI 상태를 관리, ViewModel에서 화면 상태 공유 시 사용한다.
MutableStateFlow
- 이름 그대로 StateFlow의 가변 버전으로, 상태를 업데이트 할 수 있다.
- UI 상태를 동적으로 변경해야 하는 경우, 여러 곳에서 동시에 상태를 업데이트할 필요가 있는 상황에 사용한다.
SharedFlow
🤔 코드 상에서 상속 관계를 알아보니 SharedFlow도 나왔다 찾아보자
- Hot Stream : collector가 없어도 데이터를 생산한다.
- 다중 구독이 가능하다. 초기값이 필요없다
- 데이터를 단순히 이벤트로 방출하며, 데이터가 방출된 이후에는 해당 데이터를 기억하지 않는다
- replay 값을 설정하면 일부 이벤트를 저장할 수 있다.
- 상태 관리가 필요없고, 이벤트가 발생하면 이를 다중 구독자에게 전달하는 데 특화되어 있다. 알림, 사용자 액션, 네트워크 응답 같은 일회성 이벤트에 적합하다
StateFlow는 초기 상태가 항상 저장되고, 상태가 업데이트되면, 새로운 상태가 모든 구독자에게 즉시 전달되는 반면에,
SharedFlow는 상태를 저장하지 않으므로 구독자가 없을 때 발생한 이벤트는 사라지고,
새 구독자는 현재 진행 중인 이벤트부터 수신한다.
🤔 그럼 그냥 SharedFlow 대신 StateFlow를 사용하면 되지 않나?
StateFlow는 항상 최신 상태만 유지하므로, 이전 이벤트는 덮어씌워집니다
StateFlow는 구독자가 없을 때 발생한 상태는 손실되지 않지만, 이벤트 히스토리를 관리하지 않습니다. SharedFlow는 replay 설정을 통해 일부 이벤트를 저장하여 새로운 구독자에게 제공할 수 있습니다.
Flow
- 비동기 데이터 스트림을 처리하고, 데이터의 연속적인 흐름을 관리하는 데 사용
- 시간에 따라 발생하는 값의 연속적인 스트림(데이터 흐름)을 표현하고 이를 관찰자(consumer)에게 제공
- 비동기 작업이나 시간에 따라 발생하는 데이터를 효율적이고 체계적으로 처리 및 전달
- CoroutineScope에서 실행되며, 생명주기 관리를 직접 해야 한다.
- Cold Stream - 데이터의 소비자(collector)가 생길 때 데이터 스트림이 시작된다.
- Room이 데이터베이스 변경 사항을 자동으로 감지하고, Flow를 통해 업데이트된 데이터를 계속 제공한다
🤔 데이터베이스가 변경되면 소비자가 어떻게 알고 데이터를 어떻게 요청?
Room 데이터베이스와 Flow를 사용하는 경우, 데이터베이스의 변경이 감지되면 Flow가 자동으로 데이터를 방출합니다. 즉, 소비자가 데이터를 명시적으로 요청할 필요는 없습니다. 이 과정은 Room과 Flow가 내부적으로 처리하므로 개발자가 직접 신경 쓸 필요가 없습니다.
Room은 ContentObserver나 SQLite 트리거를 사용해 데이터베이스 변경 사항을 감지한다.
StateFlow
- StateFlow는 Lifecycle에 의존하지 않는다. 관찰자가 없더라도 계속 데이터를 유지하고 갱신할 수 있다.
- 상태 기반 스트림
- 따라서, onStop 상태에서도 데이터 흐름이 멈추지 않고, ViewModel이나 다른 계층에서는 계속 동작한다.
- 특정상황에서는 stateFlow가 유용하다
- 네트워크 요청이나 비동기 작업이 onStop 상태에서도 계속 진행되어야 할 때
- 사용자가 화면을 다시 돌아왔을 때, 가장 최신 상태를 즉시 보여줘야 할 때
- UI 상태와 관계없이 비즈니스 로직이나 데이터 처리가 계속 수행되어야 하는 경우
Flow : 데이터베이스의 지속적인 변경사항을 비동기적으로 처리할 때 사용
StateFlow: ViewModel이 UI의 상태를 최신으로 유지하기 위해 사용 (최신 상태를 보관하며 상태를 유지)
Flow는 값을 방출하고 끝나지만, StateFlow는 항상 현재 상태(가장 최신 값)를 유지한다
🤔 업데이트된 값을 방출하면 그만이지 최신값을 유지하면 뭐가 좋을까?
Flow는 처음부터 데이터를 방출하고, 같은 값도 계속 방출 하지만 (값이 발생할 때마다 데이터를 방출)
stateFolw는 가장 최신 상태를 즉시 전달하며 동일한 값은 방출하지 않는다 (불필요한 업데이트 방지)