RB의 iOS 개발 이야기

Observable과 Subject의 차이는 무엇인가? 본문

iOS/RxSwift

Observable과 Subject의 차이는 무엇인가?

RaeBaek 2023. 10. 27. 12:07

Observable vs Subject

Observable은 이벤트를 방출하는 역할을 담당하고 Observer는 Observable을 구독하며 이벤트를 받아서 처리하는 역할을 담당합니다.

 

여기서 Observable은 새로운 값을 받을 수 없다. 그렇다면 Observer 역할을 하는 녀석은 누구일까?

 

글의 제목에서 유추할 수 있듯이 Observer 역할을 하는 친구가 Subject입니다.

 

Subject의 RxSwift 문서를 확인해보면 Observable을 상속받고 있고 ObservavleType을 채택하고 있습니다.

 

그렇기에 정확히는 'Observer 역할을 하는 친구가 Subject이다.' 라는 말 보다는 'Observable과 Observer의 역할을 모두 가지고 있는 친구가 Subject이다.'가 더 맞는 표현이다!

 

Unicast vs Multicast

Observable과 Subject는 단순히 역할의 차이도 있지만 Unicast와 Multicast의 차이점을 알고 사용하면 더 효과적인 코드를 작성할 수 있을 것 입니다.

 

아래의 코드를 확인해보면

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

    number.subscribe { value in
        print("Number \(value)") // Number 24
    }
    .disposed(by: disposeBag)

    number.subscribe { value in
        print("Number \(value)") // Number 75
    }
    .disposed(by: disposeBag)

    number.subscribe { value in
        print("Number \(value)") // Number 48
    }
    .disposed(by: disposeBag)

 

상수 number는 Observable.create를 통해 랜덤 Int 값 방출하고 있는 상태입니다.

그 아래로 number를 구독하고 있는 코드가 있는데 구독을 할 때마다 새로운 스트림이 발생하여 각기 다른 값을 출력하고 있는 상황을 확인할 수 있습니다. 이것이 Unicast입니다. 이로인해 같은 Observable을 여러 곳에서 구독하게 된다면 자원의 낭비가 발생할 수 있습니다.

 

다음으로 Multicast는 단순하게 Unicast와 반대로 생각하면 편합니다.

let number = BehaviorSubject<Int>(value: Int.random(in: 1...100))

number.subscribe { value in
    print("Subject \(value)") // Subject 20
}
.disposed(by: disposeBag)

number.subscribe { value in
    print("Subject \(value)") // Subject 20
}
.disposed(by: disposeBag)

number.subscribe { value in
    print("Subject \(value)") // Subject 20
}
.disposed(by: disposeBag)

 

Subject는 Multicast로 동작하기 때문에 여러번 구독을 하여도 하나의 스트림을 공유하게 됩니다.

 

그렇다면 Observable을 Muticast로 동작하게 할 수 있는 방법은 없는 것일까?

 

운이 좋게도 가능하다!

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

    number.subscribe { value in
        print("Number \(value)") // Number 39
    }
    .disposed(by: disposeBag)

    number.subscribe { value in
        print("Number \(value)") // Number 39
    }
    .disposed(by: disposeBag)

    number.subscribe { value in
        print("Number \(value)") // Number 39
    }
    .disposed(by: disposeBag)

 

위의 Observable과의 차이점이 보이시나요?

 

바로 상수 number 마지막에 붙어있는 .share()가 차이점입니다.

share 메서드를 활용하게 되면 Observable을 여러 곳에서 구독하더라도 하나의 값으로 사용할 수 있습니다.

 

이렇게 오늘은 Observable과 Subject의 차이점을 알아보았고 .share()을 활용하는 방법까지 알아봤습니다! 감사합니다!