스트림의 데이터를 변형하는 연산자들

🔮  마블 다이어그램 출처: https://reactivex.io/documentation/operators.html 

Transfrom Operators

스트림의 데이터들을 변형해서 또 다른 데이터를 만들어 내는 연산들입니다. 모든 순수 함수가 그러하듯이 스트림에 있는 데이터 원본을 변형하는 부작용이 없습니다.

toArray

complete되는 순간에 모든 stream의 데이터를 array에 담아서 발행합니다. 아래 마블 다이어그램에서도 볼 수 있듯이 complete가 되기 전에는 아무 것도 발행하지 않다가 complete가 되는 순간에 한번 발행하는 것을 볼 수 있습니다.

그리고 구독할 때 실행할 클로저의 인자 레이블이 onNext이 아니라 onSuccess라는 점도 filter 연산자들과 다른 점입니다.

import RxSwift

let subject = PublishSubject<Int>()
let disposeBag = DisposeBag()

var array = [Int]()

subject
    .toArray()
    .subscribe(onSuccess: { array = $0 }) //👉 발행되면 변수 array에 할당
    .disposed(by: disposeBag)

subject.onNext(1)
subject.onNext(2)
subject.onNext(3)
print("complete 되기 전 배열: \(array)") //👉 complete 되지 않은 상태
subject.onCompleted()
print("complete 된 후의 배열: \(array)") //👉 complete가 된 상태
//🖨 출력 결과
complete 되기 전 배열: [] //🚫 complete가 되지 않았기 때문에 아직 onSuccess 클로저가 실행 안됨
complete 된 후의 배열: [1, 2, 3]

map

array에 사용하는 고차함수 map과 유사한 연산자입니다. 스트림의 데이터를 인자로 받아 새로운 데이터를 리턴하는 클로저를 통해 데이터를 변형할 수 있습니다.

import RxSwift

let subject = PublishSubject<Int>()
let disposeBag = DisposeBag()

subject
    .map {"\($0) 더하기 \($0)은 귀요미" } //👉 Int를 String 타입의 새로운 데이터로 변경
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

subject.onNext(1)
subject.onNext(2)
subject.onNext(3)
//🖨 출력 결과
1 더하기 1은 귀요미
2 더하기 2은 귀요미
3 더하기 3은 귀요미

flatMap

flatMap은 상당히 복잡한 개념입니다. 일단 flatMap은 데이터를 발행하는 map과는 달리 다시 Observable (스트림)을 발행합니다. 그리고 발행한 Stream이 하나로 합쳐진다고 보면 될 것 같습니다.


아래의 코드를 보시면 superSubject가 subSubject 두 개를 flatMap으로 하나로 합쳤습니다. 이제 superSubject는 subSubject1과 subSubject2를 합친 것이기 때문에 subSubject가 각각 데이터를 발행할 때 마다 subscribe에 정의된 클로저를 실행합니다.

import RxSwift

let superSubject = PublishSubject<PublishSubject<Int>>()
let disposeBag = DisposeBag()

let subSubject1 = PublishSubject<Int>()
let subSubject2 = PublishSubject<Int>()

superSubject
    .flatMap({ $0 })
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

superSubject.onNext(subSubject1)
superSubject.onNext(subSubject2)

subSubject1.onNext(1)
subSubject2.onNext(-1)
subSubject1.onNext(2)
subSubject2.onNext(-2)
subSubject1.onNext(3)
//🖨 출력 결과
1
-1
2
-2
3

flatMapLatest

flatMap을 이해했다면 flatMapLatest는 이해하기 쉽습니다. flatMap이 합쳐진 Stream의 발행물을 모두 발행한다면 flatMapLatest는 가장 마지막에 합쳐진 Stream의 결과물만 발행합니다.

import RxSwift

let superSubject = PublishSubject<PublishSubject<Int>>()
let disposeBag = DisposeBag()

let subSubject1 = PublishSubject<Int>()
let subSubject2 = PublishSubject<Int>()

superSubject
    .flatMapLatest({ $0 })
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

superSubject.onNext(subSubject1)
subSubject1.onNext(1)

superSubject.onNext(subSubject2) //👉 이 스트림으로 바뀜.
subSubject2.onNext(-1)
subSubject2.onNext(-2)
subSubject1.onNext(2) //👉 subSubject1의 데이터는 더 이상 발행 안됨.
subSubject1.onNext(3)
//🖨 출력 결과
1
-1
-2

좋은 웹페이지 즐겨찾기