MapleStory Finger Point

[RxSwift] RxSwift를 사용해야 하는 이유?

2024. 4. 12. 18:53iOS Development/RxSwift

https://github.com/ReactiveX/RxSwift

 

 


 

배경

앱 개발 시 외부 이벤트에 대한 응답을 작성하는 코드가 많아질수록 전반적인 코드를 복잡하게 만듦

  • 외부 이벤트에 대한 응답 코드 예시
    • 사용자의 컨트롤 조작에 대해 반응하기 위한 IBAction 핸들러
    • 키보드 위치 변경을 감지하기 위한 Notification 관찰
    • URLSession이 데이터를 수신할 때 실행할 클로저
    • KVO를 사용해서 변수의 변경 사항을 감지

 

따라서 응답 코드에 대한 일관적인 시스템의 요구가 커짐

 

애플의 비동기 API

  • 애플이 iOS SDK 내에서 비동기식 코드를 작성할 수 있도록 제공하는 다양한 API
    • Notification Center, Delegate Pattern, Grand Central Dispatch(GCD), Closure 등

 

  • 일반적으로 대부분의 클래스들은 비동기적으로 작업을 수행함
    • 예를 들면 모든 UI 구성요소들은 본질적으로 비동기로 작동
    • 사용자의 입력이나 네트워크 작업, 기타 OS 이벤트와 같은 다양한 외부 요인에 따라서 매번 다른 순서로 실행될 수 있음
    • 따라서 어떤 코드를 작성했을 때 정확히 어떤 순서로 작동하는지 가정하는 것은 불가능

 

  • 따라서 단순히 애플의 비동기 API 방식으로 복합적인 비동기 코드를 구현 시 부분 별로 나눠 쓰거나 실행 과정을 추적하기 어렵다는 단점이 있음

 

RxSwift

비동기적으로 움직이는 애플의 API를 사용하고 수시로 상태가 변하는 환경에서 보다 직관적이고 효율적인 코드를 작성할 수 있게 도와둠

  • 특징
    1. Bindings
      • Observable이라는 객체를 통해서 이벤트의 흐름을 표현
      • bind를 통해 UI 코드 작성(구체적으로는 RxCococa에서 제공하는 개념)
      • Operator를 통해서 Observable이 내뱉는 이벤트 속의 값들을 여러 형태로 조합하고 변경
      • DispatchQueue로 스레드 작업을 지정해주지 않아도 자동적으로 처리
    2. Retry
      • API 통신을 기반으로 하는 앱은 언제든지 API 콜이 실패할 수도 있는데 RxSwift를 사용하면 기본적으로 retry 연산자를 제공하기 때문에 재시도 기능을 구현하기 용이함
    3. Delegate
      • 어떤 뷰의 delegate를 설정해 줬는지 명시적으로 확인 가능
// 1. Bindings
Observable
    .combineLatest(
        firstName.rx.text,
        lastName.rx.text
    ) { $0 + " " + $1)
    .map { "Greeting, \($0)" }
    .bind(to: greetingLabel.rx.text)
    .disposed(by: disposeBag)
// 2. Retry
doSometing("me")
    .retry(3)
// 3. Delegate
self.resultsTableView.rx.contentOffset
    .map { $0.x }
    .bind(to: self.leftPositionConstraint.rx.constant)
    
// 기존 코드와 비교
public func scrollViewDidScroll(scrollView: UIScrollView) { [weak self] _ in
    self?.leftPositionConstraint.constant = scrollView.contentOffset.x
}
  • RxSwift를 사용하면 좋은 점
    • Composable
    • Reusable
    • Declarative: Operator를 통해 데이터만 변경 가능
    • Understandable & Concise
    • Stable: 상태를 저장하기보다는 앱을 단방향 흐름으로 모델링하기 때문에 안정적
    • Less stateful
    • Without leaks