[iOS | RxSwift] RxSwift, 도대체 뭘까?

minji0801·2022년 1월 8일
0

RxSwift

목록 보기
1/6
post-thumbnail

개요

RxSwift는 여러 기업의 채용공고나 우대조건에서 종종 볼 수 있다. 왜 RxSwift를 알아야 할까? 왜 채용공고에 RxSwift에 대한 우대조건이 있는걸까?
도대체 RxSwift가 뭐가 좋은 건지 알아보자.

👀 RxSwfit 살펴보기

Rx는 기본적으로 비동기적으로 움직이는 Apple의 API 들과 수시로 상태가 변하는 환경에서 직관적, 효율적으로 코드를 작성할 수 있게 도와준다.
참고 : RxSwift - why use rx?

Bindings

Observable.combineLatest(firstName.rx.text, lastName.rx.text) { $0 + " " + $1 }
    .map { "Greetings, \($0)" }
    .bind(to: greetingLabel.rx.text)

Rx에서는 Observable 객체를 통해서 이벤트의 흐름을 표현한다.
그리고 Operator(combineLatest, map 등)를 통해서 Observable이 내뱉는 이벤트의 값들을 해당 형태로 조합하고 변경한다.

combineLatest : 다른 Observable에서 나온 값들을 조합
map : 기존의 Arrary에서 다루던 map과 동일
bind(to:) : UI 코드 작성(기존의 DispatchQueue.main 부분을 자동으로 처리함)

Retries

func doSomethingIncredible(forWho: String) throws -> IncredibleThing

API 통신을 이용한 앱을 만들 때 API 콜이 실패하지 않으면 좋겠지만 언제든 실패할 가능성이 있다. 따라서 API 콜이 실패할 때 재시도할 수 있도록 구현하면 좋을 것이다.

위와 같은 함수는 API 콜이 실패하면 재시도하기 어렵다. 물론 불가능한 것은 아니지만 구현하기가 매우 복잡할 것이다.

doSomethingIncredible("me")
    .retry(3)

그러나 Rx에는 기본적으로 제공하는 retry로 아주 간단하게 재시도를 할 수 있다.

Delegate

public func scrollViewDidScroll(scrollView: UIScrollView) { [weak self] // what scroll view is this bound to?
    self?.leftPositionConstraint.constant = scrollView.contentOffset.x
}

스크롤 뷰가 움직였는지 확인하려면 위와 같은 스크롤 뷰 델리게이트를 작성해야 한다.
위의 코드만 봐서는 어떤 스크롤 뷰에 명령을 하는지 알 수 없다. 또, 델리게이트를 별도로 선언해 줘야 한다.

self.resultsTableView
    .rx.contentOffset
    .map { $0.x }
    .bind(to: self.leftPositionConstraint.rx.constant)

하지만 Rx를 사용하면 훨씬 직관적으로 표현할 수 있다.
resultsTableView가 가지고 있는 스크롤 뷰의 Offset을 원하는 곳에 binding 해주고 있다.

Benefits

RxSwift를 사용하면 다음과 같은 Benefit이 있다고 정리되어 있다.

  • Composable (조합 가능) - Rx는 composition의 별명
  • Reusable (재사용 가능) - 구성 가능하기 때문
  • Declarative (선언형) - 정의는 변경하지 없고 데이터만 변경
  • Understandable and concise (이해하기 쉽고 간결함) - 추상화 수준을 높이고 일시적인 상태를 제거
  • Stable (안정적) - Rx 코드는 철저하게 단위 테스트를 거쳤기 때문
  • Less stateful(상태 저장 안 함) - 단방향 데이터 흐름으로 모델링
  • Without leaks (누수 없음) - 자원관리 용이

‼️ RxSwift 알아보기

RxSwift를 이해하려면 반드시 알아야 하는 구성요소가 있다.

  • Observable
  • Operator
  • Scheduler

Observable은 Swift에서 기본적으로 제공하는 sequence와 동일하다.
sequence는 각 요소들을 순회할 수 있는 타입으로 대표적으로 Array가 있다.

