iOS/RxSwift

RxSwift) Subject (2/3) - Subject의 Observer 역할

소들이 2023. 9. 24. 19:39

 

 

 

안녕하세요! 소들입니다 :)

최근에 제 RxSwift 포스팅과 관련해,  "포스팅 내용이 너무 어렵다!" 라는 말을 들었습니다 😂

네.. 사실 맞아요! 제 블로그 글 중에 RxSwift..!?

특히 개념 쪽 부분은 상당히 어려운 편에 속합니다

쉽게 쉽게 설명해주려고 해도 내용 자체가 심오해서 어쩔 수가 없네요 .. ㅠㅠ

 

누군가는 Third Party Library를 왜 이렇게 심오하게 다루냐 할 수도 있지만,

저는 원리도 모른 채 문법을 외워서 기계처럼 쓰는 것을 매우 기피하는 사람이라..

그리고 어차피 님들 Swift Combine 쓸 거 아님...??? 비슷한 기능 까본다 생각하면 되자나!!!

만약 원리 필요 없어! 사용법만 원해! 하시는 분이라면 다음 포스팅으로 가버렷!!

 

서론이 왤케 장황 하냐면,

오늘 내용도 (많이?) 어려워서 ㅎㅎ.. 네.. 열심히 공부하란 말입니다

저 평일에 퇴근하고도 진짜 열심히 공부하고 포스팅 썼는데..

내용이 어려워서 그른가,, 포스팅까지 꽤 걸렸네여?? 🙄

만약 제가 틀린 내용이 있다면 바로바로 피드백 주시길 바랍니다!!

모든 포스팅은 편의 말투로 합니다~!

 

 

 

 

1. Subject의 Observer 역할이 뭔데요?

 

앞서 우리가 

Observable은 항목(이벤트)를 방출!

Observer는 Observable을 구독하여 이벤트를 받음!

이라고 했잖음??

 

근데 사실 우리가 직접 Observer를 만들어 쓸 일이 없었기 때문에,

Observable에 비해서 Observer가 조금 생소할 수 있음...

 

꽤나 여러 번 말했지만,

우리가 Observable을 구독할 때 사용하는 subscribe(onNext:...)라는 메서드는 

Observer 자체가 가진 게 아니었음!!!

 

 

extension ObservableType {
    public func subscribe(
        onNext: ((Element) -> Void)? = nil,
        onError: ((Swift.Error) -> Void)? = nil,
        onCompleted: (() -> Void)? = nil,
        onDisposed: (() -> Void)? = nil
    ) -> Disposable {
        ...
    }
}
 

 

 

Observable 클래스가 채택하고 있는

ObservableType이란 프로토콜 extension에 정의되어 있고,

이 subscribe(onNext...) 메서드를 잘 까보면

 

 

 

 

AnonymousObserver라는 observer를 자체적으로 생성해서

해당 Observable에 대고 이 observer를 subscribe 해주었단 것을 알았잖음??

때문에, 우리가 직접 Observer를 생성할 일이 없었던 것임!

 

근데..

Subject도 subscribe(onNext:...)로 구독해서 받을 수 있었단 말임..?

그렇게 받고 있었고요? 🙄

 

 

