관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] RxSwift의 share() 알고 사용하기 (Hot Observable, Cold Observable) 본문

iOS 응용 (swift)

[iOS - swift] RxSwift의 share() 알고 사용하기 (Hot Observable, Cold Observable)

jake-kim 2023. 4. 7. 01:07

Hot Observable과 Cold Observable 개념

  • hot observable
    • 이벤트를 발행할때 observer가 있든 없든 바로 방출하는 것
    • 여러 observer가 구독해도 모두 같은 데이터를 발행
    • ex) PublishSubject, BehaviorSubject
  • cold observable
    • 이벤트를 발행할때 observer가 구독했을때 방출하는 것 (observer가 구독하기 전까지는 방출을 안한다고해서 cold라고 표현)
    • 각각의 observer마다 독립적인 데이터 생성하여 발행
    • ex) just, single, create

코드로 보는 Hot, Cold Observable

  • Observable.create는 cold observable이므로, observer가 구독하는 시점마다 독립적으로 발생
  • observer가 두 개고, 각각 구독하고 있으므로 1, 2, 3이벤트가 2번 발생
let observable = Observable<Int>.create { observer in
    print("observable created")
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    return Disposables.create()
}

_ = observable.subscribe(onNext: { element in
    print("first subscription: \(element)")
})

_ = observable.subscribe(onNext: { element in
    print("second subscription: \(element)")
})

/*
observable created
first subscription: 1
first subscription: 2
first subscription: 3
observable created
second subscription: 1
second subscription: 2
second subscription: 3
*/
  • 많이 사용하는 패턴인, 외부에 getter만 제공할때 내부에서는 publish를 사용하고 외부에는 observable을 접근가능하게 사용할때, publish는 hot observable이므로, 이벤트가 발생하고나서 subscribe하면 이벤트를 받지 못함
    • 아래 코드에서 viewDidAppearPublish 이벤트가 발생하면 observer들의 구독 여부에 상관없이 바로 방출되므로 아무런 출력 x
class ViewController: UIViewController {
    private let viewDidAppearPublish = PublishSubject<Void>()
    var viewDidAppearObservable: Observable<Void> {
        viewDidAppearPublish
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        viewDidAppearPublish.onNext(())
        
        _ = viewDidAppearPublish
            .subscribe(onNext: {
                print("first subscription, viewDidAppearPublish")
            })
        
        _ = viewDidAppearPublish
            .subscribe(onNext: {
                print("second subscription, viewDidAppearPublish")
            })
    }
}

share() 개념

  • share()는 cold observable을 단 한번만 방출시키게 하는 것
    • cold observable을 단 한번만 방출하게하여 observable 내부가 중복으로 실행되지 않게끔하기 위함

ex) share()를 사용하면 아래 코드에서 second subscription이 실행되지 않음 (= observable 내부 코드가 한 번만 실행됨)

let observable = Observable<Int>.create { observer in
    print("observable created")
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    return Disposables.create()
}.share()

_ = observable.subscribe(onNext: { element in
    print("first subscription: \(element)")
})

_ = observable.subscribe(onNext: { element in
    print("second subscription: \(element)")
})

/*
observable created
first subscription: 1
first subscription: 2
first subscription: 3
*/
  • share(replay:) 
    • 위에서 share()를 사용하여 observable 내부가 중복으로 실행되지 않는데, 만약 replay를 사용하면 입력된 값만큼 추가로 마지막에 방출된 이벤트를 추가로 observer에게 방출시킨다는 의미
    • share(replay: 2)를 사용하면 observer.onNext(3), observer.onNext(2)가 추가로 방출
    • 핵심은 observable 내부는 한번 실행되어, 아래 프린트에서 observable created가 한번만 찍힘
let observable = Observable<Int>.create { observer in
    print("observable created")
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    return Disposables.create()
}.share(replay: 2)

_ = observable.subscribe(onNext: { element in
    print("first subscription: \(element)")
})

_ = observable.subscribe(onNext: { element in
    print("second subscription: \(element)")
})
/*
 observable created
 first subscription: 1
 first subscription: 2
 first subscription: 3
 second subscription: 2
 second subscription: 3
 */

결론

  • share()은 cold observable을 이벤트 방출시키는 부분을 중복실행하지 않게끔하는 것
  • share()은 이벤트를 방출하는 부분이 중복으로 불리면 안될때만 사용할 것

* 전체 코드: https://github.com/JK0369/ExShare_RxSwift

Comments