RxSwift

[RxSwift] Subject

thoonk: 2021. 2. 24. 20:02
반응형

Subject에 대해서 기록해보겠습니다. 

 

Subject: 

  • ObserverObservable의 역할을 둘 다 하는 bridge 또는 proxy의 종류이다.
  • Observer의 역할을 하기 때문에 하나 이상의 Observable 구독(subscribe) 있다.
  • Observable의 역할을 하기 때문에 관찰한 이벤트를 방출(emit)할 수 있고 새 이벤트를 방출할 수 있다.
  • Observable을 구독하기 때문에, Observable이 이벤트를 방출할 수 있도록 트리거의 역할을 한다. -> "Cold" Observable를 "Hot"하게 바꿔주는 효과가 있다.

"Cold" Observable: 구독되는 시점부터 이벤트를 생성하여 방출한다. 

"Hot" Observable: 생성되자마자 이벤트를 방출하고 어떤 Observer가 구독하기 시작한 시점과 상관없이 이벤트를 중간부터 전달해준다. 

 


AsyncSubject

  • Complete되면 가장 마지막 이벤트를 방출하고 종료된다.

  • Error가 발생하면 이벤트를 방출하지 않고 에러를 전달한다.

Complete 되기 전 "three"만 출력되는걸 볼 수 있다.

let asyncSubject = AsyncSubject<String>()
asyncSubject
    .subscribe(onNext: {
        print($0)
    })

asyncSubject.onNext("one")
asyncSubject.onNext("two")
asyncSubject.onNext("three")
asyncSubject.onCompleted()

// three

 

활용 예시:

  • 네트워크 요청 결과 처리: 네트워크 요청이 완료되고 응답을 받은 후 해당 데이터만 사용할 때 활용할 수 있음.
  • 폼 제출 처리: 폼 입력 값을 모두 입력하고 제출 버튼을 누른 후 서버에 전송할 때 활용하여 서버 응답에 따라 처리 할 수 있음.

PublishSubject

  • 비어 있는 상태로 시작하여 새로운 값만을 새 구독자(subscriber)에게 방출한다. 
  • 구독하기 전 이벤트는 받을 수 없고 구독된 순간 새로운 이벤트를 전달한다. 
  • 구독을 끝내거나 .completed, .error 이벤트를 통해 Subject가 완전히 종료될 때까지 지속된다. 

아래의 코드를 통해 observer2가 구독하기 전의 이벤트들은 방출되지 않고 구독 후 새로운 이벤트가 방출되는 것을 볼 수 있다. 

let publishSubject = PublishSubject<String>()

publishSubject.subscribe(onNext: { print("observer1: \($0)") })
publishSubject.onNext("one")
publishSubject.onNext("two")
publishSubject.subscribe(onNext: { print("observer2: \($0)") })
publishSubject.onNext("three")
publishSubject.onCompleted()

/*
observer1: one
observer1: two
observer1: three
observer2: three
*/

 

BehaviorSubject

  • 초기 값을 가진 상태로 생성되고 새로운 구독자에게 초기 값 또는 최신 값을 방출한다. 
  • 기본적으로 PublishSubject와 유사하지만 마지막 .next 이벤트를 새로운 구독자에게 반복하여 전달한다. 

아래의 코드를 통해 observer1가 초기 값인 "one"부터 이벤트를 구독받는 것을 볼 수 있고 observer2가 구독 전 마지막 이벤트 "three"와 새로운 이벤트 "four"를 전달받는 것을 볼 수 있다. 

let behaviorSubject = BehaviorSubject<String>(value: "one")

behaviorSubject.subscribe(onNext: { print("observer1: \($0)") })
behaviorSubject.onNext("two")
behaviorSubject.onNext("three")
behaviorSubject.subscribe(onNext: { print("observer2: \($0)") })
behaviorSubject.onNext("four")

/*
observer1: one
observer1: two
observer1: three
observer2: three
observer1: four
observer2: four
*/

 

ReplaySubject

  • n개의 이벤트를 가지는 버퍼에 저장하고 구독되는 시점과 상관없이 버퍼에 저장된 최신의 이벤트들을 새 구독자에게 방출한다.
  • create(bufferSize: Int)createUnbounded() 함수를 통해 생성할 수 있다. 
  • createUnbounded() 는 Subject 생성 이후 모든 이벤트를 저장한다. 

아래의 코드를 통해 observer1이 버퍼 사이즈 2만큼의 최신 이벤트("two", "three")를 전달받는 것을 볼 수 있고 마찬가지로 observer2가 구독 이후 버퍼 사이즈 2만큼의 최신 이벤트("four", "five")를 전달받는 것을 볼 수 있다. 

let replaySubject = ReplaySubject<String>.create(bufferSize: 2)

replaySubject.onNext("one")
replaySubject.onNext("two")
replaySubject.onNext("three")

replaySubject.subscribe(onNext: { print("observer1: \($0)") })
replaySubject.onNext("four")
replaySubject.onNext("five")
replaySubject.subscribe(onNext: { print("observer2: \($0)") })

/*
observer1: two
observer1: three
observer1: four
observer1: five
observer2: four
observer2: five
*/

 

부족한 부분은 피드백해주시면 감사하겠습니다🙃

 

참고:

reactivex.io/documentation/subject.html

github.com/fimuxd/RxSwift/blob/master/Lectures/03_Subjects/Ch3.%20Subjects.md

반응형