천원의 개발

RxSwift Observable vs Subject(Publish, Behavior) 차이점 본문

iOS&Swift🍎/RxSwift

RxSwift Observable vs Subject(Publish, Behavior) 차이점

천 원 2022. 10. 27. 02:19

Observable vs Subject

Observable은 이벤트를 방출 하는 역할을 담당하고 Observable을 구독하는 Observer는 이벤트를 받아서 처리 하는 역할을 담당합니다. 그런데 Observable은 새로운 값을 추가 할 수 없습니다. 그래서 새로운 값을 추가 하고 그것을 방출할 수 있는 객체가 바로 Subject입니다.

 

 

Subject문서를 확인해 보면 Observable을 상속받고 있으며 ObserverType Protocol을 채택 하는 모습을 확인할 수 있습니다.

그래서 Subject는 Observable의 역할과 Observer 역할을 둘 다 수행할 수 있는 겁니다.

 

 

이번에는 ObserverType을 확인해 보면 on 함수가 있는데 이 on함수를 통해서 Observer로 이벤트를 전달할 수 있습니다.

 

let number = BehaviorSubject<Int>(value: 4)

number
    .subscribe { value in
        print(value)
    } onCompleted: {
        print("completed")
    }
    .disposed(by: disposeBag)
    
number.on(.next(7))  // on함수를 통해 새로운 이벤트를 observer로 전달합니다.
number.on(.completed)

// 출력 
4
7
completed

 

 

정리 해보면 결국 Subject는 Observable과 달리 ObserverType을 채택하고 있기 때문에 on 함수를 사용해서 새로운 이벤트를 Observer한테 전달할 수 있는 겁니다.

 

 

Unicast Vs Multicas

일반적으로 Observable은 Observer와 Unicast 형태로 동작하는데 예제를 통해 확인 해봅시다.

 

    let num = Observable<Int>.create { observer in   // 총 3번이 실행된다
        observer.onNext(Int.random(in: 1...100))
        return Disposables.create()
    }

    num.subscribe { value in
        print("Observable \(value)") // Observable next(50)
    }
    .disposed(by: disposeBag)

    num.subscribe { value in
        print("Observable \(value)") // Observable next(36)
    }
    .disposed(by: disposeBag)

    num.subscribe { value in
        print("Observable \(value)") // Observable next(22)
    }
    .disposed(by: disposeBag)

같은 Observable 이지만 새로 subscribe 할 때 마다 새로운 시퀀스가 생기는 형태입니다. 따라서 subscribe를 여러번 하게 될 경우에는 불필요한 리소스가 발생할 수 있습니다.

 

반면에 Subject는 Multicast형태로 동작하기 때문에 subscribe를 여러개 해도 하나의 시퀀스를 공유하게 됩니다.

let num = BehaviorSubject<Int>(value: Int.random(in: 1...100))  // 한번 만 실행

num.subscribe { value in
    print("Subject \(value)") // Subject next(41)
}
.disposed(by: disposeBag)

num.subscribe { value in
    print("Subject \(value)") // Subject next(41)
}
.disposed(by: disposeBag)

num.subscribe { value in
    print("Subject \(value)") // Subject next(41)
}
.disposed(by: disposeBag)

 

 

 

PublishSubject

초기값이 없는 상태로 시작합니다.

구독 시점 이후부터 on함수를 통해 전달받은 이벤트를 처리 합니다.

 

let publish = PublishSubject<Int>() // 초기값이 존재하지 않는다

publish.onNext(1) // on(.next(1)) 이랑 같은형태
publish.onNext(2) // 구독 전에

publish
    .subscribe { value in  // 구독하기
        print("publish -\(value)")
    } onError: { error in
        print("publish -\(error)")
    } onCompleted: {
        print("publish - completed")
    } onDisposed: {
        print("publish - dispose")
    }
    .disposed(by: disposeBag)

publish.onNext(3) // 구독 후에
publish.onNext(4)
publish.on(.next(5))

publish.onCompleted() // 구독취소
    
// 출력
publish -3
publish -4
publish -5
publish - completed
publish - dispose

 

BehaviorSubject

생성시에 초기값을 가지고 시작합니다.

구독 직전의 이벤트를 전달 받습니다.

 

let behavior = BehaviorSubject<Int>(value: 1)

behavior.onNext(2) // 구독 전에

behavior
    .subscribe { value in  // 구독하기
        print("behavior -\(value)")
    } onError: { error in
        print("behavior -\(error)")
    } onCompleted: {
        print("behavior - completed")
    } onDisposed: {
        print("behavior - dispose")
    }
    .disposed(by: disposeBag)

behavior.onNext(3) // 구독 후에
behavior.onNext(4)
behavior.on(.next(5))

behavior.onCompleted() // 구독취소

//출력
behavior -2
behavior -3
behavior -4
behavior -5
behavior - completed
behavior - dispose

 

ReplaySubject

bufferSize에 작성이된 이벤트 만큼, 메모리에 가지고 있다가 구독 직후에 메모리에 저장된 이벤트를 전달 합니다.

let replay = ReplaySubject<Int>.create(bufferSize: 2)

replay.onNext(1)
replay.onNext(2)
replay.onNext(3) // 구독 전에

replay
    .subscribe { value in  // 구독하기
        print("replay -\(value)")
    } onError: { error in
        print("replay -\(error)")
    } onCompleted: {
        print("replay - completed")
    } onDisposed: {
        print("replay - dispose")
    }
    .disposed(by: disposeBag)

replay.onNext(4) // 구독 후에
replay.onNext(5)

replay.onCompleted() // 구독취소

 

 

여기까지 Observable vs Subject 정리였습니다.

 

감사합니다

 

 

 

공부자료 :

🌱SeSAC iOS 2기 77회차, 78회차

https://sujinnaljin.medium.com/rxswift-subject-99b401e5d2e5

 

'iOS&Swift🍎 > RxSwift' 카테고리의 다른 글

RxSwift Operator 정리  (0) 2023.09.11
RxSwift Subscribe, Bind, Drive 차이점  (0) 2022.10.28
RxSwift 개념 정리 (Observable, Disposable)  (0) 2022.10.26