[iOS] RxSwift 연산자

황석범·2025년 1월 19일
0

내일배움캠프_iOS_5기

목록 보기
67/76

RxSwift를 사용한 여러 코드를 구경하면서 본 연산자들을 구경해보고 비교해보자...

요약

연산자역할주요 사용 사례
withUnretainedself의 강한 참조 방지메모리 누수 방지
do사이드 이펙트 추가디버깅, 로깅, 상태 변경
filter조건에 맞는 값만 필터링유효성 검사, 이벤트 조건부 처리
flatMapLatest최신 스트림만 유지검색, API 요청
bindUI와 스트림 연결UI 업데이트
DriverUI 바인딩을 위한 특별한 Observable안전한 UI 데이터 처리
map스트림 값 변환데이터 포맷팅, 계산
merge여러 스트림 결합다중 이벤트 처리
combineLatest최신 값 조합폼 유효성 검사, 상태 계산
takeUntil특정 조건까지 스트림 방출작업 종료

1. withUnretained

  • 강한 참조로 인한 메모리 누수를 방지하면서 이벤트를 수신할 때 self를 안전하게 사용하기 위해
observable
    .withUnretained(self)
    .subscribe(onNext: { (owner, value) in
        owner.updateUI(with: value)
    })
    .disposed(by: disposeBag)

2. do

  • 스트림의 이벤트를 처리하거나 디버깅 용도로 사용. 스트림의 결과를 변경하지 않음
observable
    .do(onNext: { value in
        print("Value received: \(value)")
    }, onError: { error in
        print("Error occurred: \(error)")
    }, onDispose: {
        print("Stream disposed")
    })
    .subscribe()
    .disposed(by: disposeBag)

데이터 흐름을 변경하지 않고 사이드 이펙트 추가나 주로 로깅, 디버깅, 상태 업데이트에 사용


3. filter

  • 조건에 맞는 이벤트만 스트림에 전달
observable
    .filter { $0 > 10 }
    .subscribe(onNext: { value in
        print("Filtered value: \(value)")
    })
    .disposed(by: disposeBag)

특정 조건(Bool을 반환하는 조건문)에 맞는 값만 통과시키거나 유효한 입력이나 특정 상태를 걸러낼 때 사용


4. flatMapLatest

  • 최신 스트림만 유지하며 이전 스트림의 작업을 취소
button.rx.tap
    .flatMapLatest {
        return apiService.fetchData() // 새 요청이 오면 이전 요청은 취소
    }
    .subscribe(onNext: { data in
        print("Fetched data: \(data)")
    })
    .disposed(by: disposeBag)

새로운 값이 들어오면 이전 스트림을 취소하고 최신 스트림만 처리, 주로 API호출이나 검색 입력 같은 최신 상태만 필요한 작업에 유용


5. bind

  • UI 요소와 스트림을 바인딩
viewModel.output.text
    .bind(to: label.rx.text)
    .disposed(by: disposeBag)

데이터를 UI 요소에 직접 연결하거나 에러 처리가 필요하지 않은 UI 바인딩 작업에 적합


6. Driver

  • UI 바인딩을 안전하게 처리하기 위한 Observable의 특별한 형태

특징

  • MainScheduler에서 동작
  • 에러를 방출하지 않음
  • 구독은 항상 공유 됨
let driver = observable
    .asDriver(onErrorJustReturn: "Default value")

driver
    .drive(label.rx.text)
    .disposed(by: disposeBag)

UI와 데이터를 연결할 때 추천, 에러가 발생해도 UI에 안전하게 기본값을 표시할 수 있음


7. map

  • 스트림의 값을 다른 값으로 변환
observable
    .map { $0 * 2 }
    .subscribe(onNext: { value in
        print("Mapped value: \(value)")
    })
    .disposed(by: disposeBag)

입력 값에서 출력 값을 계산하거나 변환할 때 사용, UI 요소에 표시할 데이터를 변환하는데 유용


8. merge

  • 여러 스트림을 하나의 스트림으로 결합
