본문 바로가기
iOS/RxSwift

Ch3. Subjects

by 헤콩 2023. 2. 24.
반응형

본 게시물은 Florent Pillet, Junior Bontognali, Marin Todorov, Scott Gardner - RxSwift.  Reactive Programming with Swift (2017, Razeware LLC) 책과 ReactiveX 사이트를 기반으로 작성되었습니다.

 

RxSwift를 공부하는 데에 이 책을 읽으면 좋겠다고 생각하였고, 단지 읽기만 하는 것보다 한국어로 직접 정리해놓으면 더 기억하기 좋을 것 같아 게시물을 작성하게 되었습니다.

이번 게시물에서는 마블 다이어그램과, 마블 다이어그램에 해당하는 코드 예시 및 결과를 중점으로 정리하였습니다.


앞서 작성했던 게시물 Chapter 2에서는 Observable이 무엇인지, 어떻게 생성하는지, 어떻게 subscribe하는지, 어떻게 dispose하는지를 배웠습니다. 하지만 보통 앱 개발에서 필요한 것은 실시간으로 Observable에 새로운 값을 수동으로 추가하고 subscriber에게 방출하는 것이 필요합니다. 즉, Observable이자 Observer인 것을 필요로 하는데, 이것이 바로 Subject입니다.

 

 

PublishSubject

  • 구독한 순간부터 발생하는 새로운 이벤트 수신을 알리고 싶을 때 용이합니다.
  • completed나 error 이벤트와 같이 종료 이벤트를 받고 난 이후부터는 completed 이벤트만 방출합니다.
  • 현재의 subscriber에게만 이벤트를 방출합니다. 따라서 어떤 이벤트가 발생했을 때, subscribe하지 않은 상태라면 그 값을 얻을 수 없습니다.
  • 비어있는 상태로 시작하여 새로운 값만을 방출합니다.
  • 실시간 경매 앱처럼 시간에 민감한 데이터를 모델링할 때 용이합니다.

let publishSubject = PublishSubject<String>()

publishSubject.onNext("one")

let subscriptionOne = publishSubject.subscribe(
                          onNext: { string in
                              print("1. \(string)")
                          }
                      )

publishSubject.onNext("two")

let subscriptionTwo = publishSubject.subscribe(
                          onNext: { string in
                              print("2. \(string)")
                          }
                      )

publishSubject.onNext("three")
publishSubject.onCompleted()

subscriptionOne.dispose()
subscriptionTwo.dispose()

 

<결과>

1. two

1. three

2. three

 

 

BehaviorSubject

  • PublishSubject와 비슷하지만, BehaviorSubject는 초기값이 필요합니다.
  • BehaviorSubject는 가장 최근의 next 이벤트를 새로운 구독자에게 방출합니다.
  • 초기값/최신값이 필요한 View를 가장 최신의 데이터로 미리 채워놓는 상황에 용이합니다.

let disposeBag = DisposeBag()
let behaviorSubject = BehaviorSubject(value: "one")

behaviorSubject.subscribe {
    print("1. \($0)")
}.disposed(by: disposeBag)

behaviorSubject.onNext("two")

behaviorSubject.subscribe {
    print("2. \($0)")
}.disposed(by: disposeBag)

behaviorSubject.onNext("three")

 

<결과>

1. one

1. two

2. two

1. three

2. three

 

 

ReplaySubject

내용

  • ReplaySubject는 생성할 때 정한 특정 크기만큼 방출하는 최신 element를 일시적으로 버퍼에 저장합니다. 그리고 저장된 element들을 새로운 subscriber에게 방출합니다.
  • 주의❗️이렇게 일시적으로 저장된 element들은 메모리가 가지고 있기 때문에, 이미지나 array 같이 메모리를 크게 차지하는 값들을 큰 사이즈의 버퍼로 가지는 것은 메모리에 엄청난 부하를 주게 됩니다.
  • 최근 검색어 5개를 보이는 것처럼 최근의 element보다 더 많은 것을 보여주고 싶은 상황에 사용하면 용이합니다.

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

replaySubject.subscribe {
    print("1. \($0)")
}.disposed(by: disposeBag)

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

replaySubject.subscribe {
    print("2. \($0)")
}.disposed(by: disposeBag)

replaySubject.onNext("three")
replaySubject.onError(Error)

replaySubject.subscribe {
    print("3. \($0)")
}.disposed(by: disposeBag)

 

<결과>

1. one

1. two

2. one

2. two

1. three

2. three

1. error

2. error

3. two

3. three

3. error

 

위 결과에서 알 수 있듯이, replaySubject가 종료되었어도 버퍼는 여전히 메모리에 남아있기 때문에 error를 통해 완전 종료시켰음에도 불구하고 새 구독자 3에게 버퍼값을 넘겨줍니다.

따라서 종료시키고 난 다음에는 반드시 dispose하여 이벤트의 재방출을 박아야 합니다.

 

 

Variable

  • 일반적인 Subject나 Observable와 다르게 onNext(_ :)로 새로운 element를 넣지 않습니다.
  • Variable은 에러가 발생하지 않을 것임을 보증합니다. 따라서 error 이벤트를 넣을 수 없습니다.
  • Variable은 할당 해제되었을 때 자동으로 완료되기 때문에 수동적으로 completed를 할 필요도, 할 수도 없습니다.
  • 현재 value값을 확인하고 싶을 때 유용합니다.
  • 제 개인적인 생각으로는 안드로이드의 LiveData와 같은 개념인 것 같습니다.
let disposeBag = DisposeBag()
let variable = Variable("one")

variable.value = "two"

variable.asObservable()
  .subscribe {
    print("1. \($0)")
}.disposed(by: disposeBag)

variable.value = "three"

 

<결과>

1. two

1. three

 

 

AsyncSubject

  • 책에는 없는 내용이지만 ReactiveX 사이트에는 있어서 정리했습니다.
  • Subject가 completed 되면 가장 마지막 데이터만을 그때서야 subscriber에게 전달합니다.
  • 오류로 인해 종료할 경우에는 발생한 오류만 전달합니다.

 

 

 

 

 

반응형

'iOS > RxSwift' 카테고리의 다른 글

Ch7. Transforming Operators  (0) 2023.02.24
Ch5. Filtering Operators  (0) 2023.02.24
RxSwift. Traits가 뭘까? (Single, Maybe, Completable)  (0) 2023.02.24
Ch2. Observable  (0) 2023.02.24
Ch9. Combining Operators  (1) 2021.01.13

댓글