티스토리 뷰

RxSwift3 Subjects, Relay

Hot Observable vs Cold Observable

  • 언제 이벤트들이 방출 되는지에 따라 Observable을 두가지로 분류할 수 있다.
  • 두가지의 차이점은 다음과 같다.
    • 구독할 시 데이터를 처음부터 발행 여부
    • 이벤트 발생 시점
    • 스트림 분기 성질

Hot Observable

  • Observable을 생성하고 일정 시간이 지난 상태에서 subscribe하면 처음 데이터를 받는 것이 아닌 중간부터 방출된 데이터를 받을 수 있게된다.

  • 구독 여부와 상관없이 데이터를 방출합니다.
  • 데이터를 처음부터 발행하는 것이 아닌 구독 시점에서 방출되는 값을 받기 시작합니다.
  • 스트림을 분기하는 성질이 있다.
  • 마우스, 키보드, 시스템 이벤트와 같은 UIEvent, 타이머, 멀티 캐스팅에서 사용할 수 있다.

Cold Observable

  • Observable을 구독하는 시점부터 처음 데이터부터 방출하므로 구독 이전에는 리소스를 사용하지 않는다.
  • 여러곳에서 구독하면 새로운 Observable 인스턴스를 생성하며 스트림이 생성되므로 리소스 낭비가 될수 있다.

  • 구독하지 않으면 데이터를 방출하지 않는다.
  • 구독을 하면 데이터를 처음부터 발행하기 시작한다.
  • 구독을 하게되면 별도의 스트림이 생성되게 된다.
  • 웹 요청, 데이터베이스 쿼리 등에서 요청했을때 결과를 받을때 사용한다.

Subject의 종류

  • Subject = Observable + Observer (와 같이 행동한다.)
  • Subject는 .next 이벤트를 받고, 이런 이벤트를 수신할 때마다 subscriber에 방출한다.
  • Subject를 사용하면 Cold Observable을 Hot Observable로 변환할 수 있다.
  • RxSwift에는 4가지 타입의 subject가 있다.
    • PublishSubject: 빈상태로 시작하여 새로운 값만을 subscriber에 방출한다.
    • BehaviorSubject: 하나의 초기값을 가진 상태로 시작하며, 새로운 subscriber에게 초기값 또는 최신값을 방출한다.
    • ReplaySubject: 버퍼를 두고 초기화 하며, 버퍼 사이즈 만큼의 값들을 유지하면서 새로운 subscriber에게 방출한다.
    • Bariable: BehaviorSubject를 래핑하고, 현재의 값을 상태로 보존한다. 가장 최신/초기 값만을 새로운 subscriber에게 방출한다.

PublishSubject

  • PublishSubject는 subscribe된 이후부터 이벤트를 방출한다.
  • 이 활동은 subscribe을 멈추거나(구독을 취소하거나), .completed, error 이벤트를 통해 Subject가 종료될 때 까지 지속된다.

let subject = PublishSubject<Int>()
subject.onNext(0)

let subscriptionOne = subject
    .subscribe(onNext: { num in
        print(num)
    })
subject.on(.next(1))
subject.onNext(2)

let subscriptionTwo = subject
    .subscribe({ event in
        print("2)", event.element ?? event)
    })

subject.onNext(3)

subscriptionOne.dispose()

subject.onNext(4)
subject.onCompleted()
subject.onNext(5)

subscriptionTwo.dispose()

let disposeBag = DisposeBag()

subject
    .subscribe {
        print("3)", $0.element ?? $0)
    }
    .disposed(by: disposeBag)

subject.onNext(9999)

/* Prints:
 1
 2
 3
 2) 3
 2) 4
 2) completed
 3) completed
*/
  • 종료되었을 때 존재하는 구독자 뿐만 아니라 이후에 구독한 subscriber에게도 종료 이벤트를 보내준다.
  • 시간에 민감한 데이터를 모델링 할 때 사용한다.(subscribe되기 이전의 값이 필요 없는 경우)

BehaviorSubject

  • PublishSubject 와 비슷하지만 초기 이벤트를 가진 Subject다.
  • subscribe 될때 가장 최신의 .next 이벤트를 전달한다.
  • BehaviorSubject는 항상 최신의 .next 이벤트를 방출하기 때문에 초기값 없이는 만들수 없다. 초기값이 없다면 PublishSubject를 사용하자!

let subject = BehaviorSubject<Int>(value: 0)
let disposeBag = DisposeBag()

subject.onNext(1)

subject.subscribe {
    print("1)", $0.element ?? $0)
}.disposed(by: disposeBag)

subject.onError(TestError.test)

subject.subscribe {
    print("2)", $0.element ?? $0)
}.disposed(by: disposeBag)

/* Prints:
 1) 1
 1) error(test)
 2) error(test)
*/
  • 항상 최신 데이터로 채워 놓아야 하는 경우에 사용한다.(유저 프로필)

ReplaySubject

  • ReplaySubject는 bufferSize갯수의 이벤트를 저장해 subscribe될 때 저장된 이벤트를 모두 방출한다.

let subject = ReplaySubject<Int>.create(bufferSize: 3)
let disposeBag = DisposeBag()

subject.onNext(1)
subject.onNext(2)
subject.onNext(3)
subject.onNext(4)

subject.subscribe {
    print("1)", $0.element ?? $0)
}.disposed(by: disposeBag)

subject.subscribe {
    print("2)", $0.element ?? $0)
}.disposed(by: disposeBag)

/* Prints:
 1) 2
 1) 3
 1) 4
 2) 2
 2) 3
 2) 4
*/
  • 최신의 여러 값들을 보여주고 싶을때 사용한다 (최근 검색어)

Relay

  • Subject와 다르게 error나 complete를 통해 완전 종료될수 없다.
  • subscribe 하고 싶을때는 asObservable을 사용할수 있다.

PublishRelay

  • PublishRelay를 래핑해서 가지고 있는다.
  • Subject는 .completed.error를 받으면 subscribe이 종료된다. 하지만 PublishRelay는 dispose되기 전까지 게속 작동하기 때문에 UIEvent에서 사용하기 적절하다.

BehaviorRelay

  • BehaviorSubject를 래핑해서 가지고 있는다.
  • .value를 사용해 현재의 값을 꺼낼 수 있다. (get-only 프로퍼티)
  • value를 변경하기 위해서 .accept()를 사용한다.

참고한 문서및 자료

https://github.com/fimuxd/RxSwift/blob/master/Lectures/03_Subjects/Ch3.%20Subjects.md
https://okanghoon.medium.com/rxswift-2-observable-subject-relay-8fcd9b01913d

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함