study record
[RxSwift] Subject의 종류 본문
Subject
Subject는 Observable이자 Observer 두 역할 모두를 수행한다. next 이벤트를 통해 값을 전달받고, 이벤트를 수신할 때마다 subscriber를 통해 방출한다.
Subject 종류
- PublishSubject : 빈 상태로 시작하여 새로운 값만을 subscriber에 방출
- BehaviorSubject : 하나의 초기값을 가진 상태로 시작하여, 새로운 subscriber에게 초기값 또는 최신값을 방출
- ReplaySubject : 버퍼를 두고 초기화하며, 버퍼 사이즈 만큼의 값들을 유지하면서 새로운 subscriber에게 방출
- Variable : BehaviorSubject를 래핑하고, 현재의 값을 상태로 보존. 가장 최신/초기 값만을 새로운 subscriber에게 방출
PublishSubject
Subject로 전달되는 이벤트를 Observer에게 전달하는 가장 기본적인 형태의 Subject.
빈 상태에서 시작하고, 새로운 값을 전달받을 때에 subscriber를 통해 방출한다.
구독한 시점 이후부터의 아이템을 전달받는 것을 볼 수 있다.
- 언제 사용하나?
구독된 순간 새로운 이벤트 수신을 알리고 싶을 때
시간이 민감한 데이터를 모델링할 때 유용하다. 예를 들어 실시간 경매 앱이 존재한다고 했을 때 경매 시간이 끝난 이후에 들어온 유저에게 "경매 시간이 얼마남지 않았습니다!"와 같은 메세지를 전달하는 것은 매우 무의미하다. 시간이 지나 구독을 시작한 Subscriber에게는 이벤트를 전달하지 않으므로, 무의미한 이벤트 전달을 하지 않을 수 있다.
let subject = PublishSubject<Int>()
// subject에 .next 이벤트 방출
subject.onNext(1)
// subject 구독
let subscribeOne = subject.subscribe(onNext: {(value) in
print(value)
})
// .next 이벤트 방출
subject.onNext(2)
// 구독취소
subscribeOne.dispose()
// 2
1은 출력되지 않는다. 구독 이후부터 이벤트가 받아지면 방출되기 때문이다.
BehaviorSubject
BejaviorSubject와 다르게 하나의 초기값을 가지고 있어야 한다.
초기값을 가지고 있는 상태이므로 초기값으로 next 이벤트로 값이 전달되면서 시작된다.
새롭게 구독을 시작하면 그 직전의 값을 전달받고 시작한다.
- 언제 사용하는가?
뷰를 가장 최신의 데이터로 미리 세팅할 때
예를들면 어떤 이미지를 호출해주는 BehaviorSubject가 있고 해당 BehaviorSubject를 이미지뷰와 바인딩 시켰을 때 가장 최근에 불려왔었던 이미지를 미리 채워둠으로서 로딩하는 모습을 감추고 싶다하는 시나리오에 매우 유용하게 사용될 수 있다.
let subject = BehaviorSubject(value: 1)
let disposebag = DisposeBag()
subject.subscribe{ (value) in
print(value)
}.disposed(by: disposebag)
subject.onNext(2)
// next(1)
// next(2)
ReplaySubject
하나 이상의 새로운 이벤트를 버퍼에 저장하고 Observer가 구독을 시작하면 버퍼에 있는 모든 이벤트를 전달한다.
버퍼의 크기를 설정할 수 있고, 버퍼 크기가 0이면 PublishSubject와 동일하다.
let disposeBag = DisposeBag()
let replaySubject = ReplaySubject<String>.create(bufferSize: 2)
replaySubject.onNext("1")
replaySubject.onNext("2")
replaySubject.onNext("3")
replaySubject
.subscribe {
print("첫번째 구독자 \($0)")
}
.disposed(by: disposeBag)
replaySubject
.subscribe {
print("두번째 구독자 \($0)")
}
.disposed(by: disposeBag)
// print
첫번째 구독자 next(2)
첫번째 구독자 next(3)
두번째 구독자 next(2)
두번째 구독자 next(3)
- 언제 사용하는가?
최근 값 1개 외에 더 많은 값을 불러오고자 할 때
버퍼들은 메모리가 가지고 있으며, 데이터 타입이 메모리를 크게 차지하는 값(이미지나 배열같은)이라면 메모리 부하가 날 수 있다.
Variable
BehaviorSubject를 래핑하고 있으며, 현재 값을 상태로 가지고 있다.
complete, error 이벤트가 발생하지 않으며 variable이 해제될 때 자동으로 complete된다.
새로운 요소를 추가하기 위해 onNext를 사용할 수 없다.
variable은 상태 값이므로 에러가 발생하지 않는 것을 보장하여 error이벤트를 발생시킬 수 없다.
variable이 해제될 때 자동으로 complete되기 때문에 complete 이벤트를 발생시킬 수 없다.
- 언제 사용하는가?
현재 값을 확인하고 싶을 때
let variable = Variable("Initial value")
let disposebag = DisposeBag()
variable.value = "New value"
variable.asObservable().subscribe{ (value) in
print("1) \(value)")
}.disposed(by: disposebag)
variable.value = "Set other value"
variable.asObservable().subscribe{ (value) in
print("2) \(value)")
}.disposed(by: disposebag)
variable.value = "Set other value2"
// 1) next(New value)
// 1) next(Set other value)
// 2) next(Set other value)
// 1) next(Set other value2)
// 2) next(Set other value2)
참고 :
https://gwangyonglee.tistory.com/61
https://velog.io/@chagmn/RxSwift-Subjects
https://www.notion.so/BehaviorSubject-a3ab38e952134b43ad4b2bdbcaa73fd4
'iOS > RxSwift' 카테고리의 다른 글
[RxSwift] Driver란? (0) | 2022.03.29 |
---|---|
[RxSwift] Subject와 Relay (0) | 2022.03.14 |
[RxSwift] RxSwift 왜 사용하게 되었나? +(선언적 프로그래밍) (0) | 2022.03.07 |
[RxSwift] Observable과 Subject 차이 (0) | 2022.03.05 |
[RxSwift] Hot Observable과 Cold Observable의 차이 (0) | 2022.03.04 |