본문 바로가기

Swift/RxSwift

[🔥Rx뿌셔] Subject - Publish Subject

728x90

Subject

Subject는 Observable이자, Observer인 존재이다.

값을 수동으로 추가할 수 있으며 해당 값을 이미 구독 중인 subscriber에 emit할 수 있다.

 

예시 코드를 보자. ⬇️

// 1
let subject = PublishSubject<String>()

// 2
subject.onNext("듣고 있니 .. ?")

// 3
let subscriptionOne = subject
    .subscribe(onNext: { (string) in
        print(string)
    })

// 4
subject.on(.next("얌마.")) // print: 얌마.

// 5
subject.onNext("듣고 있냐고.") // print: 듣고 있냐고.

위의 코드에서 주석으로 표시한 숫자의 흐름은 아래와 동일하다. 

  1. Publish Subject라는 Subject를 생성한다.
  2. 이 때는 아무런 Observer가 없기 때문에 아무런 동작도 하지 않는다.
  3. subscribe를 통해서 observer를 생성한다. 
    1. 이 때 구독을 시작했기 때문에, 이전에 emit한 "듣고 있니 .. ?"의 값은 받을 수 없다.
    2. Publish Subject는 현재 존재하는 observer에게만 이벤트를 전달한다.
  4. "얌마."가 출력 된다. (구독한 이후이므로)
  5. 마찬가지로 "듣고 있냐고."가 출력 된다.

 

여기서 on(.next(_:))는 onNext(_:)와 같다.

 

위와 같은 예시처럼 Subject는 외부로부터 값을 받고, 이를 방출할 수 있다.

 


Publish Subject

Subject의 종류에는 크게 네가지가 존재하는데, 이번 글에서는 위의 예시로도 보았던, Publish Subject에 대해서 알아보자. 

Subject에서 기본적으로 사용되는 형태가 바로 Publish Subject이다.

 

이미지로 나타내면 아래와 같다.

 

코드로 살펴보자.

var subject = PublishSubject<String>()

우선 위와 같이 초기화를 해보자. 이 때, 어떤 타입의 이벤트가 들어갈 것인지 작성해야 한다.

 

 

그리고 나서 onNext, onError, onCompleted 등의 원하는 이벤트를 방출하면 된다.

subject.onNext("sokyte")
subject.onError(error)
subject.onCompleted()

 

그 전의 Observable에서는 구독만 할 수 있었지만,

Publish Subject는 Subject의 한 종류로, 이벤트 방출도 가능하다.

 

그리고 나서 subscribe를 해보면 ..

subject.onNext("hi")
subject.onNext("my")
subject.onNext("name")
subject.onNext("is")
subject.onNext("sokyte")

subject.subscribe(onNext: { element in
    print(element)
}).disposed(by: disposeBag)

 

실행결과

// 출력값이 없다.

아무것도 출력되지 않는 것을 확인할 수 있다.

 

 

🧐 왜 ???

Subject는 Observable과 다르게 subscribe한 이후로 방출된 이벤트만 전달 받기 때문에 !! 

subject.onNext("sokyte") 이후로 subscribe 했으므로 아무것도 출력 되는 것이 없다.

 

 

✅ 그러므로 만약, 출력 값을 얻고 싶다면 ???

구독을 emit 전으로 옮기면 된다.

subject.subscribe(onNext: { element in
    print(element)
}).disposed(by: disposeBag)

subject.onNext("hi")
subject.onNext("my")
subject.onNext("name")
subject.onNext("is")
subject.onNext("sokyte")

 

그러면 아래와 같이 출력 되는 것을 볼 수 있다.

// hi
// my
// name
// is 
// sokyte

 


Publish Subject는 Subject의 한 종류로, 구독한 이후의 이벤트에 대해서 전달을 받아 처리한다. 

 

그 특징을 정리하자면 아래와 같다.

  • 초기값을 갖지 않고 새로운 값을 등록된 Subscriber에게 방출하는 Subject이다.
  • 구독되었을 때부터 새로운 이벤트를 수신하고 싶을 경우 사용한다.
  • 위의 이미지에서 볼 수 있는 것처럼 구독 이후의 방출된 값에서만 수신이 가능하다.
  • 시간이 민감한 데이터를 모델링할 때 유용하다.
    • 예를 들어 실시간 경매 앱이 존재한다고 했을 때 경매 시간이 끝난 이후에 들어온 유저에게 "경매 시간이 얼마남지 않았습니다!"와 같은 메세지를 전달하는 것은 매우 무의미한다.
    • PublishSubject 시간이 지나 구독을 시작한 Subscriber에게는 이벤트를 전달하지 않으므로, 무의미한 이벤트 전달을 하지 않을 수 있다. 

 

 

🔥 정리 
구독하는 시점에 영향을 주는 Observable을 생성하고 싶다면 일반 Observable이 아닌 PublishSubject를 사용하도록 하자!