티스토리 뷰

728x90

플로우(Flow)데이터 스트림을 비동기적으로 처리하기 위한 강력한 도구입니다. 플로우 연산자는 플로우 내에서 데이터를 변환하거나 처리할 때 사용하는 중간 연산자(intermediate operators)와 최종 연산자(terminal operators)로 나뉩니다. 플로우 연산자를 통해 데이터를 필터링, 변형, 조합하거나 오류를 처리하는 등 다양한 작업을 수행할 수 있습니다.

1. 플로우의 구조

  • 중간 연산자: 플로우 내 데이터를 변형하거나 필터링하는 역할을 하며, 여러 번 사용할 수 있습니다. 플로우 자체를 변경하지 않고, 콜드 스트림을 유지합니다.
  • 최종 연산자: 플로우에서 데이터를 수집하는 역할을 하며, 데이터의 처리가 이 연산자를 통해서 완료됩니다. collect가 대표적입니다.

2. 중간 연산자 (Intermediate Operators)

2.1 map

  • map은 플로우 내 데이터를 변환하는 연산자입니다. 각 요소에 대해 변형 작업을 수행하고, 변형된 데이터를 다시 방출합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    (1..5).asFlow()
        .map { it * 2 }  // 각 요소를 두 배로 변환
        .collect { value -> println(value) }
}

설명:

  • map을 사용하여 플로우의 모든 요소를 변환합니다. 위 예제에서는 각 요소가 두 배로 변환되어 출력됩니다.

출력:

2
4
6
8
10

2.2 filter

  • filter는 플로우 내 요소 중 특정 조건을 만족하는 요소만 통과시키는 연산자입니다.
fun main() = runBlocking {
    (1..10).asFlow()
        .filter { it % 2 == 0 }  // 짝수만 통과
        .collect { value -> println(value) }
}

설명:

  • filter는 각 요소를 필터링하여, 짝수만 통과시킵니다.

출력:

2
4
6
8
10

2.3 take

  • take는 플로우에서 지정한 개수만큼 데이터를 방출하고, 그 이후의 데이터는 무시합니다.
fun main() = runBlocking {
    (1..10).asFlow()
        .take(3)  // 처음 3개의 요소만 수집
        .collect { value -> println(value) }
}

설명:

  • take최대 3개의 요소만 방출하며, 그 이후의 요소는 무시됩니다.

출력:

1
2
3

2.4 transform

  • transform은 플로우 내 데이터를 더 유연하게 변형할 수 있게 해주는 연산자입니다. 단순한 변형뿐만 아니라, 여러 요소를 방출하거나 추가적인 비동기 작업을 수행할 수 있습니다.
fun main() = runBlocking {
    (1..5).asFlow()
        .transform { value ->
            emit(value * 2)  // 두 배로 변환
            emit(value * 3)  // 세 배로 변환
        }
        .collect { value -> println(value) }
}

설명:

  • transform각 요소를 두 번 방출합니다. 하나는 두 배로, 다른 하나는 세 배로 변형된 값입니다.

출력:

2
3
4
6
6
9
8
12
10
15

2.5 flatMapConcat, flatMapMerge, flatMapLatest

이 연산자들은 각각 다른 플로우를 연결하는 역할을 하지만, 처리 방식이 다릅니다.

  • flatMapConcat: 순차적으로 플로우를 연결하여 처리합니다.
  • flatMapMerge: 병렬로 여러 플로우를 연결하여 처리합니다.
  • flatMapLatest: 새로운 플로우가 생성되면 이전 플로우를 취소하고 최신 플로우만 처리합니다.

예시: flatMapConcat

fun main() = runBlocking {
    (1..3).asFlow()
        .flatMapConcat { number ->
            flow {
                emit(number * 2)
                delay(500L)  // 각 플로우의 지연
                emit(number * 3)
            }
        }
        .collect { value -> println(value) }
}

설명:

  • flatMapConcat은 각 플로우가 순차적으로 완료된 후, 다음 플로우를 실행합니다.

출력:

2
3
4
6
6
9

3. 최종 연산자 (Terminal Operators)

3.1 collect

  • collect는 플로우에서 데이터를 수집하는 최종 연산자입니다. Flow의 데이터 처리collect()를 호출할 때 시작됩니다.
fun main() = runBlocking {
    (1..3).asFlow()
        .collect { value -> println("Collected $value") }
}

설명:

  • collect는 플로우의 데이터를 최종적으로 수집하며, 수집된 데이터를 출력합니다.

출력:

Collected 1
Collected 2
Collected 3

3.2 reduce

  • reduce는 플로우의 모든 데이터를 순차적으로 누적하여 최종 값을 도출하는 연산자입니다.
fun main() = runBlocking {
    val sum = (1..5).asFlow()
        .reduce { accumulator, value -> accumulator + value }
    println("Sum: $sum")
}

설명:

  • reduce는 플로우의 모든 값을 더하여 최종 합계를 반환합니다.

출력:

Sum: 15

3.3 toList, toSet

  • 플로우의 데이터를 리스트(List)셋(Set)으로 변환하는 연산자입니다.
fun main() = runBlocking {
    val list = (1..5).asFlow()
        .toList()
    println(list)
}

설명:

  • toList는 플로우의 데이터를 리스트로 변환합니다.

출력:

[1, 2, 3, 4, 5]

4. 에러 처리 연산자

4.1 catch

  • 플로우에서 발생하는 예외를 처리하는 연산자입니다. 플로우 스트림 내에서 발생한 예외를 잡아 처리합니다.
fun main() = runBlocking {
    (1..5).asFlow()
        .map { check(it != 3) { "Error on $it" } }  // 3에서 오류 발생
        .catch { e -> println("Caught $e") }
        .collect { value -> println(value) }
}

설명:

  • catch는 3에서 발생한 예외를 잡아 처리하고, 그 이후 데이터는 처리하지 않습니다.

출력:

1
2
Caught java.lang.IllegalStateException: Error on 3

4.2 onCompletion

  • 플로우가 완료되었을 때(정상 완료 또는 예외 발생 시) 정리 작업을 수행할 수 있는 연산자입니다.
fun main() = runBlocking {
    (1..5).asFlow()
        .onCompletion { println("Flow completed.") }
        .collect { value -> println(value) }
}

설명:

  • onCompletion은 플로우가 완료된 후 추가적인 작업을 수행할 수 있도록 합니다.

출력:

1
2
3
4
5
Flow completed.

요약

  1. 중간 연산자는 플로우의 데이터를 변환, 필터링, 조합하거나 새로운 플로우를 연결하는 데 사용됩니다. 대표적인 연산자로는 map, filter, take, transform 등이 있습니다.
  2. 최종 연산자는 플로우의 데이터를 수집하거나 누적하여 결과를 도출합니다. 대표적인 연산자로는 collect, reduce, **
728x90
댓글