[RxSwift] Single vs Observable에서의 데이터 발행(onNext, onSuccess) 비교 실험

ase file

Single .vs. Observable

  • Observable로 만들어진 스트림을 asSingle로 했을 때와 Single로 만들어진 스트림을 asObservable로 했을 때의 차이점을 알아보기 위해 실험을 하였습니다.

Single로 만들어진 스트림을 Observable로 했을 경우

  • 코드
override func viewDidLoad() {
    super.viewDidLoad()
    
    print("=============== Observable Result ===============")
    issueObservable.asObservable()
        .subscribe(onNext: { d in
            print("onNext: \\(d)")
        }, onError: { e in
            print("onError: \\(e)")
        }, onCompleted: {
            print("onCompleted")
        }, onDisposed: {
            print("onDisposed")
        }).disposed(by: disposeBag)
    
    print("=============== Single Result ===============")
    issueObservable
        .subscribe(onSuccess: { d in
            print("onSuccess: \\(d)")
        }, onError: { e in
            print("onError: \\(e)")
        }).disposed(by: disposeBag)
}

var issueSingle: Single<Int> {
    return createSingle()
}

func createSingle() -> Single<Int> {
    
    return Single.create { emitter in
        
        emitter(SingleEvent.success(3))
        emitter(SingleEvent.success(4))
        emitter(SingleEvent.success(5))
        emitter(SingleEvent.success(6))
        
        return Disposables.create()
    }
}

  • 결과
=============== Observable Result ===============
onNext: 3
onCompleted
onDisposed
=============== Single Result ===============
onSuccess: 3

  • 위의 결과를 보면 Single에서 success이벤트를 여러번 수행하더라도 asObservable로 받아온 스트림에서는 onNext를 한번 수행하고, 바로 onCompleted를 수행하는 것을 볼 수 있습니다. 그리고 onDisposed까지 수행하는 것으로 보아, Single로 구현된 스트림에서는 한번의 success이벤트 수행으로 스트림 자체를 dispose까지 시켜버리는 것으로 확인했습니다.
  • single 스트림에서는 onSuccess를 한 번 수행한 것으로 끝났습니다.

Observable로 만들어진 스트림을 Single로 했을 경우

  • 코드
override func viewDidLoad() {
    super.viewDidLoad()
    
    print("=============== Observable Result ===============")
    issueObservable
        .subscribe(onNext: { d in
            print("onNext: \\(d)")
        }, onError: { e in
            print("onError: \\(e)")
        }, onCompleted: {
            print("onCompleted")
        }, onDisposed: {
            print("onDisposed")
        }).disposed(by: disposeBag)
    
    print("=============== Single Result ===============")
    issueObservable.asSingle()
        .subscribe(onSuccess: { d in
            print("onSuccess: \\(d)")
        }, onError: { e in
            print("onError: \\(e)")
        }).disposed(by: disposeBag)
}

var issueObservable: Observable<Int> {
    return createObservable()
}

func createObservable() -> Observable<Int> {
    
    return Observable.create { emitter in
        
        emitter.onNext(3)
        emitter.onNext(4)
        emitter.onNext(5)
        emitter.onNext(6)
        
        return Disposables.create()
    }
}

  • 결과
=============== Observable Result ===============
onNext: 3
onNext: 4
onNext: 5
onNext: 6
=============== Single Result ===============
onError: Sequence contains more than one element.

  • 위 결과를 보면 Observable로 만들어진 스트림에서는 그대로 onNext를 모두 수행하는 것을 볼 수 있었습니다.
  • Single로 만들어진 스트림에서는 onNext를 여러번 수행했기 때문에 한 개보다 많은 element를 가지고 있다는 에러메시지를 보내는 것으로 확인했습니다.

추가 실험

  • Single을 사용하여 받을 때는 DisposeBag에 따로 넣어주지 않더라도 success나 error 이벤트를 호출하면 알아서 dispose까지 시켜주는 것 같아서 직접 실험하였습니다.
override func viewDidLoad() {
    super.viewDidLoad()
    
    print("=============== Observable Result ===============")
    issueSingle.asObservable()
        .subscribe(onNext: { d in
            print("onNext: \\(d)")
        }, onError: { e in
            print("onError: \\(e)")
        }, onCompleted: {
            print("onCompleted")
        }, onDisposed: {
            print("onDisposed")
        })
    
    print("=============== Single Result ===============")
    issueSingle
        .do(onDispose: {
            print("onDispose")
        })
        .subscribe(onSuccess: { d in
            print("onSuccess: \\(d)")
        }, onError: { e in
            print("onError: \\(e)")
        })
}

var issueSingle: Single<Int> {
    return createSingle()
}

func createSingle() -> Single<Int> {
    
    return Single.create { emitter in
        emitter(SingleEvent.error(NSError(domain: "", code: 1, userInfo: nil)))
        emitter(SingleEvent.success(3))
        emitter(SingleEvent.success(4))
        emitter(SingleEvent.success(5))
        emitter(SingleEvent.success(6))
        
        return Disposables.create()
    }
}

  • 결과
=============== Observable Result ===============
onError: Error Domain= Code=1 "(null)"
onDisposed
=============== Single Result ===============
onError: Error Domain= Code=1 "(null)"
onDispose

핵심 결론

  • Single로 만들어진 스트림을 asObservable()을 사용하여 Observable로 만들게 되면 success를 아무리 호출해도 next이벤트 한 번과 complete이벤트 한 번 그리고 dispose 이벤트까지 호출된다. 심지어 Single로 만든 데이터 스트림에서는 DisposeBag으로 관리를 해주지 않아도 됨
  • Observable로 만들어진 스트림을 asSingle()을 사용하여 Single로 만들게 되면 complete 이벤트가 발생하기 전에 한 개 보다 많은 next 이벤트가 발생하면 에러가 발생한다.

- 끄읏😜 -

댓글