이번에 이직을 준비하면서 한동안 블로그 관리를 하지 못했다.
그리고 그 과정에서 과제를 받아 미니프로젝트를 진행하게 되었고
RxSwift를 프로젝트에 도입해볼 기회가 생겼었다.
RxSwift를 사용하기 전에는 주로 비동기적으로 발생하는 결괏값을(Networking 작업, 시간이 오래걸리는 작업 등등)
사용하기 위해 complition block을 통한 비동기 처리 사용으로 작업을 해왔더라면
RxSwift에서는 Observable이라는 클래스로 감싸진채로 값을 바로 return 받아
비동기 처리를 동기 처리한것 마냥 사용을 할 수 있다는걸 알게 되었다.
RxSwfit를 사용하지 않고 callback 함수의 구현으로 비동기 처리를 진행 한다고 가정했을때
상황에 따라 계속적인 callback이 발생할수도 있어 흔히 말하는 callBack 지옥이 발생할 수 있다.
또한 Networking 작업을 하다 UI관련 side effect를 구현하기 위해서 Thread 처리도 신경을 써줘야 하는데
그런 부분에 있어서 코드의 간결해짐과 감소량도 RxSwift 사용에 있어 꽤나 장점이라고 할 수 있다.
Rxcocoa를 사용해서 data binding 처리를 손쉽게 진행하여 UI관련 코드들도 간결하게 작성을 할수 있다고 한다는데
이제 막 비동기 결괏값 처리에 대한 사용만 익힌 상태라 Rxcocoa를 제대로 사용해보지 못했다.
Rxcocoa도 많이 궁금했던 부분이라 충분히 학습하고 포스팅 할 계획이다.
그리하여 이번 포스팅에서는 RxSwift에서 가장 중요한 Observable과 observer에 대해서 먼저 알아보겠다.
Observable은 이벤트를 전달하고 ovserver는 Observable을 구독하고 있다가 전달되는 이벤트를 처리한다.
Observable이 전달하는 이벤트의 종류는 3가지이며
1. Next
Observable에서 발생한 새로운 Next 이벤트를 통해서 observer로 전달(emission 또는 방출이라고 함.)
2. Error
Error 발생시 Error 이벤트 전달 (Observable 종료, 모든 리소스 정리)
3. Complete
Observable이 어떠한 Error도 없이 정상적으로 종료될때 Complete 이벤트 전달 (Observable 종료, 모든 리소스 정리)
create 연산자를 사용하여 두개의 정수를 방출하고 종료하는 Observable을 만들어 보겠다.
let myObservable =
Observable<Int>.create { (observer) -> Disposable in
observer.on(.next(0)) // 0이 저장되어 있는 next 이벤트가 observer에게 전달 ( 적어도 하나의 observer가 구독을 한 상태라면 )
observer.onNext(1) // 1이 저장되어 있는 next 이벤트가 observer에게 전달 ( 적어도 하나의 observer가 구독을 한 상태라면 )
observer.onCompleted() // Complete 이벤트가 전달. Observable은 종료되며 다른 이벤트를 전달할 수 없게된다.
return Disposables.create() // 메모리 정리에 필요한 객체
}
위 코드는 단지 두개의 정수를 방출하고 종료하는 Observable을 생성한것일뿐, 정수가 방출되거나 이벤트가 전달되지 않는다.
Observable은 이벤트가 어떤순서로 전달되어야 할지 정의할 뿐이기 때문이다.
진짜로 이벤트가 전달되는 시점은 어떠한 observer가 Observable을 구독하는 시점이라고 할 수 있다.
observer가 Observable을 구독하는 방법은 Observable에서 subscribe 메소드를 호출하는 것이다.
let subscriptionDisposable =
myObservable.subscribe { (element) in // 이벤트 전달시
print(element)
} onError: { (error) in // Observable에서 Error 발생시
print(error)
} onCompleted: { // Observable이 정상적으로 종료될때
print("onCompleted")
} onDisposed: { // 해당 Observable과 괸련된 모든 리소스가 정리되었을때 (리소스 해제 또는 실행 취소시)
print("onDisposed")
}
subscribe 메소드는 클로저를 파라미터로 받으며 이벤트가 전달되어 직접 처리할 수 있다.
또한 위 코드에서는 전부 구현을 해주었지만 각각의 파라미터들은 기본값이 nil로 설정이 되어있어 생략도 가능하다.
observer가 Observable을 subscribe 했을때 메모리 정리에 필요한 객체인 Disposable을 반환하게 되는데
이 return값을 보통 subscriptionDisposable이라고 부른다.
그리고 이것은 리소스 해제 또는 실행 취소시 사용을 하게된다.
subscriptionDisposable.dispose()
그래서 이런식으로 직접 dispose 메소드를 호출하여 리소스를 정리 해줄수 있다.
여기서 문제는 바로 dispose 메소드를 직접 호출시 Complete 이벤트는 전달되지 않고 바로 리소스가 해제되어 버린다.
var bag = DisposeBag()
let subscriptionDisposable =
myObservable.subscribe { (element) in
print(element)
} onError: { (error) in
print(error)
} onCompleted: {
print("onCompleted")
} onDisposed: {
print("onDisposed")
}
.disposed(by: bag)
.
.
.
bag = DisposeBag()
그래서 이런식으로 subscriptionDisposable들을 담아 놓을 수 있는 공간인 DisposeBag을 만들고
subscribe 할때마다 반환되는 subscriptionDisposable을 넣어 주면서 리소스 해제가 필요할때
새로 DisposeBag을 초기화하여 비워주는 식으로 진행을 하는걸 추천한다.
'RxSwift' 카테고리의 다른 글
[RxSwift] Operators (2) (0) | 2021.02.14 |
---|---|
[RxSwift] Operators (1) (0) | 2021.02.12 |
[RxSwift] Subject & Relay (0) | 2021.02.11 |