Groo

Flow 기본 개념 본문

프로그래밍 언어/Kotlin

Flow 기본 개념

김주엽 2022. 3. 26. 18:31
반응형

아래 내용은 모두 해당 원글을 기반으로 요약정리한 내용입니다.

그림은 저자가 직접 제작한 것임을 알려드립니다. (출처: Kt World)


Coroutine의 Flow는 데이터 스트림이며, 코루틴 상에서 리액티브 프로그래밍을 지원하기 위한 구성 요소이다.

리액티브 프로그래밍이란 데이터가 변경될 때 이벤트를 발생시켜서 데이터를 계속해서 전달하도록 하는 프로그래밍 방식이다.

 

[명령형 프로그래밍 데이터 스트림]

 

기존 명령형 프로그래밍에서 데이터의 소비자는 데이터의 발행자에게 데이터를 요청한 후 결과 값을 일회성으로 수신한다.

하지만, 이러한 방식은 데이터가 필요할 때마다 결과 값을 매번 요청해야 한다는 점에서 매우 비효율적이다.

 

[리액티브 프로그래밍 데이터 스트림]

 

그러나, 리액티브 프로그래밍에서 데이터의 소비자는 데이터의 발행자에게 데이터 변경에 대한 구독을 요청한다.

그러면 데이터의 발행자는 새로운 데이터가 들어올 때마다 데이터의 소비자에게 지속적으로 데이터를 발행한다.

우리는 이것을 바로 리액티브 프로그래밍의 데이터 스트림이라고 한다.

 

코루틴에서 이러한 데이터 스트림을 구현하기 위해서는 Flow를 사용해야 한다.

 

데이터 스트림은 아래 세 가지로 구성되며, 이 세 가지가 Flow의 핵심 구성 요소이다.

  • Producer (생산자)
  • Intermediary (중간 연산자)
  • Consumer (소비자)

 

[Producer (생산자)]

 

먼저, 생산자는 데이터를 발행하는 역할을 한다.

Flow에서의 Producer는 flow {} 블록 내부에서 emit()을 통해 데이터를 생성한다.

 

안드로이드에서 생산자가 가져오는 데이터의 대표적인 DataSource는 아래 두 가지이다.

  • Remote (Network)
  • Local (DB)
class WeatherRemoteDataSource(
    private val weatherApi: WeatherApi
) : WeatherDataSource {

    override fun getWeatherInfo(): Flow<WeatherInfo> = flow {
        val weatherInfo = weatherApi.getWeatherInfo()
        emit(weatherInfo)
    }
}

 

[Intermediary (중간 연산자)]

 

생산자가 데이터를 생성했으면 중간 연산자는 데이터를 수정한다.

예를 들어 생산자가 A라는 데이터를 생성하여 데이터를 발행했는데, 우리는 B라는 데이터가 필요한 경우 Flow에서 지원하는 중간 연산자를 이용하여 A 데이터를 B로 바꿀 수 있다.

 

중간 연산자는 데이터 스트림 내에서 생산자와 소비자와는 다르게 필수 구성요소는 아니며 옵셔널이다.

 

Flow에서 지원하는 대표적인 중간 연산자는 아래와 같다.

  • map (데이터 변형)
  • filter (데이터 필터링)
  • onEach (모든 데이터마다 동일한 연산 수행)
  • Flow Docs
class WeatherRepositoryImpl(
    private val weatherRemoteDataSource: WeatherRemoteDataSource
) : WeatherRepository {

    override fun getTodayWeather(date: Calendar): Flow<Weather> {
        weatherRemoteDataSource.getWeatherInfo()
            .filter { it.weathers.date == date }
            .first()
    }
}

 

[Consumer (소비자)]

 

생산자가 생성한 데이터를 중간 연산자가 변환하여 소비자에게 다시 전달한다.

Flow에서 소비자는 collect를 이용하여 전달된 데이터를 수집하고 소비할 수 있다.

class WeatherViewModel(
    private val weatherRepository: WeatherRepository
) : ViewModel() {

    private val _todayWeather = MutableLiveData<Weather>()
    val todayWeather: LiveData<Weather>() = _todayWeather

    fun collectTodayWeather(date: Calendar) {
        viewModelScope.launch {
            weatherRepository.getTodayWeather(date).collect { weather ->
                _todayWeather = weather
            }
        }
    }
}

 


이렇게 Coroutine의 Flow 그리고 리액티브 프로그래밍의 데이터 스트림에 대해서 알아봤다.

모두들 화이팅 😉

반응형
Comments