Subject는 Observer나 Observable의 역할을 하는 일종의 bridge 혹은 proxy라고 볼 수 있다.
그 이유는 Subject는 Observer이기 때문에 하나이상의 Observable을 구독할 수 있으며 동시에 Observable이기도 해서 항목들을 하나 하나 거치면서 방출할 수 있기 때문이다.
공식문서
그림으로 보면 더쉽다. Subject는 multicast방식이라서 여러개의 observer를 Subscribe할 수 있고,
observable은 unicast방식이라서 observer하나만을 subscribe를 할 수 있다.
앞서 observable은 unicast라고 설명을 하였다. unicast란 각각 subscribed된 observer가 observable에 대해 독립적인 실행을 갖는것이다. 아래 예시를 참고하자!
// --- Observable ---
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)")
})
--------------------print------------------
observer 1 : 54
observer 2 : 69
출력값이 다르다.. observer가 해당 observable에 대해 독자적인 실행을 가지고 있기 때문이다.
다음은 subject의 multicast를 살펴보자. multicast가 된다는건 하나의 observable 실행이 여러 subscriber에게 공유되는걸 뜻한다.
// ------ BehaviorSubject/ Subject
let randomNumGenerator2 = BehaviorSubject(value: 0)
randomNumGenerator2.onNext(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)")
})
--------------------print------------------
observer subject 1 : 92
observer subject 2 : 92
정리
-> observable을 subscribe를 하면 이벤트로 전달되는 것은 항상 새로운 것이 전달된다.
-> subject를 subscribe를 하면 이벤트로 전달되는 것은 subscribe전에 수행된 onNext를 방출한다.
Subject는 총 4가지의 종류가 있다.
AsyncSubject, BehaviorSubject, PublishSubject, ReplaySubject들이 있는다 아래에서 차례대로 공부한 내용을 바탕으로 정리를 해보았다!
AsyncSubject는 이벤트가 전달되는 시점이 다르다. 구독한 시점에 이벤트가 전달되는 것이 아닌 complete이벤트가 전달되면 or error가 전달되면 (즉, Observable의 동작이 완료된 후 동작) 가장 마지막 이벤트가 전달이 된다..
만약 아무값도 방출하지않으면 어떤 값도 나오지 않는다
완료가 된 후에 마지막 값을 방출하는 모습
에러가 방출되는 모습
subject중 가장 많이 사용되는 것이 BehaviorSubject가 아닐까 싶다..
observer가 BehaviorSubject를 구독하기 시작하면, obsrever는 가장 최근에 방출한 값(없다면 BehaviorSubject의 초기값을 방출한다.) 그 이후 발생된 값도 계속 방출한다.
PublishSubject는 Subscriber는 구독을 한 시점 이후에 발생되는 이벤트만 전달받는다.
behaviorSubject와 달리 초기값을 지정하지 않는다.
PublishSubject는 Subscriber가 새로운 이벤트만 전달받으면 되는 경우 사용하기 좋습니다. 즉, Subscribe 이전에 발생했던 이벤트는 전혀 몰라도 되는 경우.
ReplaySubject는 구독시점부터 이전의 값을 버퍼 사이즈만큼 저장하고 있다가 구독이 시작되면 버퍼 사이즈 만큼 여러번 방출 합니다..