RxSwift) Subject (1/3) - Subject의 Observable 역할
안녕하세요! 소들입니다 :)
저는 이제 망아지들을 완전히 탈출하여 매일 오공완! 오운완! 오롤완!을
외치는 삶을 살고 있땁니다!! (하루의 마지막으로 칼바람 뜰 사람!!??)
오늘도 주말이지만 친한 동료들과 카페 와서 공부하고 있구요!?ㅋ 🥹
PT도 받고 있어서 조만간 근육몬도 될 거구요?ㅋ 💪
그나저나.. 오늘은 Subject에 대해서 알아보려고 해요!
RxSwift 포스팅이 꽤 시기 늦은 감이 있지만.. 굉장히 많은 분들이 봐주셔서.. =-=..
이번 포스팅은 Observable, Observer를 배울 때처럼 깊고 어렵진 않으나..
해당 포스팅에 대한 이해가 없으면 이해가 힘들 수 있어 먼저 읽고오시길 추천하겠습니다!
모든 포스팅은 편의 말투로 합니다~!!
1. Subject가 뭔가요?
Subject의.. Observable..역할 어쩌고.. 하기 전에..
우리가 오늘 공부할 Subject라는 것이 도대체 뭔지!개념부터 보겠음 :D
Subject는 Observer이자 Observable입니다
Observer이기 때문에 하나 이상의 Observable을 구독할 수 있으며,
동시에 Observable이기 때문에 새로운 항목(item)들을 방출하거나 재방출 합니다
히히.. 뭐라능겨 .. 🥹 ..
이를 이해하기 위해서 지금까지 앞서 공부한
Observable과 Observer란 것을 개념부터 짧게 정리하고 가보겠음
Observable이란,
비동기 이벤트를 관찰이 가능한 형태로 만든 것으로,
해당 이벤트가 발생했을 때 "항목(item)"이란 것을 "방출(emit)"함니다
Observer란,
내가 원하는 비동기 이벤트를 방출하는 Observable이 있을 경우,
해당 Observable을 "구독(Subscribe)"하여
항목이 방출되었을 때 그 항목을 받아 처리할 수 있슴니다
자 여기까진 기본 개념이잖음?
그렇다면 Observable이란 놈은 어떻게 구현 되어있다고 했음??
ObservableType이란 프로토콜을 채택하는 제네릭 클래스로 구현이 되어있다!
따라서 Observable을 만들기 위해선 이 Observable이란 클래스를 사용해야 했음!
그렇다면 Observable까진 오케이!
이제 Observer로 넘어가서,
우리는 사실 이전 포스팅에서 Observer를 직접 생성하거나 살펴보진 않았음
왜냐?? ObservableType에서 제공하는 구독 메서드, 즉 subscribe를 사용하면
자체적으로 AnonymousObserver란 Observer를 생성해서,
해당 Observable에 subscribe를 해줬기 때문임
근데 이제 이 AnonymousObserver라는 것도 자세히 까보면,
ObserverBase란 클래스를 상속받고 있는 것을 볼 수 있고,
이 ObserverBase란 클래스는 ObserverType이란 프로토콜을 채택하고 있는 것을 볼 수 있음
무슨말이냐, Observer 역할을 하기 위해선,
ObserverType이라는 프로토콜을 준수해야 함!
(이는 다음 포스팅에서 더 자세히 다룰 거니 일단 여기까지만)
최종적으로 정리하자면!
Observable의 역할을 하기 위해선 Observable이란 제네릭 클래스를 상속받아야 하고,
Observer의 역할을 하기 위해선 ObserverType이란 프로토콜 채택이 필요함
근데 Subject는 말이야 ..
Observable과 Observer의 역할을.. 동시에 한다며.. 🥶
그러면 Subject라는 놈은
Observable 클래스를 상속받는 동시에, ObserverType도 채택하고 있어야 하겠네여!?!?
호옹이.. 정말이자너!?
PublishSubject가 뭔진 모르겠지만 이 Subejct란 놈은
Observable 역할을 위한 Observable이란 클래스를 상속받는 동시에,
Observer 역할을 위한 ObserverType을 채택하고 있는 것을 알 수 있음!!!
아, 그래서 Subject는 Observer이자 Observable의 역할을 한다는구나!를
아주 살짝만 이해를 하고 가면 됨
2. 그럼 Subject는 언제, 왜 쓰는데요?
Subject의 개념을 이해 하긴 했으나, 여러분은 의문이 드셔야 함
아 구랭구랭 Subject가 Observable과 Observer의 역할 둘다 하는거? 대충 느낌 알았어
근데 그럼 Subject는 언제 왜 쓰는데!?!??!?
이를 이해하기 위해선 Observable과 Subject의 차이를 보면서 해야함
그전에 먼저 Observable도 마치 아메리카노 처럼
뜨거운 Observable과 차가운 Observable이 있단 것을 앎?!
저는 아옵으로.. 주세요 ☕️
2-1. Hot Observable vs Cold Observable
사실 Observable의 종류는 총 두 가지가 있답니다..!??!?
먼저,
❄️ Cold Observable ❄️
구독이 되어야만 비로소 항목(이벤트)을 방출하는 Observable
어느 시점에 구독하든 같은 결과를 받습니다
🔥 Hot Observable 🔥
구독 여부와 상관 없이 항목(이벤트)을 방출하는 Observable
구독하는 시점에 따라 방출되는 결과가 다릅니다
처음부터 방출되는 결과를 받지 못할 수 있습니다
이보시오 소들양반..
Subject를 공부하는데 웬 갑자기 뜨아 아아 논쟁이요.. 싶겠지만 ..
우리가 지금껏 공부했던 Observable 연산자 뭐가 있음..?
just, of, create... 등등이 있잖음??
이 Observable들을 공부할 때 특징이 뭐였음?
let observable = Observable.just(1)
|
이렇게 Observable을 생성한다 해서 바로 항목인 "1"을 방출하지 않음!
그럼 언제 방출함??
observable.subscribe(onNext: { (data) in
print(data) // 1
})
|
이렇게 이 Observable에 대고 "구독"을 했을 때,
그때야 1이란 항목이 방출되었었음!!!
뭘 말하고 싶은 거냐면,
우리가 지금껏 공부했던 Observable 연산자들은 모두
Observer가 Observable을 구독 되어야만 비로소 해당 이벤트가 방출되는
❄️ Cold Observable ❄️이었던 것임!!
근데 마리야!
Subject는... 🔥 Hot Observable 🔥 이랍니다..!!!
따라서 Subject를 사용할 경우,
내가 구독한 시점부터 방출되는 이벤트만 받을 수 있고,
내가 구독하기 전에 이미 방출되어버린 이벤트는 받을 수 없음!!!
예로 이해를 해보자면..!
유튜버에서 "알람"이라는 것을 Observable로 구현한다고 해보셈
우리가 만약 소들이란 유튜버를 알람 설정하고 싶음!
그러면 이제 알람 설정을 한 시점부터, 소들이가 영상을 올리거나 라이브를 할 때 알람이 와야 하잖음!?
그럼 이때는 Observable을 구독한 시점부터 항목이 방출되는 Hot Observable을 사용해야 할 것임!!
만약 이때 Cold Observable을 사용하면 ...
소들 유튜버가 가입 시기부터 쓴 글과 라이브들의 과거 알람들도 다 오는 대환장 파티가 될 거잖음!! 🥺
살짝 이해가 되셨나..?
.
.
아니! 이해 안 가! 그래서 그게 뭔데! 하시는 분들을 위해..
조금 더 쉽게 정리를 해볼게요!
자, 우리가 지금까지 배운 Observable 생성 연산자들!
이 Observable이 구독되었을 때
let observable = Observable.just(1)
|
let observable = Observable<String>.create { observer in
observer.onNext("첫 번째 방출")
observer.onNext("두 번째 방출")
observer.onCompleted()
observer.onNext("세 번째 방출")
return Disposables.create()
}
|
나는 이런이런한 항목을 방출할 거예요! 라는 코드를 작성 했었음!
(just의 경우, 나는 1이란 숫자를 한번 방출 할 거예요! 고,
create의 경우, 나는 print를 두번 찍고 completed을 호출해서 정상 종료할 거예요! 잖음)
그리고, 실제 이 Observable을 구독했을 때
이렇게 미리 정의된 코드에 의한 항목이 방출되며,
Observer는 이 방출되는 항목을 오롯이 다 받을 수 있었음!
이것이 바로 ❄️ Cold Observable ❄️ 이란 것임!
자 여기까진 이해가 가시져!?!?
그럼,
🔥 Hot Observable🔥 인 Subject 또한 코드로 이해해보면 좀 더 쉬울 거같음!
Subject는 물론 후에 배울 종류에 따라 다르지만 PublishSubject라는 것으로 보면
let subject = PublishSubject<String>()
|
이런 식으로 선언함..!!
대충 제네릭 타입을 String으로 선언한 거로 보아,
String의 항목을 방출하는 건 예상해볼 수 있지만
위에서 Cold Observable을 정의할 때와 어떤 게 다른지 확 보임?!?!
어떤 항목을 방출할 것인지에 대한 정의가 없음!!!!
아항.. 이 말 뜻이 뭐냐면 Hot Observable은,
Cold Observable마냥 내가 어떤 항목을 방출할 것인지를 생성 당시 정의해두는 것이 아니라,
내가(개발자가) 원하는 시점마다 항목을 방출할 수 있다는 것임!!
구독했을 때 온전히 처음부터 모든 항목을 다 방출해줘야 하는 Cold Observable과 달리,
나는 항목 발행 하고싶을 때마다 내 알아서 발행 할 곤뎅? 🥺
만약 내 항목 받고 싶으면 구독 하든가? ㅋ
근데 너가 구독하기 이전에 내가 이미 방출해버린 항목 못받는 건 내 알바 아닙니다!?
가 바로 Hot Observable이란 것임!
따라서, Subject를 생성했을 경우,
let subject = PublishSubject<String>()
subject.onNext("1")
subject.onNext("2")
|
이렇게 onNext라는 것을 통해 내가 원할 때마다 항목을 발행 할 수 있음!!!
(3편에 공부할테니 아 onNext? 그렇구나! 하고 넘어가셈)
따라서, Subject는 Observer가 구독하는 "시점"에 따라서
subject.subscribe(onNext: {
print("첫번째 Observer가 받는 항목 : \($0)")
}).disposed(by: disposeBag)
subject.onNext("1")
subject.onNext("2")
subject.subscribe(onNext: {
print("두번째 Observer가 받는 항목 : \($0)")
}).disposed(by: disposeBag)
subject.onNext("3")
|
이렇게 Observer가 받을 수 있는 항목이 달라질 수 있게 되는 것임
(Hot Observable이라 두번 째 Observer의 경우, 구독 전에 발행된 1, 2 항목은 받을 수 없는 것)
이제 Hot Observable과 Cold Observable의 차이가 이해가 가셨길 :)
3. Observable(unicast) vs Subject(multicast)
엥 위에서 Hot Observable.. Cold Observable 비교 한거 아닌가요 ..
웬 또 unicast... multicast.. 비교죠..?.. 싶죠 ..
예 ..저도.. 그럽니다.. 이제 운동 해야되는데.. 보내줘 후엥..
사실 위에 내용을 다 이해 했다면 아주 간단하게 끝날 내용임!!!
앞서 공부한 내용이 뭐임?
Cold Observable은 Observer가 어느 시점에 구독하든 똑같은 항목을 발행하는 거였고,
Hot Observable은 Observer가 언제 구독하든 말든 발행하는 거였잖음?
따라서 (Cold) Observable은 unicast고
(Hot Observable인) Subject는 multicast임ㅋ
아하하 ㅋ 끝 ㅋ 하고 싶으나.. ..
예제로 봅시다
3-1. Observable(unicast)
Observable은 나를 구독한 Observer가 몇 개든 간에, "독자적인 실행"을 가짐!!
무슨 말이냐면,
let observable = Observable<Int>.deferred {
return Observable.just(Int.random(in: 0..<100))
}
|
이렇게 defer를 통해 Observable을 생성 했음!!
defer는 Observable이 구독될 당시에 항목을 생성하잖음??
그리고 이제 이 Observable을 여러 Observer에서 구독하면 어떻게 되냐면,
observable.subscribe(onNext: {
print("첫번째 Observer가 받는 항목 : \($0)")
}).disposed(by: disposeBag)
observable.subscribe(onNext: {
print("두번째 Observer가 받는 항목 : \($0)")
}).disposed(by: disposeBag)
|
어떻게 되냐면!!!!
이렇게 두 Observer가 받는 값이 서로 다름!!!
이게 의미하는 것이 바로 앞에 말했던,
Observable이 자신을 구독하는 Observer"들"에 대해 "독자적인 실행" 을 갖는다는 것임
이 Observable에 대한 Observer가 몇 개건 간에,
해당 Observer가 구독을 시작했을 경우,
그 구독에 대한 Observable이 각각 실행되어 Observer들이 서로 다른 값을 갖게 되는 것임!
그렇기 때문에 Cold Observable은 unicast라는 것임!!!
어렵지 않죠 :)
3-2. Subject(multicast)
Subject가 multicast라는 말은,
Subject는 "하나의 Observable의 실행"이 여러 Subscribe에게 "공유"된다는 말임!
예제로 바로 보자면,
subject.subscribe(onNext: {
print("첫번째 Observer가 받는 항목 : \($0)")
}).disposed(by: disposeBag)
subject.subscribe(onNext: {
print("두번째 Observer가 받는 항목 : \($0)")
}).disposed(by: disposeBag)
subject.onNext(Int.random(in: 0..<100))
|
이렇게 subject에 항목이 발행될 경우,
이렇게 해당 Subject를 구독한 Observer들은 모두 "동일한" 결과를 받게 됨!
때문에 Subject는 multicast라는 것임!!!
음.. 실제 코딩을 할때.. 예를 들면 A라는 부모 뷰에서 B, C, D 자식뷰에게
부모의 어떤 상태 값이 변경되었단 걸 뿌려줘야 할 경우, Subject를 사용하면 되겠져!? (RIBs의 방식!)
자, 위에서 이해한거까지 보면 ..
응.. 그래그래.. Subject? Hot Observable이고 .. multicast 방식인거..? 알겠어..
근데 이건 그냥 Observable의 입장에서 아냐? 얘가 왜 Observer의 역할도 한다는 거야?
싶지 않음..?
그래서 이 포스팅이 Subject의 Observable 역할인 것임돠
이제 다음 포스팅에서 Subject의 Observer 역할에 대해서 공부해보도록 하게씀니다
ObserverType이란 놈을 좀 까봐야 해서 너무 길어질까봐 3편으로 나눠버렸움
아마 3일 이내론 올라오지 않을까?
.
.
.
.
아니.. 이거 2시부터 썼는데.. 왜 벌써 8시 ..?
아니지.. 어제도 이거 2시간 넘게 쓰다 이어서 쓴 건데 ... 🥺
RxSwift.. 후.. 쉽지 않다ㅜㅜ
그럼 전 오공완을 완수 했으니.. 이만 운동하러 .. 👋
만약 잘못된 내용, 오타, 피드백 있으면 언제든 댓글 주셔요!!!
참고 글 :
https://sujinnaljin.medium.com/rxswift-subject-99b401e5d2e5
날진은 신이야~ (1호팬 가슴이 벅차오른다)