Observable.merge(stream1, stream2)
    .subscribe(onNext: { value in
        print("Merged value: \(value)")
    })
    .disposed(by: disposeBag)

여러 스트림에서 방출된 이벤트를 단일 스트림으로 결합, ex) 여러 버튼의 클릭 이벤트를 처리할 때


9. combineLatest

  • 여러 스트림의 최신 값을 조합
Observable.combineLatest(textField1.rx.text.orEmpty, textField2.rx.text.orEmpty) { text1, text2 in
    return "\(text1) \(text2)"
}
.subscribe(onNext: { combinedText in
    print("Combined text: \(combinedText)")
})
.disposed(by: disposeBag)

모든 입력 스트림 중 하나가 변경될 때마다 모든 최신 값을 조합, 폼 유효성 검사나 복합 상태 계산에 유용


10. takeUntil

  • 특정 조건까지 스트림을 방출
observable
    .takeUntil(button.rx.tap)
    .subscribe(onNext: { value in
        print("Value until tap: \(value)")
    })
    .disposed(by: disposeBag)

주로 작업을 특정 시점에서 중단하거나 종료해야 할 때 사용


bind와 Driver


1. bind

특징

  1. 기본적인 바인딩 도구
  • Observable과 UI 요소를 연결하는 데 사용
  • 에러를 처리하거나 스케줄러를 강제하지 않음
  1. 유연성
  • 에러 처리가 필요한 경우에도 사용할 수 있음
  • UI가 아닌 다른 곳에도 바인딩할 수 있음

장점

  • 간단하고 가벼워서 빠르게 UI와 데이터를 연결할 수 있음
  • 유연하여 다양한 상황에서 사용 가능

단점

  • 에러를 처리하지 않으면 UI에 영향을 줄 수 있음
  • 스케줄러 강제 없이 동작하므로 UI 작업에서는 별도로 MainScheduler를 지정해야 할 수도 있음
observable
    .observe(on: MainScheduler.instance) // UI 작업이므로 MainScheduler에서 실행
    .bind(to: label.rx.text)
    .disposed(by: disposeBag)

2. Driver

특징

  1. UI 바인딩에 최적화
  • Drivers는 Observable의 래퍼로 UI와 데이터를 안전하게 연결하기 위한 특별한 타입
  1. 안정성
  • MainScheduler에서 동작
    • 항상 메인 스레드에서 실행
  • 에러를 방출하지 않음
    • 에러가 발생하면 스트림을 중단하지 않고 기본값(onErrorJustReturn)을 반환
  • 공유
    • 구독자가 여러 명이어도 스트림이 재생성되지 않고 공유
  1. 제약
  • UI 관련 작업에 적합하며 네트워크 비동기 작업에는 사용되지 않음

장점

  • UI와 데이터를 안전하게 바인딩할 수 있습니다.
  • 에러가 발생해도 UI를 중단하지 않고 대체 값을 제공하여 안정성을 보장합니다.
  • 항상 메인 스레드에서 동작하므로, 추가로 observe(on: MainScheduler.instance)를 지정할 필요가 없습니다.

단점

  • 사용 범위가 UI와 관련된 작업으로 제한됩니다.
    = Driver로 변환하기 위해 asDriver(onErrorJustReturn:) 등의 처리가 필요합니다.

bind와 Driver 비교

특징bindDriver
에러 처리에러를 방출하며 직접 처리해야 함에러를 방출하지 않음, 기본값 반환
스케줄러별도로 스케줄러 지정 필요항상 MainScheduler에서 동작
공유기본적으로 공유되지 않음자동으로 공유 (Hot Observable)
사용 대상UI 및 비 UI 요소주로 UI 요소
유연성유연하며 다양한 상황에서 사용 가능UI 바인딩에 최적화
스트림 재사용여러 구독 시 스트림이 재생성됨스트림을 공유하여 재생성 방지

Driver는 Relay와 비슷하게 둘 다 RxCocoa에서 제공하는 주로 UI 관련 작업에서 안정적인 데이터 흐름을 제공하기 위해 사용되는 것 같다.


profile
iOS 공부중...

0개의 댓글

관련 채용 정보