Operator는 Observable의 입력들을 입력받아 결과로 출력해 내는 연산자이고, SchedulerRx의 DispatchQueue라고 생각하면 된다.
참고 : RxSwift - the basics, getting started with RxSwift

Observable

Observable<T>

Observable 클래스는 Rx 코드의 기반이 된다.
제너럴 T로 표현한 T 형태의 데이터 snapshot을 전달하는 이벤트를 비동기적으로 생성한다.
즉, 다른 클래스에서 만든 값을 시간에 따라 읽을 수 있다.

enum Event<Element>  {
    case next(Element)      // next element of a sequence
    case error(Swift.Error) // sequence failed with error
    case completed          // sequence terminated successfully
}

이렇게 세 가지 유형의 이벤트만 생성한다.
next는 최신 또는 다음 데이터를 전달하는데, T에 해당하는 값을 Element로 전달한다.
completed는 성공적으로 이벤트를 종료시킨다.
error는 에러를 발생시켜서 추가적으로 이벤트를 생성하지 않는다.

Network.download(file: "https://www...")
    .subscribe(onNext: { data insequence
    	// 데이터 추가
    },
    onError: { error in
    	// 에러 표현
    },
    onCompleted: {
    	// 다운로드 된 파일 사용
    })

위 예시에서 Network.download가 Observable인 셈이다.
onNext라는 이벤트를 통해서 데이터를 받게 되고, onError 이벤트를 통해서 에러가 발생했을 때 에러를 표현한다. onCompleted 이벤트를 받으면 새로운 액션을 취할 수 있다.

UIDevice.rx.orientation
    .subscribe(onNext: { current in
    	switch current {
        case .landscape:
            // 가로모드
    	case .portrait:
            // 세로모드
    	}
    })

앞선 예시와 다르게 무한하게 관찰 가능한 UI 이벤트 예시를 살펴보자.
orientation 값을 읽어와 현재 방향을 알아온 후 그에 맞게 UI를 설정한다.
여기서는 이벤트가 반드시 발생하기 때문에 error와 completed는 작성하지 않았다.


Operator

UIDevice.rx.orientation
    .filter { value in
    	return value != .landscape
    }
    .map { _ in
    	return "세로모드"
    }
    .subscribe(onNext: { string in
    	showAlert(text: string)
    })

앞서 예시로 들었던 Device Orientation Observable의 Operator 예시이다.
filter를 사용해 orientation이 세로인 경우만 필터링한다. 가로인 경우에는 이벤트가 아예 생성되지 않는다.
map을 통해 string 출력으로 변환되고 마지막으로 subscribe를 통해 onNext 이벤트를 구현한다.

Scheduler

Scheduler는 Rx에서 DispatchQueue와 동일한 것이다. 다만 훨씬 강력하고 쓰기 쉽다.
RxSwift에는 여러 가지 Scheduler가 이미 정의되어 있기 때문에 별도로 Scheduler를 만들 일은 거의 없다.

기존에는 GCD를 통해서 코드를 작성했다면 Scheduler를 통한 RxSwift는 아래와 같이 돌아간다.

예를 들어, Network Subscription은 Background Concurrent Scheduelr에서 먼저 fetch JSON, process JSON 작업을 한 뒤, Main Thread Serial Scheduler로 가서 UI display 작업을 한다.


🛠 RxSwift 설치하기

RxSwift는 여러 가지 방법으로 설치할 수 있지만 대표적으로 아래 두 방법이 있다.
현재 문서에서 Swift Package Manager로 설치하는데 오류가 있다고 설명되어 있으니 CocoaPods으로 설치하는 것을 추천한다.
참고 : RxSwift - Installation

CocoaPods

pod 'RxSwift', '6.2.0'

Swift Package Manager

https://github.com/ReactiveX/RxSwift.git

마무리

RxSwift가 무엇인지 알아보고 설치하는 방법까지 알아보았다.
다음에는 이번에 이론으로만 배운 Observable을 다시 복습하고 실제로 코딩해 보자!

profile
iOS Developer

0개의 댓글