subject.subscribe(onNext: {
    print("첫번째 Observer가 받는 항목 : \($0)")
}.disposed(by: disposeBag)
 
subject.subscribe(onNext: {
    print("두번째 Observer가 받는 항목 : \($0)")
}.disposed(by: disposeBag)
 
subject.onNext(Int.random(in0..<100))

 

 

이런 식으루!!!

물론 이벤트를 방출하는 방법은 달랐지만!!

 

근디.. 어차피 subscribe(onNext:...) 메서드를 쓰는 거라면,

해당 메서드 내부에서 AnonymousObserver를 자체적으로 생성해서 구독해줄거잖음..

 

그럼 그냥 Observable과 다른점이 뭐임..?

Subject는 분명 Observable + Observer라구 했는데..

이렇게만 보면 Observer의 역할은 보이지 않구,

 

Subject는 Observable이

Hot🔥인지 / Cold❄️인지

unicast인지 / multicast인지

에 대해서만 관여하는 "Observable" 역할로만 동작하는 거 아닌가요!?!

싶지 않음?? 난 매우 그랬는데!!!!! 

 

이 의문을 해결하기 위해,

우린 Observer에 대해서 좀 더 까봐야 합니당

 

 

 

 

2. Observer를 좀 더 까봅시당 🍌

 

자, 먼저!

Observer라는 것을 좀 더 자세하게 볼 건데여

어떤 객체가 Observer의 역할을 하기 위해선

 

 

 

 

이렇게 ObserverType이란 프로토콜을 채택하고 있어야 함!!!

그리구, 이 ObserverType이란 프로토콜은

 

 

 

 

 on(_ event: Event<Element>)이라는 메서드를 필수적으로 요구하는데,

이때 on이라는 메서드의 파라미터 타입인 Event 타입은

 

 

 

 

next, error, completed이 정의된 열거형 인스턴스인 것을 알 수 있음!!!

 

이잉? 저게 머하는 건데요? 싶을 수 있으나,

우리가 Observable을 볼 때 다 공부한 것임!

항목 방출(next), 에러(error), 정상종료(completed)!!!

 

좀 더 쉽게 이해해보기 위해 예를 봅시당!!

observer의 on이라는 메서드가 언제 불리는지를 보면 되는데,

우리가 Cold Observable 만드는 방법 중 가장 간단한 just 클래스를 보면,

 

 

 

 

init할 때 받았던 element(항목)을 저장하고 있다가,

subscribe가 불릴 경우 그와 동시에 파라미터로 받은 observer에 대고

on(.next(self.element)) 하면서 항목을 방출하고,

또 observer에 대고 on(.completed)을 하는 것을 볼 수 있음

 

아항!

observer의 on이라는 메서드는,

 

 

 

 

Observable이 어떤 Event를 방출할 때,

이를 Observer에게 전달할 때 사용하기 위한 메서드이구나!

 

정리하자면,

Observable에서 일어나는 이벤트를 이 on이라는 메서드를 통해 Observer가 알 수 있는구나!

따라서 Observer가 필수적으로 구현해야 하는 메서드구나!를 알면 됨

 

그럼 이제,

이걸 우리가 알고 있는 AnonymousObserver와 Subject는 이 on이라는 메서드를

각각 어떻게 구현하고 있나 나눠서 보겠음!!

어려울 수 있고... 함수가 잘 안 보일 수 있으니 확대해서 보길 바람

 

 

 

2-1. AnonymousObserver의 Observer 구현

 

기존에 우리가 subscribe(onNext:...)를 썼을 때 

자체적으로 생성한 AnonymousObserver 또한 당연히 Observer 역할이기 때문에

 

 

 

 

AnonymousObserver의 부모 클래스인 ObserverBase

ObserverType이란 프로토콜을 채택하고 있음!!

 

또한, ObserverType 프로토콜에서 요구하는 on 메서드

 

 

 

 

(부모 클래스) ObserverBase 안에 정의되어 있음!!!

그러면 이 on 메서드는 Observable이 항목을 방출(.next) 했을 때의 예로 보자면

 

 

 

 

부모 클래스가 아닌,

AnonymousObserver 자체에서 오버라이딩 한 onCore라는 메서드를 호출함!

그럼 이 onCore 메서드는 내부에 정의된 eventHandler라는 클로저를 호출하는데,

 

 

 

 

이 eventHandler라는 것은,

 subscribe(onNext:...)메서드가  AnonymousObserver를 만들 때 등록해둔 클로저이고

즉,

 

 

 

 

우리가 subsribe(onNext:...)메서드를 호출하며 정의한 클로저가 실행이 된단 것임!!

 

자, 여기까지 이해를 했으면

우리가 subscribe(onNext:...) 메서드를 통해 Observable이 항목을 방출 했을 때

어떤 어떤 작업을 하겠따! 하고 작성해둔 클로저가,

어떤 플로우를 통해 실행이 됐는지를 알 수 있었을 거임!!

 

정리하자면,  

Observer라는 것은

"Obsevable이 Event를 방출 했을 때 누군가에게 알리는 역할"

이라는 것을 이해하면 됨

 

지금은

Observer를 통해 Observable을 구독한 우리(해당 subscribe메서드를 작성한 인스턴스)가

Observer가 알려야 하는 "누군가"가 될 것임!!!

Observer가 없으면, Observable이 항목을 방출했든, 에러를 방출했든

아무도 모를 거 아님!! ㅎㅎㅎ

 

이 관점으로 이해를 한 상태로,

Subject가 on 메서드를 어떻게 구현하고 있는지를 보자ㅏㅏ

 

 

 

2-2. Subject의 Observer 구현

 

subject 또한 Observer의 역할을 한다고 했기 때문에,

 

 

 

 

이렇게 ObserverType을 채택하고 있음!!!

그럼 Subject의 on 메서드는 어떻게 구현되어 있을까!?

 

 

 

 

갑자기 집중력이 흐려지져? 눈 앞이 뿌옇져? 나가고싶져?

나는 어렵다 했어 몰라!

 

뭐 쨌든 Subject의 on 메서드는 대충 이렇게 구현되어 있는데,

AnonymousObserver처럼 바로 등록된 클로저를 실행시키는 게 아니라

if DEBUG 조건문을 빼고 본다면 dispatch 메서드의 첫 번째 파라미터로 

self.synchronized_on(event)라는 메서드의 반환값을 넘겨주고 있음..

 

그럼 self.synchronized_on(event) 얘가 뭘 반환하는데..?

 

 

 

 

대충 .next라는 메서드가 들어왔을 때를 보면,

self.observer"s"라는 옵저버 뭉탱이를 반환하고 잉네

흐헝 observers까지 까보면 진짜 머리 빠개지니까

그냥 observers는 이름 그대로 observer"들"을 담는 객체라고 생각을 하겠음

 

그럼 Subject가 갖고있는 이 observers가 뭔데..? 할 수 있잖음??

이는.. 말야...!!! 다시 돌아가봐야 하눈데..!!!

 

 

 

 

우리가 subject에 대고 subscribe(onNext:...)메서드를 호출했을 때

지겹도록 봤던 AnonymousObserver를 만들고,

이 observer를 observable에 대고 subscribe(_ observer: Observer) 메서드를 호출 하잖음??

 

근데 Subject는!!!

이 subscribe(_ observer:Observer) 메서드를 자체적으로 오버라이딩 하고 있는데,

 

 

 

 

Subject에서 오버라이딩 한 subscribe가 불리면 어떤 일이 일어나냐면,

대충 하이라이팅 친 부분만 보면, 해당 observer를 observers에 insert 하는 것을 볼 수 있음

 

만약,

우리가 subscribe를 여러 번 하면

 

 

 

 

이렇게 각각의 observer가 생성되어,

Subject의 subscribe(_ observer: Observer) 메서드에 의해

Suject 인스턴스가 가지고 있는 observers라는 객체에 insert 되는 것까지 알았음!!!

 

않이,, Observable에 대고 subscribe를 호출 했을 땐,

단순히 클로저를 등록하고 Observable이 이벤트를 방출 했을 때

그 클로저를 실행하느 게 끝이었자나여!!

 

Subject는 왜 observers라는 것도 만들고

여기에 각각의 observer를 등록하는 과정이 들어가는 거져!?!?!? 🙄 싶잖음

 

이것이 바로, subject의

 

 

 

 

multicast 방식 때문임...!!!

subject는 unicast로 동작하는 Observable과 달리,

multicast로 동작한다 했잖음??

 

따라서, Observable이 어떤 이벤트를 방출 했을 때,

동일한 결과를 해당 Subject를 구독하고 있는 Observer"들"에게 모두 알려야 하기 때문임!!!

 

아까 Subject는  on이라는 Observer의 메서드를 실행하면,

 

 

 

 

이렇게 synchronized_on이라는 메서드를 통해

자신을 구독한 observer들의 모임인 "observers"를 반환받고,

이를 dispatch라는 메서드를 통해 발생한 event랑 함께 넘기는데,

 

 

 

 

이 disptach라는 메서드에서는

매개변수로 받은 observers순회하며

observable에서 event가 방출됐음을 알려주는 것임!!!!!

 

때문에 Subject에서

자신을 구독한 Observer들에게 모두 동일한 이벤트를 줄 수 있었던 것임

 

 

아까 내가 Observer를 어떤 관점으로 이해해야 한다 했냐면,

"Obsevable이 Event를 방출 했을 때 누군가에게 알리는 역할"

이라 했짢음

 

따라서!!! 이번 포스팅의 주제인

⭐️Subject의 Observer 역할⭐️

"Obsevable이 Event를 방출 했을 때 나를 구독한 Observer들에게 알리는 역할"

이라고 이해를 하셔야 함!!!

 

Subject가 나를 구독한 observer에게 해당 이벤트가 발생했음에 대해 각각 알리고 나면

➡️ 여기까지가 Subject의 Observer로서 역할

각각의 observer는 subscribe(onNext:...)를 통해 받은 클로저를 실행하여

이벤트를 우리(해당 subscribe를 실행한 인스턴스)에게 알려주는 것

➡️ 여기서부턴 Anonymous의 Observer로서 역할

 

 

실제 Subject의 Observer 역할인 on 메서드를 보면,

 

 

 

 

Notifies all subscribed observers about next event
구독한 모든 observers에게 next event에 대해 알립니다

 

 

라고 쓰여있는 것을 볼 수 있음 ㅎㅎ

 

 

+ 사실 우리가 Subject에서 이벤트를 보낼 때 쓰던 onNext(_ element) 메서드 있잖음 ?ㅎㅁㅎ

 

 

 

 

이는 사실 Observable이 직접 항목을 방출할 수 있게 하는 메서드가 아니라,

ObserverType에 정의된 메서드임!!!

우리가 공부한 Observer의 on 메서드의 파라미터로

해당 Event를 만들어서 호출하는 것을 볼 수 있음!!

이만하면 의문이 다 풀렸길 ㅎㅁㅎ

 

 

 

 

3. 정리

 

Observer의 역할을 하기 위해선 ObserverType이란 프로토콜을 채택해야 한다

ObserverType이란 프로토콜은 on(_ event: Event)라는 메서드를 필수적으로 구현해야 하는데,

Subject에서 이 메서드를 나를 구독한 observer"들"에게 각각 이벤트가 왔음을 실행시켜주게 구현되어 있다

 

따라서, Observer 역할이라는 것은

Observable이 이벤트를 방출 했을 때 그것을 "누군가"에게 알리는 역할이고,

Subject에서는 나를 구독한 모든 Observer들에게 이벤트 방출을 알리는 것으로써

Observer 역할을 수행하고 있따

 

 

 

 

 

.

.

.

 

 

넹... 길고 길었네요...

뭔 거의 2주가량 포스팅을 한 건지 ... 알 쑤가 업써...

나눈 왜 주말에도 왜 공부를 하고 있는지 알 쑤가 업써...

 

 

에헤이 조졌네 이거

 

 

이 글의 포스팅 후기입니다..ㅋㅋㅎㅋㅎㅋㅎㅋㅎㅋㅎ

잘못된 내용이나 피드백거리 있으면 꼭 댓글 주세요!!!!

모두 이해 하셨길 바라며 20,000ㅎㅎㅎㅁㅎㅎㅎㅎ