개발콩블로그
[RxSwift] Cold-Hot Observable, Unicast와 Multicast 본문
안녕하세요 개발콩입니다 !😊
RxSwift와 같은 기술스택은 알고 사용하는 것이 중요한 것 같습니다.
오늘은 Cold vs Hot Observable과 Unicast vs Multicast에 대해서 알아보도록 하겠습니다.
구독 시점과 이벤트 방출 시점에 따라 달라지는 것이 Cold-Hot Observable입니다.
Cold Observable
- 구독이 발생할 때까지 기다렸다가 이벤트를 방출합니다.
- 처음부터 모든 데이터 stream을 확인할 수 있습니다. 따라서 각 subscriber가 구독을 시작한 시점에 동일한 데이터 stream을 받을 수 있습니다.
Cold Observable의 특성을 갖고있는 Observable 타입으로 예시를 확인해보겠습니다.
let coldObservable = Observable.just("추운 겨울이 가고 따뜻한 봄이 옵니다.")
coldObservable
.subscribe { text in
print(text)
}
.disposed(by: disposeBag)
// 추운 겨울이 가고 따뜻한 봄이 옵니다.
구독을 한 시점에 이벤트가 방출되고 해당 이벤트를 처리하는 것을 볼 수 있습니다.
Hot Observable
- 구독 시점과는 상관없이 Observable 생성과 동시에 이벤트를 방출할 수 있습니다.
- 처음부터 모든 데이터 stream을 확인하지 못할 수 있습니다. (데이터 stream을 중간부터 볼 수도 있습니다.)
Hot Observable의 특성을 갖고있는 Subject 타입으로 예시를 확인해보겠습니다.
let hotObservable = PublishSubject<String>()
hotObservable.onNext("추운 겨울이 가고 따뜻한 봄이 옵니다.")
hotObservable
.subscribe { text in
print(text)
}
.disposed(by: disposeBag)
hotObservable.onNext("벌써 뜨거운 여름이 왔습니다.")
// 벌써 뜨거운 여름이 왔습니다.
구독한 시점 이전에 방출된 "추운 겨울이 가고 따뜻한 봄이 옵니다." 이벤트는 확인하지 못합니다.
구독을 한 Observer가 없더라도 이벤트를 방출하는 것을 볼 수 있습니다.
즉, 구독한 시점 이전의 방출된 이벤트를 처리할 수 없고, 구독한 시점 이후의 방출된 이벤트만 처리하는 것을 확인할 수 있습니다.
UniCast
- stream이 공유되지 않습니다.
- 독립적인 stream을 갖습니다.
UniCast의 특징을 가진 Observable 타입으로 예시를 확인해보겠습니다.
let unicastObservable = Observable.create { observer in
observer.onNext(Int.random(in: 1...100))
return Disposables.create()
}
unicastObservable
.subscribe { number in
print("1번째 - \(number)") // 1번째 - next(27)
}
.disposed(by: disposeBag)
unicastObservable
.subscribe { number in
print("2번째 - \(number)") // 2번째 - next(48)
}
.disposed(by: disposeBag)
unicastObservable
.subscribe { number in
print("3번째 - \(number)") // 3번째 - next(30)
}
.disposed(by: disposeBag)
Unicast의 특성을 갖고있는 Observable을 생성합니다.
1부터 100까지의 random한 숫자를 방출합니다.
구독을 한 여러개의 stream이 모두 다른 값을 받는 것을 볼 수 있습니다.
즉, stream이 공유되지 않고 독립적인 stream을 갖는 것을 볼 수 있습니다.
MultiCast
- stream이 여러 Observer에게 공유됩니다.
- 모든 구독이 동일한 stream을 받게 됩니다.
MultiCast의 특성을 가진 Subject타입을 통해 예시를 확인해보겠습니다.
let multiCastObservable = BehaviorSubject(value: Int.random(in: 1...100))
multiCastObservable
.subscribe { number in
print("1번째 - \(number)") // 1번째 - next(75)
}
.disposed(by: disposeBag)
multiCastObservable
.subscribe { number in
print("2번째 - \(number)") // 2번째 - next(75)
}
.disposed(by: disposeBag)
multiCastObservable
.subscribe { number in
print("3번째 - \(number)") // 3번째 - next(75)
}
.disposed(by: disposeBag)
하나의 Observable에 대해서 여러 구독을 하더라도 동일한 값을 받는 것을 볼 수 있습니다.
모든 구독이 동일한 stream을 받는 것을 확인할 수 있습니다.
Share
share(replay, scope:)
Unicast로 동작하는 Stream을 MultiCast로 동작하도록 합니다.
- replay
- subscriber에 이전에 방출한 이벤트를 몇개까지 방출한 것인지 설정합니다.
- scope
- .whileConnected: subcriber가 1개 이상일 경우 replay 유지됩니다.
- .forever: subcriber가 0개인 경우에도 replay가 유지됩니다.
share() method 사용 전
let tap = nextButton.rx.tap
.map { Int.random(in: 1...100) }
tap
.bind(with: self) { owner, value in
print("1번 - \(value)") // 1번 - 44
}
.disposed(by: disposeBag)
tap
.bind(with: self) { owner, value in
print("2번 - \(value)") // 2번 - 70
}
.disposed(by: disposeBag)
tap
.bind(with: self) { owner, value in
print("3번 - \(value)") // 3번 - 94
}
.disposed(by: disposeBag)
share() method 사용 이후
let tap = nextButton.rx.tap
.map { Int.random(in: 1...100) }
.share()
tap
.bind(with: self) { owner, value in
print("1번 - \(value)") // 1번 - 55
}
.disposed(by: disposeBag)
tap
.bind(with: self) { owner, value in
print("2번 - \(value)") // 2번 - 55
}
.disposed(by: disposeBag)
tap
.bind(with: self) { owner, value in
print("3번 - \(value)") // 3번 - 55
}
.disposed(by: disposeBag)
share를 왜 사용할까?
let tap = nextButton.rx.tap
.flatMap { 네트워크 통신 작업 }
위와 같이 버튼을 클릭하면 네트워크 통신 값을 변환하는 코드가 작성되어있다고 가정합니다.
이러한 Observable을 구독을하는 subscriber가 여러개가 존재한다면 그에 따른 개수마다 네트워크 통신을 반복 수행하게 될 것입니다.
우리는 이러한 경우에 share method를 적용해볼 수 있습니다.
'RxSwift' 카테고리의 다른 글
[RxSwift] Dispose (0) | 2025.03.02 |
---|---|
[RxSwift] 구독 방식에 대한 선택 subscribe, bind, drive (0) | 2025.02.28 |
[RxSwift] PublishRelay, BehaviorRelay, ReplayRelay (0) | 2025.02.27 |
[RxSwift] PublishSubject, BehaviorSubject, ReplaySubject, AsyncSubject (0) | 2025.02.26 |
[RxSwift] ObservableType과 ObserverType (0) | 2025.02.25 |