일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- 안드로이드 클린 아키텍처
- 안드로이드 의존성주입
- RxJava
- 안드로이드 Mockito
- android clean architecture
- 안드로이드 리싸이클러뷰
- sharedFlow
- Android MVVM
- 안드로이드 mvvm
- 리싸이클러뷰 최적화
- 안드로이드 테스트코드
- 안드로이드 Espresso
- 안드로이드 최적화
- Hilt
- 안드로이드 아키텍처 컴포넌트
- MVVM
- coroutine
- 안드로이드 앱 아키텍처 가이드라인
- 안드로이드 앱 아키텍처 가이드라인 설명
- 안드로이드 앱 아키텍처 가이드라인 사용법
- android memory leak
- 스타트업 코딩테스트
- android DI
- 안드로이드 mvvm예제
- Koin
- 안드로이드 앱 아키텍처 가이드라인 예시
- Android App Architecture Guideline
- 안드로이드 hilt
- 안드로이드 JUnit
- 코루틴
- Today
- Total
안드로이드 연구소
[Flow vs RxJava] Flow(Coroutine Flow) 본문
요즘 채용 시장에서 "Flow 라이브러리에 익숙하신 분"이라고
우대사항에 적어놓은 기업들을 많이 보았습니다.
Flow에 대해서 한번 알아보겠습니다.
Q1. ChatGPT, Flow에 대해 설명해줘
안드로이드에서 "Flow"는 코루틴 프레임워크의 일부인 "Kotlin Flow"라는 라이브러리를 나타냅니다.
반응형 프로그래밍 스타일에서 데이터(이벤트) 스트림을
비동기식으로 처리하는 효율적이고 사용하기 쉬운 방법을 제공하도록 설계되었습니다.
시간이 지남에 따라 비동기적으로 내보낼 수 있는 값의 스트림을 나타낼 수 있습니다.
Flow를 사용하면 데이터 스트림을 생성 및 사용하고, 변경 사항에 대응하고, 체계적이고 간결한 방식으로 backpressure을 처리할 수 있습니다.
Q2. 데이터 스트림이란
데이터 스트림은 시간이 지남에 따라 생성되거나 수신되는 데이터 요소의 시퀀스 또는 흐름을 나타냅니다.
각 요소가 차례로 처리되는 연속적인 데이터 흐름을 나타냅니다.
데이터 스트림은 데이터의 변경 사항을 관찰하고 대응할 수 있는 반응형 프로그래밍 패러다임에서 일반적으로 사용됩니다.
이를 통해 수신 데이터를 기반으로 상태를 업데이트하거나 작업을 트리거할 수 있는 응답성이 뛰어난 이벤트 기반 애플리케이션을 구축할 수 있습니다.
일반적으로 데이터 스트림은 전송(emit) -> 변환 -> 수집(collect) 단계로 이루어지는 프로세스로 보입니다.
아래는 Flow의 예시 코드입니다.
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
// (1)
fun getDataStream(): Flow<Int> = flow {
val data = listOf(1, 2, 3, 4, 5)
for (value in data) {
emit(value)
}
}
fun main() = runBlocking {
val dataStream = getDataStream() // (2)
// (3)
dataStream.collect { value ->
println("Received value: $value")
}
}
(1) getDataStream()에서 emit메서드를 이용하여 리스트의 값들이 하나씩 방출이 될 것이다.
(2)그리고 main에서 방출된 flow객체들을 인스턴스로 가져옵니다.
(3)마지막으로 collect메서드로 해당 값들을 수신합니다.
이리하여 데이터 스트림의 변화에 감지하여 UI의 업데이트 하는 데에 작업을 하는데 주로 쓰일 것으로 예상합니다.
그렇다면 LiveData와 다른점이 무엇일까요?
Q3. LiveData와 무엇이 다른가?
둘 다 모두 비동기 작업을 처리할 수 있지만 접근 방식이 다릅니다.
LiveData는 네트워크 요청 또는 데이터베이스 쿼리에서 데이터를 가져오는 것과 같은
단일 비동기 업데이트를 처리하도록 설계되었습니다.
그렇기 때문에 데이터 스트림 처리를 기본적으로 지원하지 않습니다.
반면 Flow는 데이터 스트림을 처리하도록 특별히 설계되었으며
이러한 데이터 스트림을 변환하고 처리할 수 있는 풍부한 연산자 집합을 제공합니다.
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
// (1)
fun getDataStream(): Flow<Int> = flow {
val data = listOf(1, 2, 3, 4, 5)
for (value in data) {
emit(value)
}
}
fun main() = runBlocking {
val dataStream = getDataStream() // (2)
// Transform the data stream (3)
val transformedStream = dataStream.map { value ->
value * 2 // Multiply each value by 2
}
// (4)
transformedStream.collect { value ->
println("Received transformed value: $value")
}
}
(1) 이번 예제도 앞 전 예제처럼 리스트 안에 있는 1,2,3,4,5 데이터를 전송하고 있다.
(2) Flow객체를 인스턴스로 생성한다
(3) Flow의 map연산자를 이용하여 데이터 스트림 또는 컬렉션의 각 요소를 새 요소로 변환할 수 있습니다. 각 요소들을 *2해주어 2,4,6,8,10으로 변환합니다.
(4) 그 후 collect함수로 변환된 데이터가 수집됩니다.
LiveData와 달리 Flow는 map과 같은 연산자를 이용하여
데이터를 변환할 수 있는 것이 가장 큰 차이점이자 Flow의 특징으로 보여집니다.
Q4. map과 같은 Flow연산자에는 어떤것들이 있어?
map
: 해당 연산자는 제공된 매핑 함수를 기반으로 Flow에서 내보낸 각 요소를 새 요소로 변환합니다.
변환된 값을 내보내는 새 흐름을 만듭니다.
val transformedStream = dataStream.map { value ->
value * 2 // Multiply each value by 2
}
Filter
: 해당 연산자는 제공된 조건자 함수를 기반으로 Flow에서 요소를 선택적으로 내보냅니다.
주어진 조건을 만족하는 요소만 방출하는 새로운 Flow를 생성합니다.
val filteredStream = dataStream.filter { value ->
value % 2 == 0 // Only keep even values
}
FlatMap
: 해당 연산자를 사용하면 Flow에서 내보낸 각 요소를 새 Flow로 변환한 다음
결과 Flow를 요소의 단일 스트림으로 병합할 수 있습니다.
val flatMappedStream = dataStream.flatMap { value ->
flowOf(value, value * 2) // 원래 값과 변환된 값 둘 다 전송
}
Transform
: 해당 연산자는 Flow에서 방출된 요소에 대해 임의의 변환을 수행할 수 있는 범용 변환 연산자를 제공합니다.
val transformedStream = dataStream.transform { value ->
emit(value * 2) // 변환 후 전송
}
Take
: take 연산자는 Kotlin Flow에서 Flow에서 방출하는 요소의 수를 제한하는 데 사용됩니다.
Flow에서 수신하려는 최대 요소 수를 지정할 수 있으며 해당 요소 수를 내보내면 Flow가 자동으로 완료됩니다.
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
fun getDataStream(): Flow<Int> = flow {
val data = listOf(1, 2, 3, 4, 5)
for (value in data) {
emit(value)
}
}
fun main() = runBlocking {
val dataStream = getDataStream()
val takenStream = dataStream.take(3) // Only take the first 3 elements
takenStream.collect { value ->
println("Received value: $value")
}
}
그렇다면 take 연산자를 사용하여
3개의 데이터만 전송 받게 설정하여
결과는 1,2,3 데이터만 수집될 것입니다.
Q5. Flow는 언제 도입되었고 이전에는 어떻게 데이터 스트림을 처리하였나?
코루틴은 2017년 Kotlin 1.1에서 소개되었으며
2019년에 코루틴을 기반으로 구축된 Kotlin Flow는 반응형 스트림 처리 라이브러리로 도입되었습니다.
코루틴이 등장하기 이전에는 아래와 같은 방식으로 반응형 스트림 처리를 하였습니다.
1. Callback
: 비동기 작업이 완료되면 결과와 함께 콜백이 호출되게 하여 반응형 스트림을 처리합니다.
이 접근 방식은 각 비동기 작업에 대한 콜백을 구현하고 관리해야 하므로 관리가 어려운 코드로 이어졌습니다.
2. Promises/Futures
: 약속 또는 미래는 비동기 작업의 최종 결과를 나타내는 객체입니다.
콜백이나 콤비네이터를 사용하여 작업을 연결하고 성공 또는 실패를 처리할 수 있습니다.
3. RxJava
: RxJava는 비동기 및 이벤트 기반 데이터 스트림 작업을 위한
포괄적인 연산자 및 추상화 집합을 제공하는 인기 있는 반응형 프로그래밍 라이브러리입니다.
데이터 변환, 필터링, 결합 및 동시성 관리를 위한 강력한 연산자를 제공합니다.
RxJava는 관찰 가능 항목과 관찰자를 사용하여 데이터 스트림을 처리합니다.
Flow 이전에 완벽하게 반응형 데이터 스트림을 처리하려면
RxJava를 주로 사용한 것으로 보입니다.
RxJava 또한 채용 시장에 해당 기술을 사용할 줄 아는 안드로이드 개발자를 우대하는 것을
쉽게 찾아볼 수 있습니다.
그렇다면 다음장에서 Flow이전에 사용했던 RxJava에 대해서 알아보겠습니다.
'안드로이드 연구소 > 비동기' 카테고리의 다른 글
Flow 심화2: EventFlow (1) | 2023.11.13 |
---|---|
Flow 심화1: StateFlow와 SharedFlow (2) | 2023.11.12 |
안드로이드 코틀린 코루틴(coroutine) (1) | 2023.05.09 |