ReactiveX의 Swift 라이브러리인 RxSwift의 핵심 구성 요소는 Observable과 이를 구독하여 이벤트를 처리하는 Observer이다.
Observer Pattern https://refactoring.guru/design-patterns/observer |
---|
Observable
Observable은 데이터를 방출하는 스트림이다. (시간 개념)
Observable
은 데이터를 비동기적으로 생성하고 방출한다. 데이터는 이벤트로 표현되며, onNext, onError, onCompleted 세 가지 유형이 있다.
Observable
생성Observable.create
Observable.create
는 개발자가 커스텀하게 이벤트를 정의할 수 있도록 제공한다.
import RxSwift
let customObservable = Observable<String>.create { observer in
observer.onNext("Hello")
observer.onNext("RxSwift")
observer.onCompleted() // 스트림 종료
return Disposables.create()
}
customObservable.subscribe(
onNext: { print("onNext:", $0) },
onError: { print("onError:", $0) },
onCompleted: { print("onCompleted") },
onDisposed: { print("onDisposed") }
)
Observable.just
하나의 값을 방출하는 Observable을 생성한다.
let observable = Observable.just("Single Value")
observable.subscribe(onNext: { print($0) })
Observable.of
여러 값을 순차적으로 방출하는 Observable을 생성한다.
let observable = Observable.of(1, 2, 3, 4, 5)
observable.subscribe(onNext: { print($0) })
Observable.from
배열과 같은 Sequence로부터 순차적으로 방출하는 Observable을 생성한다.
let numbers = [1, 2, 3, 4, 5]
let observable = Observable.from(numbers)
observable.subscribe(onNext: { print($0) })
Observable.interval
지정한 시간 간격으로 값을 방출한다. 주로 타이머나 반복 작업에 사용된다.
let observable = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
observable.subscribe(onNext: { print($0) }).disposed(by: DisposeBag())
subscribe
subscribe
는 Observable을 구독하여 이벤트를 처리하는 메서드이다. 주로 onNext, onError, onCompleted 핸들러를 정의한다.
let observable = Observable.of(1, 2, 3)
observable.subscribe(
onNext: { print("onNext:", $0) },
onError: { print("onError:", $0) },
onCompleted: { print("onCompleted") }
)
let coldObservable = Observable.from([1, 2, 3])
coldObservable.subscribe { print($0) }
let subject = PublishSubject<String>()
subject.onNext("Hot") // 구독 전에 방출된 데이터는 받을 수 없음
subject.subscribe { print($0) }
subject.onNext("Observable")
DisposeBag
RxSwift의 메모리 관리를 위해 사용하며, 구독을 명시적으로 해제하지 않아도 DisposeBag
이 해당 구독을 자동으로 해제한다.
기본적으로 구독 후에는 disposed(by: disposeBag)
을 호출해서 구독 해제를 명시해야 한다.
subscribe
를 수행하면 Disposable
객체가 되고, 이를 DisposeBag
안에 담으면 DisposeBag
이 메모리에서 해제될 때 구독의 해제가 함께 일어난다.
let disposeBag = DisposeBag()
Observable.of("Rx", "Swift")
.subscribe { print($0) }
.disposed(by: disposeBag)
.disposed(by:)
를 호출하지 않았는데도 onDisposed
가 출력되는 이유는 subscribe
로 생성된 Disposable
객체가 구독이 끝나거나 오류가 발생했을 때 자동으로 해제(dispose)되기 때문입니다.
Observable
의 생명주기Observable
은 onNext
, onError
, 또는 onCompleted
이벤트 중 하나가 발생하면 구독이 종료된다.Disposable
도 자동으로 해제된다. 따라서 명시적으로 .disposed(by:)
를 사용하지 않아도 onDisposed
는 호출된다.onDisposed
의 호출 시점:onDisposed
는 Observable
의 구독이 종료될 때 호출된다.onError
이벤트가 발생할 때onCompleted
이벤트가 발생할 때dispose()
를 호출할 때.disposed(by:)
를 사용하지 않아도 Observable
의 생명주기가 끝나면 자동으로 onDisposed
가 호출된다. 하지만, 명시적으로 메모리 관리를 하고 싶거나, 구독이 무한히 지속될 수 있는 상황에서는 .disposed(by:)
를 사용하는 것이 필수적이다.
Trait는 Observable의 특수한 형태로, 단일 이벤트나 특정 이벤트 흐름을 명확히 표현하기 위해 사용된다.
Single
단 하나의 값 또는 에러를 방출한다.
하나의 값을 방출하거나, 에러를 방출하면 곧바로 스트림이 종료된다.
( onSuccess
, onFailure
)
let single = Single<String>.create { single in
single(.success("Single Success"))
return Disposables.create()
}
single.subscribe { event in
switch event {
case .success(let value):
print("Success:", value)
case .failure(let error):
print("Error:", error)
}
}
Maybe
값을 방출하거나, 방출하지 않고 완료하거나, 에러를 방출할 수 있다.
( onSuccess
, onError
, onCompleted
)
let maybe = Maybe<String>.create { maybe in
maybe(.success("Maybe Value"))
maybe(.completed) // 값을 방출하지 않을 수도 있음
return Disposables.create()
}
maybe.subscribe { event in
switch event {
case .success(let value):
print("Success:", value)
case .completed:
print("Completed")
case .failure(let error):
print("Error:", error)
}
}
Completable
값을 방출하지 않고 완료하거나 에러를 방출한다.
( onCompleted
, onError
)
let completable = Completable.create { completable in
completable(.completed)
return Disposables.create()
}
completable.subscribe {
print("Completed")
} onError: { error in
print("Error:", error)
}