brunch

매거진 ReactiveX

You can make anything
by writing

C.S.Lewis

by Tilltue Sep 01. 2016

RxSwift, subscriptions 의 공유

multicast, connect, replay, publish

* 이 포스트는 RxSwift 4.3.1, swift 4.2 버전을 기준으로 작성되었습니다.


Cold Observable 은 subscribe 시점부터 Observable 이 이벤트를 발생시키기 시작한다.

두번의 subscribe 가 일어나면 두개의 이벤트 스트림이 발생한다는 것이다.

하나의 이벤트 스트림을 두개의 subscribe에서 공유하고 싶다면 어떻게 해야할까?

subscriptions 공유 관련 메서드들을 알아보자.



먼저 공유하지 않을때의 이벤트 흐름을 살펴보자.


예제

        let timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)

        timer.subscribe(onNext: { item in

            print("first subscription \(item)")

        }).disposed(by: disposeBag)


        timer.delaySubscription(2, scheduler: MainScheduler.instance).subscribe(onNext: { item in

            print("second subscription \(item)")

        }).disposed(by: disposeBag)


아래 결과와 같이 Observable 두개가 서로 각각 이벤트가 발생하는 것을 볼 수 있다.


결과

first subscription 0

first subscription 1

first subscription 2

second subscription 0

first subscription 3

second subscription 1

first subscription 4

second subscription 2

first subscription 5



1. multicast, publish, connect  ( subject )

Observable 의 시퀀스를 하나의 subject 를 통해 multicast 로 이벤트를 전달 하게 된다.



예제

        let timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)

        let subject = PublishSubject<Int>()

        let multicast = timer.multicast(subject)

        _ = multicast.connect()

        

        multicast.subscribe(onNext: { item in

            print("first subscription \(item)")

        }).disposed(by: disposeBag)

        

        multicast.delaySubscription(2, scheduler: MainScheduler.instance)

        .subscribe(onNext: { item in

            print("second subscription \(item)")

        }).disposed(by: disposeBag)


* multicast Observable을  connect() 를 하기 전에는 시퀀스가 시작되지 않는다.


결과

first subscription 0

first subscription 1

first subscription 2

second subscription 2

first subscription 3

second subscription 3


second subscribe 시점부터 이벤트가 공유된 것을 확인 할 수 있다.


publish = multicast + publish subject

publish 메서드는 위와 같은 과정을 하나의 메서드로 함축시켜준다.


let publish = Observable<Int>.interval(1, scheduler: MainScheduler.instance).publish()


2. replay , replayAll

subscriptions 을 공유시 지정한 버퍼 크기만큼 이벤트를 저장하고 전달해준다.


예제

        let timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance) 

        let replay = timer.replay(2)

        _ = replay.connect()

        replay.subscribe(onNext: { item in

            print("first subscription \(item)")

        }).disposed(by: disposeBag)


        replay.delaySubscription(3, scheduler: MainScheduler.instance).subscribe(onNext: { item in

            print("second subscription \(item)")

        }).disposed(by: disposeBag)


결과

first subscription 0

first subscription 1

first subscription 2

second subscription 1

second subscription 2

first subscription 3


버퍼로 지정한 크기 2만큼 저장되어 이벤트가 공유된 것을 확인 할 수있다.


replayAll 메서드는 모든 이벤트를 저장한다.

메모리나 성능상 이슈가 있을수 있으므로 주의하자.


3. share, shareReplay

간단하게 공유를 만들수 있다. subscribe가 더이상 없을때 까지 지속되고 계속 적으로 subscription 을 공유할 수 있다.

shareReplay 는 replay 와 마찬가지로 버퍼를 지정할 수 있다.

shareReplayLatestWhileConnected 는 마지막 버퍼를 공유한다.


let share = Observable<Int>.interval(1, scheduler: MainScheduler.instance).share()

여기까지 subscription 의 공유에 대해서 알아보았다.




각각의 operator 의 속성이 잘 표현된 표.

이미지 출처: https://medium.com/@_achou/rxswift-share-vs-replay-vs-sharereplay-bea99ac42168



다음에는 driver 와 variable 등에 대해서 알아보자.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari