-
RxSwift - Driver & BehaviorRelayRxSwift 2025. 2. 6. 09:44
안녕하세요. 그린입니다 🍏
이번 포스팅에서는 Driver와 BehaviorRelay에 대해 알아보며 연관 관계에 대해 정리해보겠습니다 🙋🏻
그전에, BehaviorRelay에 대해 알고 있는것이 더 편리해요.
해당 포스팅을 사전에 먼저 보시는게 좋습니다 😃
Driver
Driver는 RxCocoa에서 제공하는 특수한 Observable 타입으로, 주로 UI 바인딩을 안전하게 수행해주는데 사용해요.
가장 큰 Driver의 특징은 아래와 같습니다.
1️⃣ 메인 스레드에서 실행 - UI 업데이트는 항상 메인 스레드에서 이뤄져야 하고, Driver가 이를 보장해줍니다.
2️⃣ 에러 미발생 - Driver는 에러를 방출하지 않습니다.
3️⃣ Hot Observable - 새로운 구독이 추가되면 기존 값을 공유하기에 UI 업데이트에 최적화되어 있습니다.
Driver를 생성하는 방법은 간단해요.
let textObservable = textField.rx.text.orEmpty.asDriver(onErrorJustReturn: "")
이렇게 Driver는 주로 asDriver(onErrorJustReturn:)을 통해 변환해 생성됩니다.
위 코드에서 textObservable이 Driver로 변환되었기에, UI 바인딩에 안전하게 사용할 수 있어요!
Driver는 아래와 같이 사용할 수 있습니다.
let inputText = textField.rx.text.orEmpty.asDriver(onErrorJustReturn: "") inputText .map { "입력된 텍스트: \($0)" } .drive(label.rx.text) .disposed(by: disposeBag)
위 코드를 보면 textField의 입력값을 label에 바인딩하는 로직이에요.
drive 메서드를 사용해 UI 관련 처리를 더욱 안전하게 해줍니다.
그럼 다음으로 BehaviorRelay를 볼까요?
BehaviorRelay
BehaviorRelay는 RxSwift에서 가장 많이 사용되는 상태 관리 도구에요.
BehaviorSubject와 유사하지만, 에러를 방출하지 않고 반드시 초기값을 가져야 한다는 점에서 차이가 있죠.
BehaviorRelay의 특징은 다음과 같아요.
1️⃣ 초기값 필수 - 생성 시 반드시 초기값이 필요
2️⃣ 현재 값 저장 및 공유 - 새로운 구독자는 항상 최근 값을 받을 수 있음
3️⃣ 에러 없이 상태 관리 가능 - BehaviorSubject와 달리 에러 미방출
4️⃣ Mutable 상태 관리 - accept 메서드를 사용해 값을 변경할 수 있음
BehaviorRelay는 아래와 같이 사용될 수 있어요.
let relay = BehaviorRelay(value: "초기값") relay.accept("새로운 값") relay.subscribe(onNext: { value in print("현재 값: \(value)") }).disposed(by: disposeBag)
위 코드에서 relay.accept()를 호출해 이후 구독자들은 새 값을 받습니다.
여기까지 Driver와 BehaviorRelay의 간단한 정리를 해봤어요.
이제 오늘의 핵심인 Driver와 BehaviorRelay를 조합하는 연관에 대해 알아볼께요.
Driver와 BehaviorRelay 연관 관계
let relay = BehaviorRelay(value: "초기 값") let textDriver = relay.asDriver() textDriver .drive(label.rx.text) .disposed(by: disposeBag)
BehaviorRelay는 Driver와 함께 사용하면 UI 상태를 더욱 안전하게 관리할 수 있어요.
위 코드처럼 BehaviorRelay를 Driver로 변환하여 UI에 바인딩했어요.
이렇게 처리하면 UI 업데이트가 더욱 안전해집니다.
그럼 이쯤에서 Driver와 BehaviorRelay를 표로 한번 정리해볼까요?
Driver vs BehaviorRelay
항목 Driver BehaviorRelay 사용 목적 UI 바인딩 상태 관리 에러 방출 X X 초기값 필수 X O 멀티캐스트 O O 값 변경 방법 drive() accept(_:) 스레드 보장 O (메인 스레드) X 그럼 다음으로 RxSwift + MVVM 구조를 많이 사용하죠?
그럴때 이런 의문이 들 수 있어요.
ViewModel을 가지고 UI 바인딩을 처리하고 하는데 그럼 BehaviorRelay를 사용하지 않고 ViewModel에서부터 전부 Driver로 작업하면 안되나!?
적어도 저는 처음 접할때(기본개념에 대해 겉만 핥았을때) 이런 생각이 들었습니다.
그래서 그러면 안되는 이유를 한번 살펴볼께요!
ViewModel에서 Driver만 사용하면 안되는 이유
저처럼 ViewModel에서 Driver만 사용해 상태를 관리하려는 경우를 생각할 수 있는데, 이는 몇가지 문제를 발생시켜요.
1️⃣ 상태 변경의 어려움
가장 크게 Driver는 값의 변경이 불가능합니다.
왜냐면 Subject가 아니라 Observable이기 때문이죠.
그래서 새로운 상태를 만들기 위해선 기존 Driver에 새로운 스트림을 결합해야 해요.
이는 상태 관리를 복잡하고 어렵게 만듭니다.
let textDriver = inputRelay.asDriver() textDriver.drive(label.rx.text).disposed(by: disposeBag) // 새로운 값 설정 불가능 -> BehaviorRelay 필요 inputRelay.accept("새로운 값")
2️⃣ ViewModel에서 상태 저장을 위한 용도가 아님
Driver는 UI 바인딩에 최적화된 도구이기에 ViewModel 내부에서 상태를 관리하는 용도로는 적절하지 않아요.
ViewModel 내에서 상태를 저장하려면 BehaviorRelay 혹은 PublishRelay가 필요합니다.
3️⃣ 동적 상태 변경에 부적합
사용자 입력, 네트워크 응답 등에 따라 동적으로 상태를 변경해야 하는 경우 BehaviorRelay가 적절해요.
Driver만 사용하면 새로운 값을 accept 할 수 없기에, UI 상태를 갱신하기 어렵습니다.
// Driver만 사용했을 경우 상태 변경 불가 let isLoading = BehaviorRelay(value: false) let isLoadingDriver = isLoading.asDriver() isLoading.accept(true) // 가능
이런 특성때문에 ViewModel에서 Relay와 Driver를 같이 혼합하여 이용해야 합니다 😃
마무리
RxSwift에서 Driver와 BehaviorRelay는 각각 UI 바인딩과 상태 관리를 위한 핵심 도구에요.
Driver는 UI 바인딩을 안정적으로 수행할 수 있도록 도와주며, BehaviorRelay는 에러 없이 상태를 관리할 수 있는 도구입니다.
ViewModel에서 Driver만을 사용하려는 접근 방식은 상태 관리의 어려움을 가져오기에 BehaviorRelay를 병행하여 사용하는것이 적절합니다.
레퍼런스
'RxSwift' 카테고리의 다른 글
RxSwift - BehaviorSubject vs BehaviorRelay (0) 2025.02.03 RxSwift로 서버 통신하기 (5) 2022.12.19 RxSwift - Time Based Operator (0) 2021.11.17 RxSwift - Combining Operator (0) 2021.11.12 RxSwift - Transforming Operator (0) 2021.11.10