본문 바로가기
🍎 iOS

[RxSwift] Relays에 대해서 알아보기

by 틴디 2022. 1. 10.
728x90
반응형

Relay란?

Observable과 Subject를 할 때는 RxSwift만 import해줘도 되었지만 Relay는  UI에 사용 되고 PublishSubject의 Wrapper 클래스이자 RxCocoa 클래스 이므로 RxCocoa를 임포트 해주어야 함. (RxRelay라고 있으나 RxCocoa 임포트 하면 함께 임포트 됨)

Relay는 replay subject 와 비슷한 동작을 수행하지만 Subject, Observable과 달리 .completed, .error 이벤트가 없다. 심지어 .next 이벤트가 아닌 accept(_:) 메소드를 사용합니다. terminate 이벤트를 발생시키지 않기 때문에 Dispose 되기 전까지 동작하여 UI에 사용된다고 함

 

PublishRelay

publish relay는 publish subject의 동작과 유사하다. 구독자는 구독하고 난 이후에 방출되는 이벤트를 받아 처리하게 된다. 그렇다면 PublishSubject를 쓰면 되지 왜 PublishRelay를 쓰는 걸까? 우선 Subject와 Relay에는 차이가 있다. Relay의 경우 terminate 이벤트인 .completed  .error 이벤트를 발생 시킬 수 없다. Replay는  Subject를 wrapper 했기 때문에 subject보다 더 작은 범주에 속하고 dispose 전에 종료되지 않는 객체에 대해서 생성해 줄 때 유리하다. 

 

        let relay = PublishRelay<Int>()
        let disposeBag = DisposeBag()
        
        relay.accept(1)

기존에 onNext 로 이벤트를 발생했던 subject와 달리 relay는 accept를 사용한다. 여기에는 '이벤트를 받아서 구독자에게 방출한다'라는 의미를 가지고 있다. 현재 상태에서는 구독자가 없기 때문에 아무런 동작도 하지 않는다. 

여기에 subscriber를 추가해 준다. 

        relay
            .subscribe(onNext: {
                print("첫번째 : ", $0)
            })
        relay.accept(2)

그 후에 새로운 이벤트를 받아 방출하면 첫 번째 subscriber는 해당 element를 받을 수 있다. 

        relay.subscribe(onNext: {
            print("두번째 : ", $0)
        })
        relay.accept(3)

두 번째  subscriber를 추가한 뒤 새로운 이벤트를 방출한다. 

콘솔에서 아래와 같은 결과를 볼 수 있다.

첫번째 :  2
첫번째 :  3
두번째 :  3

PublishSubject와 동일한 기능을 하고 있는 것을 확인할 수 있다. 구독 이후에 방출되는 것에 대하여 동작을 수행한다. 여기서 주의 해야 할 점은 .error, .completed 와 dispose가 같은 것이 아니라는 것이다. Relay의 경우 terminate 이벤트는 없지만 dispose는 가능하다.

 

BehaviorRelay

Behavior Relay는 BehaviorSubject 처럼 동작하지만 다른 점이 있다. 우선 BehaviorRelay는 현재 값(element)을 출력할 수 있다. 현재 값을 알기 위해서 일회성으로  사용 될 새로운 subscriber가 아닌 value 를 이용해 현재 값에 접근 할 수 있다는 장점이 있다. 

또한 .next 이벤트가 발생할 때마다 응답하도록 subject 와 같은 동작을 수행한다.

        let relay = BehaviorRelay(value: "1")
        let disposeBag = DisposeBag()

BehaviorRelay와 DisposeBag을 생성해 준다. BehaviorRelay 도 PublishRelay와 마찬가지로  next 이벤트가 아닌 accept를 이용해서 이벤트를 받아 처리해야 함.

        relay.accept("2")
        
        relay.subscribe({
            print("첫번째 구독자 : ", $0)
        }).disposed(by: disposeBag)
        relay.accept("3")

이벤트를 방출하고 첫 번째 구독자를 등록하면 BehaviorSubject와 동일하게 가장 최근에 방출된 이벤트의 element를 가지고 동작을 수행하는 것을 볼 수 있다. 

따라서 콘솔에는 아래와 같이 찍힌다.

첫번째 구독자 :  next(2)
첫번째 구독자 :  next(3)

이제 여기에 두번째 subscription을 등록한다. 

        relay.subscribe({
            print("두번째 구독자 : ", $0)
        }).disposed(by: disposeBag)

이때 두 번째  subscription은 가장 최근에 방출된 이벤트의 값으로 동작을 수행한다. 따라서 콘솔에는 아래와 같이 찍힌다. 

첫번째 구독자 :  next(2)
첫번째 구독자 :  next(3)
두번째 구독자 :  next(3)
relay.accept("4")
print(relay.value)

이 상태에서 새로운 이벤트를 방출하면 첫번째 구독자와 두번째 구독자 모두 이벤트를 받아 값을 처리할 수 있게 된다. 

마지막에 relay.value가 subject에는 없는 프로퍼티이다. 현재 element 값을 출력할 수 있는 프로퍼티로서 값 타입은 Element 이다. 

현재 값을 얻기 위해 새로운 subject를 만들지 않아도 된다는 장점이 있다. 

 

 

참고 사이트 및 도서 

https://jinshine.github.io/2019/01/05/RxSwift/3.Subject%EB%9E%80/

728x90
반응형

댓글