이번에는 앞선 글에서 다룬 Observable를 시작으로, Observer인 Subject, RxCocoa의 Relay 세가지에 대해 알아보려고 합니다.
먼저 이전 글에서 다룬 Observable에 대해 더 자세히 알아봅시다.
Observable
Observable은 이벤트 시퀀스를 비동기적으로 생성하는 기능을 가지고 있습니다.이 때 Observable이 지속적으로 이벤트를 발생시키는 것을 emit 이라고 합니다.
1. Observable의 LifeCycle
next
를 통해 1, 2, 3을 방출하는 Observable
세 번의 tap 이벤트를 방출한 뒤 complete
를 통해 종료된 Observable
1, 2를 방출하고 에러가 발생해 error
를 통해 종료된 Observable
이전 글에서 다뤘던 내용을 정리해보면 아래와 같습니다.
next
: 최신(다음)값을 전송하는 이벤트
error
: Observable이 값을 배출하다 에러가 발생하면 error를 배출하고 종료시키는 이벤트
complete
: 성공적으로 이벤트 시퀀스를 종료시키는 이벤트. Observable이 더 이상 값을 배출하지 않음
2. Observable의 생성
let observable: Observable<Int> = Observable<Int>.just(1)
- just는 오직 하나의 요소를 포함하는 Observable Sequence를 생성
let observables = Observable.of(1, 2, 3)
- of는 주어진 값들에서 Observable Sequence를 생성
let observables2 = Observable.of([1, 2, 3])
- of의 인자로 array를 넣게되면 [1, 2, 3]을 단일요소로 가지게 됩니다
- observables2 의 타입은 Observable<[Int]>
let observables3 = Observable.from([1, 2, 3])
- from을 사용하게 되면 array의 요소들로 Observable Sequence 생성
- observables3 의 타입은 Observable<Int>
3. Subscribing ( 구독 )
Observable은 Sequence의 정의일 뿐이다. Subscribe 되기 전에는 아무런 이벤트도 보내지 않습니다.
- .subscribe는 escaping 클로저로 Event<Int>를 갖는다. escaping에 대한 리턴값은 없으며 Disposable을 반환합니다.
- Prints를 보면 observable은 각 요소들에 대해서
.next
이벤트를 방출합니다. - 마지막으로
.completed
를 방출합니다.
4. subscribe(onNext: , onError:, onCompleted:, onDisposed:)
- Observable이 방출하는
.next
,.error
,.completed
각각의 이벤트들에 대해 subscribe 연산자가 있습니다. - 위에서 사용한 subscribe()은 아래와 같이 사용할 수 있습니다.
onNext 클로저는 .next
이벤트 만을 핸들링하고, onCompleted 클로저는 .completed
만을 핸들링 합니다
5. 여러가지 Observable
지금까지 한개 혹은 여러개의 Element를 가진 Observable을 만들었습니다. 이제 더 다양한 Observable을 살펴봅시다.
.empty()
- .empty 는 요소를 하나도 가지지 않는 Observable을 생성합니다. 따라서
.completed
이벤트만을 방출하게 됩니다. - 즉시 종료할 수 있는 Observable을 리턴하고 싶을 때 사용합니다.
.range()
.range
는 start 부터 count 까지의 값을 갖는 Observable 을 생성하다.
6. Disposing
subscribing은 Observable이 이벤트들을 방출하도록 해주는 방아쇠 역할을 한다면 반대로 disposing은 구독을 취소하여 Observable을 수동적으로 종료시킵니다.
.dispose()
- Int 의 Observable을 생성하고 subscribe을 통해 Disposable을 반환
- 구독을 취소하고 싶으면 dispose()를 호출하면 됩니다.
DisposeBag()
- 각각의 구독에 대해서 일일히 관리하는건 효율적이지 못하기 때문에 RxSwift 에서 제공하는 DisposeBag을 사용할 수 있습니다.
- Disposable은 DisposeBag instance 의 deinit() 이 실행될 때 dispose()를 호출합니다.
.create(:)
Observable을 .create 연산자로 만드는 방법이 있습니다.
- .create 는 escaping 클로저로 AnyObserver<T> 를 인자로 받아 Disposable을 반환합니다.
.next(“1”)
,.completed
,.next(“2”)
의 이벤트를 가진 Observable 을 생성하고 Disposable을 반환합니다.- 여기서
.next(“2”)
의 경우 onComplete 이후이기 때문에 방출되지 않습니다.
7. Traits
Trait은 일반적인 Observable보다 좁은 범위의 Observable
# 종류 : Single
, Maybe
, Completable
Single
무한한 이벤트 스트림이 아닌 하나의 결과, 에러를 처리하고자 할 때 사용
- .success(value) or
.error
만을 방출합니다. - .success(value) 은
.next
와.completed
이벤트의 조합 - HTTP 요청처럼 한 번의 응답 / 에러를 처리할 때 사용합니다
Completable
결과값이 필요하지 않고 완료만 의미 있는 모델에서 사용
.completed
or.error
만을 방출합니다.- 연산이 성공적으로 완료되었는지 확인하고 싶을 때 사용합니다.
Maybe
Single 과 Completable을 섞어 놓은 것
.success(value)
,.completed
,.error
를 방출합니다- 하나의 이벤트가 발생하거나, 이벤트 없이 완료 되거나, 에러가 발생하거나 셋 중 하나의 결과를 발생시키고 종료됩니다
- Observable 을
.asMaybe()
로 변형 가능합니다
8. Hot Observable vs Cold Observable
언제 이벤트들이 방출되는지에 따라 Observable을 두가지로 분류할 수 있습니다.
Hot Observable
- 생성과 동시에 이벤트를 방출하기 시작하는 Observable.
- Subscribe 되는 시점과 상관없이 Observer 에게 이벤트를 중간부터 전송합니다.
Cold Observable
- Subscribe 되는 시점부터 이벤트를 생성해 방출합니다.
9. Subscription 공유
Cold Observable 은 subscribe 되는 시점부터 이벤트를 생성해 방출합니다.
여러번의 subcribe 가 있을 대마다 스트림이 중복으로 발생하게 됩니다.
Subject
우리는 실시간으로 Observable에 값을 추가하고 Subscriber에게 방출하는 것이 필요하다. 이 때 Observable이자 Observer인 Subject 를 사용합니다.
Subject를 사용하면 Cold Observable을 Hot Observable로 변환할 수 있습니다.
PublishSubject
PubishSubject는 subscribe된 이후부터 이벤트를 방출합니다. 이 활동은 subscribe을 멈추거나, .completed
, .error
이벤트를 통해 Subject가 종료될 때까지 지속됩니다.
- 종료되었을 때 존재하는 구독자 뿐만 아니라 이후에 구독한 subscriber에게도 종료 이벤트를 보내줍니다.
- 사용 : 시간에 민감한 데이터를 모델링 할 때 사용합니다 (subscribe 되기 이전의 값이 필요 없는 경우)
BehaviorSubject
PublishSubject 와 비슷하지만 초기 이벤트를 가진 Subject 입니다. subscribe 될때 가장 최신의 .next
이벤트를 전달합니다.
- BehaviorSubject는 항상 최신의
.next
이벤트를 방출하기 때문에 초기값 없이는 만들 수 없습니다. 초기값이 없다면 PublishSubject를 사용합시다.
- 사용 : 항상 최신 데이터로 채워놓아야 하는 경우에 사용 (유저 프로필)
ReplaySubject
ReplaySubject는 bufferSize 개의 이벤트를 저장해 subscribe 될 때 저장된 이벤트를 모두 방출합니다
- 사용 : 최신의 여러 값들을 보여주고 싶을 때 사용 (최근 검색어)
Relay
- Subject와 다르게 error 나 complete 를 통해서 완전종료될 수 없습니다
- subscribe 하고 싶을 때는 asObservable을 사용합니다.
PublishRelay
- PublishSubject를 wrapping 해서 가지고 있습니다.
- Subject 는
.completed
나.error
를 받으면 subscribe 이 종료됩니다. 하지만 PublishRelay는 dispose되기 전까지 계속 작동하기 때문에 UI Event에서 사용하기 적절합니다.
BehaviorRelay
- BehaviorSubject를 wrapping 해서 가지고 있습니다.
.value
를 사용해 현재의 값을 꺼낼 수 있습니다.- Variable이 deprecate 되면서 BehaviorRelay를 대신 사용합니다.
.value
의 경우 get-only-property 이므로 유의합시다. - value를 변경하기 위해서
.accept()
를 사용합니다