2021. 9. 17. 11:45ㆍReactiveX
RxSwift를 공부하면서 헷갈리는 개념이 너무 많아서 용어부터 정리해야겠다고 생각했다. Observable, Observer, Subject, Relay, Disposable 등등..... 이 용어들에 대해 정리하고 넘어가자.
Observable과 Observer
Observable은 영어 그대로 해석하면 관찰 가능한 것이라고 해석할 수 있다. Observer는 관찰을 하는 주체이다. 즉 Observer가 Observable을 관찰하고 있다.
공식 문서를 읽어보면 observer는 observable을 구독하고, observable이 발생시키는 아이템을 observer가 사용할 수 있다고 한다.
여기까지만 보면 헷갈릴 것은 별로 없다. 하지만 코드를 작성하다보니 혼란이 왔다. Observable은 다음과 같이 선언할 수 있다.
Observable은 Observer에 의해 관찰될 수 있는 데이터로 선언되었다. 이 데이터를 구독하여 계속 관찰하고 싶을 때에는 다음과 같이 코드를 작성한다.
observable을 subscribe 함수를 통해 구독하고 이벤트가 발생하면 onNext에서 코드를 통해 처리할 수 있다.
이 때, subscribe는 observable 내부의 함수인데 그럼 대체 observer는 어디 있는지 의문이 들었다.
실체가 없는 무언가일까?.... 하고 넘길 뻔했지만 이에 대한 의문이 들어서 검색해 보았다. 그 결과 subscribe 내부에서 observer를 자체적으로 생성하고 있음을 알게 되었다.
subscribe 함수의 내부는 다음과 같이 구현되어있다.
public func subscribe(onNext: ((Element) -> Void)? = nil,
onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil,
onDisposed: (() -> Void)? = nil) -> Disposable {
let disposable: Disposable
if let disposed = onDisposed {
disposable = Disposables.create(with: disposed)
}
else {
disposable = Disposables.create()
}
#if DEBUG
let synchronizationTracker = SynchronizationTracker()
#endif
let callStack = Hooks.recordCallStackOnError ? Hooks.customCaptureSubscriptionCallstack() : []
let observer = AnonymousObserver<Element> { event in
#if DEBUG
synchronizationTracker.register(synchronizationErrorMessage: .default)
defer { synchronizationTracker.unregister() }
#endif
switch event {
case .next(let value):
onNext?(value)
case .error(let error):
if let onError = onError {
onError(error)
}
else {
Hooks.defaultErrorHandler(callStack, error)
}
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
}
}
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
}
이 함수에서 observer를 생성하여 observable을 관찰하는 것이다.
Disposable
그렇다면 위의 코드에서도 계속 나오는 Disposable은 무엇일까? Disposable, Disposables, dispose, DisposeBag 등등.... 여기도 여러 가지 용어들이 나를 혼란스럽게 만들었다.
먼저 Disposable에 대해 알아보자.
/// Represents a disposable resource.
public protocol Disposable {
/// Dispose resource.
func dispose()
}
Disposable을 따라 들어가 보면 위와 같은 코드를 마주할 수 있다. Disposable은 일단 프로토콜이다.
그런데 위에서 subscribe 함수를 자세히 보았을 때, Disposables.create를 반환했는데 Disposable과 어떤 관련이 있는걸까?
Disposables을 따라가보면 다음과 같이 struct가 정의되어있다. create함수는 다른 곳에 정의되어 있는듯 하다.
/// A collection of utility methods for common disposable operations.
public struct Disposables {
private init() {}
}
extension으로 Disposables를 검색해보았다. 인자가 다른 여러 개의 create 함수를 찾을 수 있었다. 가장 간단한 걸로 아래에 두 개의 create 함수 예시를 가져왔다. create는 Disposable이나 Cancelable을 반환하는 모습을 볼 수 있었다.
extension Disposables {
/**
Creates a disposable that does nothing on disposal.
*/
static public func create() -> Disposable {
return NopDisposable.noOp
}
}
/// Creates a disposable with the given disposables.
public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable {
return BinaryDisposable(disposable1, disposable2)
}
여기서 새로 등장한 Cancelable에 대해서도 찾아보았다. Cancelable 역시 Disposable을 상속받고 있었다.
/// Represents disposable resource with state tracking.
public protocol Cancelable : Disposable {
/// Was resource disposed.
var isDisposed: Bool { get }
}
즉, subscribe는 결론적으로 Disposable을 반환하는 것이다. 그런데 이를 어떤 용도로 사용하는 것일까?
Disposable은 직역하면 '처리할 수 있는'이라는 뜻인데, 이는 비동기 작업을 실행하다가 중간에 멈추기 위한 용도로 사용한다. 멈추고 싶을 때는 disposable을 건드리면 되는 것이다!
subscribe 내부 함수에서도 disposable이 이미 존재하는 경우이면 그것을 넘겨주고, 존재하지 않는 경우에 새로 생성한다. 이처럼 disposable을 계속 가지고 있어 이를 쓰레기통에 담음으로써 언제든 처리할 수 있다. 그 쓰레기통이 DisposeBag 이다.
다음과 같은 방식으로 DisposeBag을 활용할 수 있다.
let disposeBag = DisposeBag()
observable.subscribe(onNext: { _ in
})
.disposed(by: disposeBag)
disposable을 직접 처리하고 싶으면 다음과 같이 하면 된다.
disposable.dispose()
이제 Observable, Observer, Disposable, Disposables, DisposeBag 에 관한 개념이 어느 정도 정리된 것 같다.
다음 글에서는 Subject, Relay에 대해 정리하는 글을 작성할 계획이다!
ReactiveX
CROSS-PLATFORM Available for idiomatic Java, Scala, C#, C++, Clojure, JavaScript, Python, Groovy, JRuby, and others
reactivex.io
'ReactiveX' 카테고리의 다른 글
[RxSwift #5] Driver란 무엇일까? (0) | 2022.01.01 |
---|---|
[RxSwift #4] Subject 와 Relay (2) | 2021.09.22 |
[RxSwift #3] Scheduler (0) | 2021.09.20 |
[RxSwift #2] Observable에 대해 (0) | 2021.09.19 |
[RxSwift #0] RxSwift란 무엇일까? (0) | 2021.09.15 |