오늘은 subject란 무엇인지에 대해 공부해보겠습니다
subject는 observable과 observer의 역할을 모두 수행하는 bridge/proxy입니다.
그러니까는 데이터를 넣어줄수도(onNext), subscribe 할수도 있다는 거죠 !
observer처럼 subscribe할 수 있지만
subject는 여러 observer 구독 가능한 multicast 이고 observable는 하나의 observer만 가능한 unitcast입니다.
unicast와 multicast는 어떤 차이가 있을까요 ?
일반적인 Observable은 어떠한 상태도 가지지 않습니다.
따라서 모든 Observer가 구독하게 되면 그때마다 새로 생성(create)하여 발행하는 과정을 거치게 됩니다.
let randomNumGenerator1 = Observable<Int>.create{ observer in
observer.onNext(Int.random(in: 0 ..< 100))
return Disposables.create()
}
randomNumGenerator1.subscribe(onNext: { (element) in
print("observer 1 : \(element)")
})
randomNumGenerator1.subscribe(onNext: { (element) in
print("observer 2 : \(element)")
})
observer 1 : 54
observer 2 : 69
observer가 두번 subscribe시 다른 값이 출력되었습니다. 이는 Observer가 해당 Observable에 대해 독자적(uni)으로 실행하기 때문입니다. 구독을 진행할 때마다 create가 호출되는 것을 의미하며, 따라서 결괏값이 그때그때 새로 생성된 값으로 할당됩니다.
하지만 Subject의 경우 Observer들의 정보를 저장하고 발행된 이벤트를 모든 Observer에게 제공하게 됩니다.
let randomNumGenerator2 = PublishSubject<Int>()
randomNumGenerator2.on(.next(Int.random(in: 0..<100)))
randomNumGenerator2.subscribe(onNext: { (element) in
print("observer subject 1 : \(element)")
})
randomNumGenerator2.subscribe(onNext: { (element) in
print("observer subject 2 : \(element)")
})
observer subject 1 : 92
observer subject 2 : 92
비슷한 방식으로 PublishSubject인 randomNumGenerator2를 두 번 구독하여 테스트한 결과로 같은 값이 공유되어 받을 수 있었습니다.
이처럼 Subject는 observer들에게 발행된 이벤트를 알려주는 것이라고 할 수 있습니다.
https://ntomios.tistory.com/12
이 글을 참고하여 정리하였습니다! 한번씩 들러 보면 이해하기 좋을듯 합니다
subject는 4가지 종류가 있습니다
1. AsyncSubject
obsevable이 complete 되었을 시 마지막 값을 방출하지만 observable이 complete 되지 않았을 때는
방출하지 않고 원본 Observable과 같이 에러가 발생합니다.
2. PublishSubject
subscribe된 시점 이후부터 발생한 이벤트 전달, subscribe되기 전의 이벤트는 전달하지 않습니다.
구독된 순간 새로운 이벤트를 구독자에게 알리고 싶을 때 유용합니다. ex) 시간에 민감한 데이터를 모델링 할 경우(실시간 경매 앱 - 10:00am 경매 시작일 경우, 10:01am에 접속했을 때 알림이 보내질 필요가 없는 경우)
3. BehaviorSubject
초기값이 있습니다. 그래서 초기값만 있을때 subscribe되면 초기값을 방출하고 저장된 값이 있다면 현재 저장된 값들을 방출합니다. 마지막에 값들을 저장하고 싶을때 (마지막 데이터 뷰에 뿌릴때) 유용합니다.
4. ReplaySubject
언제 observer가 subscribe되든 상관 없이 모든 이벤트들을 방출하는데 버퍼 사이즈를 지정하며, 버퍼 사이즈만큼 새로운 subscriber에게 방출합니다.
※ 버퍼 사이즈는 메모리에 할당되므로 버퍼 사이즈가 커질 수록 메모리에 큰 부하를 갖는 것을 주의해야 합니다.
Relay란
rxswift인 subject와 달리 rxcocoa의 클래스입니다.
subject는 .completed, .error 이벤트가 발생하면 subscribe가 종료되는 반면
relay는 .completed, .error 이벤트를 발생하지 않고 dispose 되기 전까지 계속 작동하므로 UI 등에서 사용하기 적절합니다.
PublishRelay와 BehaviorRelay 두가지가 있는데 한번 살펴 보도록 하겠습니다.
1. PublishRelay
PublishSubject의 wrapper 클래스입니다
Relay는 Subject와 다르게 onNext(_:)가 아닌 accept(_:)를 통해 새로운 이벤트를 전달합니다
PublishSubject처럼 구독 이후의 발생하는 이벤트들을 모두 방출합니다
2.BehaviorRelay
BehaviorSubject의 wrapper 클래스입니다
BehaviorSubject와 같이 마지막 값을 꺼내올때 사용합니다.
'IOS🍎 > RxSwift' 카테고리의 다른 글
[RxSwift] Driver란 ? (feat. bind) (0) | 2022.03.21 |
---|---|
[RxSwift] Traits 이란 (0) | 2022.03.19 |
[RxSwift] Disposable DisposeBag 이란 (0) | 2022.03.17 |
[RxSwift] Combine Operator(CombineLatest, Merge, StartWith, Concat, Zip, WithLastFrom, Sample, SwitchLatest, Debounce) (0) | 2022.03.06 |
[RxSwift ] 1. Observable이란 (0) | 2021.11.15 |
댓글