Subject와 Relay

SteadySlower·2022년 3월 30일
0

RxSwift

목록 보기
3/7
post-thumbnail

Subject

발행할 것이 미리 정해진 Observable과는 다르게 일단 구독을 하고 추후에 발행을 하는 객체가 Subject입니다.

Observable과의 차이

ObservableSubject
누군가가 구독을 해야 발행구독을 하지 않아도 개발자가 원하는 때에 발행 가능
각 구독자에게 따로 발행모든 구독자에게 동시에 발행

Subject의 종류

Publish Subject

가장 기본이 되는 Subject입니다. 구독하기 전에도 발행할 수도 있지만 구독하지 않으면 이벤트를 받을 수 없습니다.

import RxSwift

//✅ 구현하기 (발행물의 타입을 제네릭으로 선언합니다.)
let subject = PublishSubject<String>()

//✅ 발행하기
    //🚫 해당 객체를 구독하기 전에 발행해서 출력되지 않습니다.
subject.onNext("구독전 발행 1")

//✅ 구독하기
    //🚫 구독 전에 발행한 것에 대해서는 받을 수 없습니다.
subject.subscribe { event in
    print(event)
}

//✅ 구독 이후에도 발행 가능!
subject.onNext("구독 후 발행 1")
subject.onNext("구독 후 발행 2")

//✅ dispose하거나 complete한 다음에는 추가 발행할 수 없다!
subject.dispose()
subject.onCompleted()

subject.onNext("dispose 후 발행 1") //🚫 발행 안됨
//🖨 출력 결과
next(구독 후 발행 1)
next(구독 후 발행 2)

Behavior Subject

초기 값을 가지는 subject입니다. 항상 마지막으로 발행된 값으로 초기 값을 갱신합니다.

import RxSwift

//✅ 초기 값을 가지고 발행합니다.
let subject = BehaviorSubject(value: "원래 초기 값")

//✅ 구독 전에 발행하면 이전 값을 지우고 발행된 값을 초기 값으로 가지고 있습니다.
subject.onNext("새로운 초기 값")

//✅ 구독하는 순간 초기값을 발행합니다.
subject.subscribe { event in
    print(event)
}

//✅ 구독자에게 발행하고 현재의 초기 값으로 가지고 있습니다.
subject.onNext("또 새로운 초기 값")
//🖨 출력 결과
next(새로운 초기 값)
next(또 새로운 초기 값)

Relay Subject

Behavior Subject와 유사하게 초기 값을 가지고 있지만 여러 개의 초기 값을 가지고 있다는 차이점이 있습니다.

import RxSwift

//✅ buffer size를 정의하여 발행합니다.
let subject = ReplaySubject<String>.create(bufferSize: 2)

//✅ 마지막 n개의 발행물을 buffer size만큼 가지고 있다가 발행합니다.
subject.onNext("발행 1")
subject.onNext("발행 2")
subject.onNext("발행 3")

//✅ 구독 하기
subject.subscribe {
    print("처음 구독: \($0)")
}
    //👉 발행된 값 중에 2개가 저장되어 있다가 발행됩니다.

//✅ 추가적으로 발행하는 것은 정상적으로 발행되고 buffer size만큼 최신의 발행물을 갱신하면서 저장해서 가지고 있습니다.
subject.onNext("발행 4")
subject.onNext("발행 5")
subject.onNext("발행 6")

//✅ 새롭게 구독하면 저장해둔 마지막 2개의 발행인 5, 6을 발행합니다.
subject.subscribe {
    print("두번째 구독: \($0)")
}
//🖨 출력 결과
처음 구독: next(발행 2) //👉 초기값 2개 발행
처음 구독: next(발행 3)

처음 구독: next(발행 4)
처음 구독: next(발행 5)
처음 구독: next(발행 6)

두번째 구독: next(발행 5) //👉 갱신된 초기값 2개 발행
두번째 구독: next(발행 6)

Relay

크게는 Subject와 유사한 개념이라고 보시면 됩니다. 하지만 결정적인 차이가 몇 가지 있습니다.

  • Relay는 Subject와 다르게 RxSwift가 아니라 RxCocoa에 정의되어 있습니다.
  • Subject는 completed 혹은 error의 이벤트가 발생하면 구독을 종료합니다. 반면에 Relay는 completed나 error 이벤트를 발생시키지 않습니다. dispose될 때까지 계속 발행할 수 있습니다. 이러한 특성 때문에 Relay는 UI에 더 사용하기 적합합니다.

종류

Publish Relay

Publish Subject와 거의 동일한 객체입니다. 구독하기 전에 발행된 값은 무시되고 구독하고 발행된 값만 출력되는 모습을 볼 수 있습니다.

import RxCocoa

//✅ 구현하기
let relay = PublishRelay<String>()

//✅ 발행하기
    //👉 Subject와는 다르게 accept라는 키워드로 발행
relay.accept("발행 1")

//✅ 구독하기
relay.subscribe {
    print($0)
}

relay.accept("발행 2")
relay.accept("발행 3")
//🖨 출력 결과
next(발행 2)
next(발행 3)

Behavior Relay

RxSwift에 있던 Variable이라는 클래스를 대체해서 사용할 수 있는 클래스입니다. (Variable은 deprecated 되었습니다.) 초기 값을 가지고 있고 구독하면 초기값을 발행합니다. 그리고 해당 초기 값이 변경될 때 마다 발행됩니다.

import RxCocoa

//✅ 초기값을 가지고 선언!
let relay = BehaviorRelay(value: "원래 초기 값")

//🚫 value를 직접 수정할 수 없습니다! 👉 readOnly
//relay.value = "새로운 초기 값"

//✅ value를 새로 세팅하기
relay.accept("새로운 초기 값")

//✅ asObservable로 구독할 수 있음
relay.asObservable()
    .subscribe {
        print($0) //👉 구독하자마자 초기값이 발행됨!
}

//✅ 구독하고 있을때 초기 값을 바꾸면 발행된다.
relay.accept("다시 또 새로운 초기 값")
//🖨 출력 결과
next(새로운 초기 값) //👉 구독하자마자 초기 값 발행
next(다시 또 새로운 초기 값) //👉 초기 값 바꾸면 새로 발행
profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.

0개의 댓글