RxSwift 알아보기

권승용(Eric)·2024년 12월 26일

TIL

목록 보기
25/38

배경

  • RxSwift 지식을 공부해 보았다.

RxSwift?

  • 관찰 가능한 시퀀스를 사용해 비동기 및 이벤트 기반 프로그램을 작성하기 위한 라이브러리인 ReactiveX API를 Swift에 적용한 것
  • Microsoft에서 제작

핵심 개념

Observer & Observable

  • Observable이 값 발행, Observer가 구독 및 관찰 수행
  • Observable은 데이터를 방출하는 스트림.

방출 상태

  • Observable에서 데이터 방출은 상태와 함께 이루어짐
  • onNext: 정상 데이터 방출
  • onError: 에러 방출
  • onCompleted: 옵저버블 종료 사실 방출.

Disposable & DisposeBag

  • 구독을 수행하면 그 반환값은 Disposable 프로토콜을 준수하는 객체
  • 이를 DisposeBag 에 담아두면 DisposeBag이 메모리에서 해제될 때 구독의 해제가 함께 일어난다.

DisposeBag을 사용하는 이유

  • Observable 객체들은 자신이 살아 있는 동안 이벤트를 방출하지만, Observer 객체는 별도의 참조가 없으면 이벤트를 처리한 뒤 사라질 수 있다.
  • Observer 객체가 구독을 유지하기 위해서는 메모리에 남아 있어야 하며, 이를 위해 DisposeBag을 활용한다.
  • 또한 더 이상 사용하지 않는 구독은 메모리 누수 방지를 위해 해제가 필요한데, 이 또한 DisposeBag의 deinit 시점에 모두 해제시키기 위해 DisposeBag 사용.
// RxSwift - DisposeBag.swift
public final class DisposeBag: DisposeBase {
    
    private var lock = SpinLock()
    
    // state
    private var disposables = [Disposable]()
    private var isDisposed = false
    
    /// Constructs new empty dispose bag.
    public override init() {
        super.init()
    }

    /// Adds `disposable` to be disposed when dispose bag is being deinited.
    ///
    /// - parameter disposable: Disposable to add.
    public func insert(_ disposable: Disposable) {
        self._insert(disposable)?.dispose()
    }
    
    private func _insert(_ disposable: Disposable) -> Disposable? {
        self.lock.performLocked {
            if self.isDisposed {
                return disposable
            }

            self.disposables.append(disposable)

            return nil
        }
    }

    /// This is internal on purpose, take a look at `CompositeDisposable` instead.
    private func dispose() {
        let oldDisposables = self._dispose()

        for disposable in oldDisposables {
            disposable.dispose()
        }
    }

    private func _dispose() -> [Disposable] {
        self.lock.performLocked {
            let disposables = self.disposables
            
            self.disposables.removeAll(keepingCapacity: false)
            self.isDisposed = true
            
            return disposables
        }
    }
    
    deinit {
        self.dispose()
    }
}
  • 따라서 구현을 살펴보면 DisposeBag이 deinit 되는 시점에 참조하고 있던 모든 disposable을 메모리에서 해제하는 로직을 확인할 수 있다.

Cold & Hot Observable

  • 구독을 해야 데이터가 방출되기 시작하는 옵저버블은 Cold
  • 구독과 무관하게 데이터가 방출되는 옵저버블은 Hot

Operator

Scheduler

  • Swift의 DispatchQueue와 의미가 동일
  • RxSwift에서 작업을 수행할 때 어떤 스레드에서 수행할 지 지정하는 장치
  • 참고

subscribeOn & observeOn

  • subscribeOn : Observable의 작업이 어느 스케줄러에서 수행될지 결정
  • observeOn : Observer가 Observable을 어느 스케줄러에서 관찰할지 결정

Subject

  • Observable과 Observer의 역할을 모두 수행 가능한 객체
  • BehaviorSubject -> 초기값 있음
  • PublishSubject -> 초기값 없음
  • Behavior -> 현재 상태를 의미. 현재 상태를 방출
  • Publish -> 새로운 이벤트 발행을 의미. 새로운 값을 방출

Relay

  • 에러나 완료 이벤트를 방출하지 않게 설계된 RxCocoa의 Subject
  • 주로 UI 이벤트에서 사용(UI를 그리는 작업은 멈추지 않아야 하기 때문)
  • 마찬가지로 BehaviorRelay, PublishRelay 있음

RxCocoa

  • Swift 언어가 아닌 iOS, macOS 등 프레임워크에 대해 Rx 프로그래밍을 지원하는 도구
  • UI 관련 작업에 대해 반응형 프로그래밍이 가능해진다.

출처

https://github.com/ReactiveX/RxSwift
https://reactivex.io/

profile
ios 개발자에용

0개의 댓글