본문 바로가기

Swift/RxSwift

[🔥Rx뿌셔] Relay

728x90

Relay란?

우선, Relay는 RxCocoa에 속해 있는 클래스이다. 

RxSwift가 아니라, RxCocoa에 속하는 개념으로 그 종류는 크게 세가지가 있다.

 

Relay는 크게 세 가지 클래스가 있다.

  • Publisch Relay
  • Behavior Relay
  • Replay Relay 

 

각 PublishRelay와 BehaviorRelay는 이름에서 알 수 있듯이 PublishSubject랑 BehaviorSubject의 wrapper 클래스이다.

 

 

🤔 Relay와 Subject의 차이는 무엇일까?

이벤트를 방출하는 스타일의 차이이다.

 

✔️ Subject는 Observale와 같이 onNext, onError, onCompleted 이렇게 세 가지의 이벤트를 방출 시킬 수 있다.

 

✔️ Relay는 onNext 대신 accept이라는 이벤트를 방출한다. accept이 onNext의 역할을 한다고 볼 수 있다.

✔️ 그리고 다른 onError나 onCompleted 이벤트는 모두 무시한다. 오직, accept 이벤트만 방출하고 onError나 onCompleted가 방촐되어도 무시하기 때문에 시퀀스가 사라지지 않는다. 

 

 

사용 예시

이렇게 accept이벤트만 방출하고 에러, 완료 이벤트는 모두 무시하는 Relay를 어디에 활용하면 좋을까?

바로 Relay 시퀀스가 절대 사라지지 않는다는 특성을 이용해서 주로 UI를 다룰 때 사용한다.

 

예를 들어서 사용자의 input을 관찰하고 있는 Observable에서 에러가 발생하면 그 상태로 시퀀스가 끝나기 때문에 더 이상의 사용자 input을 관찰할 수 없다.

하지만 Relay를 이용하면 이런 error가 발생해도 무시하므로 시퀀스가 끊기지 않고 다음 input을 정상적으로 관찰할 수 있는 것이다.

 

 

여기까지 요약 !!
Subject는 .completed, .error의 이벤트가 발생하면 subscribe가 종료되는 반면, Relay는 .completed, .error를 발생하지 않고 Dispose되기 전까지 계속 작동하기 때문에 UI Event에서 사용하기 적절하다.
Subject를 Wrapping하는 형태로 구성되어 있다.

UI에 사용하기 좋은 Subject의 변형이다.

 


Publish Relay

이름에서 알 수 있는 것처럼, Publish SubjectWrapper 클래스이다.

 

Publish Subject와 다르게 completed 또는 error와 함께 종료될 수 없다.

accept 메서드를 통해 이벤트를 받고 subscriber에게 전송한다.

 

내부에 Publish Subject가 있으므로 그 외의 특징은 (초기값이 없는 형태) Publish Subject와 동일하다.

 

사용 예시

선언하는 방식 역시 Publish Subject와 유사하다.

var publishRelay = PublishRelay<String>()

 

그리고 이벤트를 방출하기 전에 구독을 먼저 해주면, 아래와 같이 코드를 작성할 수 있다.

publishRelay.subscribe(onNext: { element in
    print(element)
}).disposed(by: disposeBag)

 

이제 이벤트를 방출해보자.

이전의 방식처럼 onNext를 통해서 방출할 수 없다. Relay는 onNext() 대신에 accept()을 사용해야 한다.

publishRelay.accept("hi🙂")

이렇게 이벤트를 방출하면 

 

// hi🙂

위와 같은 결과로 출력되는 것을 확인할 수 있다.

 


Behavior Relay

BehaviorRelayPublishRelay와 마찬가지로 BehaviorSubject의 wrapper 클래스이다. 

그리고 BehaviorSubject와 사용 방식도 굉장히 비슷하다. 

 

Behavior의 특징인 초기값을 갖고 시작한다는 점과 Relay의 특징인 onError와 onCompleted가 발생해도 무시한다는 점을 확인할 수 있다.

 

  • Behavior Subject의 Wrapper 클래스로
  • Behavior Subject와 다르게 completed 또는 error와 함께 종료될 수 없다.
  • accep 메서드를 통해서 이벤트를 받고 subscriber에게 전송한다.
  • 내부에 Behavior Subject가 있기 때문에 그 외 특징은 Behavior Subject와 동일하다. (초기값이 필요하고 값을 보유하고 있다는 점에 있어서) 

 

 

사용 예시

코드로 한번 구현해보자.

 

초기화는 Behavior Subject와 비슷하게 아래와 같이 초기화를 해주면 된다.

var behaviorRelay = BehaviorRelay<String>(value: "Start with me")

 

이벤트를 방출하기 전에 간단하게 요소를 받아서 출력할 수 있는 구독을 하고

behaviorRelay.subscribe(onNext: { element in
    print(element)
}).disposed(by: disposeBag)

 

아래와 같이 accept()을 통해서 방출해주면 된다.

behaviorRelay.accept("hi🙂")

 

 

그리고 실행을 하면 초기값과 함께 구독 이후로 전달한 이벤트를 모두 받아서 출력하는 것을 확인할 수 있다.

// Start with me
// hi🙂

 

 

BehaviorSubject처럼 초기값이 구독과 함께 구독자에게 전달 받은 모습을 확인할 수 있다. 또 BehaviorSubject와 동일하게 새롭게 구독을 하게 되면 “hi🙂” 라는 값과 함께 시작하게 된다.

 

그리고 PublishRelay와 같이 애초에 onErroronCompleted를 취급하지 않다보니 PublishRelay를 통해서 onErroronCompleted 이벤트를 방출시킬 수도 없다.

 

Relay가 애초에 UIKit에 관련된 RxCocoa에 속해있는 것이다 보니 UI와 관련된 처리를 할 때 매우 유용하게 사용될 수 있다.