Rxswift iostechtalk

RxSwift 예제로 감잡기 : RxSwift 시작을 위한 간단한 예제들 - iOS Tech Talk

소개

저는 Kakao에서 트래블라인 iOS 앱을 만들었고 현재는 서버 팀에서 일하고 있습니다. 이 강연에서는 트래블라인에 RxSwift를 적용하기 시작했을때 힘들었던 부분을 중점으로 RxSwift를 시작하는 방법을 예제와 함께 보여드리겠습니다.

ReactiveX

rxswift-ReactX

처음 시작할때 ReactiveX에 대해 많은 부분을 생각하게 됩니다. 하지만 제 경우 코드를 모르고 이런 내용을 읽으니 시간이 너무 많이 들었기 때문에 이번 강연에서는 코드를 중심으로 보여드리겠습니다. 코드를 먼저 이해하면 나중에 문서를 읽을때 도움이 될 것 같습니다.

UI Event

rxswift-UIEvent1

옵저버블에서 나오는 이벤트를 비동기식으로 받아서 로직을 붙이는 것으로 많이 사용하는데, 앱 개발을 할 때 가장 많이 사용하는 것이 UI Event 입니다. 버튼이 탭 이벤트를 받을 때마다 탭이 됐다는 void 이벤트가 발생하고, 뒤에서 이를 구독해서 reload라는 로직을 붙여서 구성한 예제입니다. 이런 식으로 간단하게 이용하는 것이 Rx의 기본적인 패턴입니다.

rxswift-UIEvent2

이렇게 구독을 하면 탭을 할 때마다 onNext가 불리게 되는데, RxSwift에서는 bindNext() 라는 간결한 문법을 제공하고 있습니다. reload 함수에 로직을 넣으면 됩니다. bindNext도 self 레퍼런스를 strong하게 capture하기 때문에 사용하지 않게 될 때 명시적으로 disposeBag을 해제하는 등의 주의를 기울여야 합니다.

이런 개발 뉴스를 더 만나보세요

rxswift-UIEvent3

또한 메서드 체이닝으로 오퍼레이터를 추가할 수 있는데, 위 코드처럼 중간에 이벤트에 대한 로그를 넣을 수도 있습니다.

rxswift-UIEvent4

탭을 리로드할 때 너무 여러번 불리는 것을 막기 위해 debounce 함수로 일정 시간 안에 불리는 것은 무시할 수도 있습니다. RxMarbles라는 사이트에서 오퍼레이터의 결과가 실제로 어떻게 나오는지 인터렉티브하게 볼 수 있으니 참고하세요.

REST API

UI 말고도 앱에서는 네트워크 이벤트를 많이 사용하는데, 동기적으로 사용하면 UI가 블럭되거나, 스레드에서 처리하더라도 UI로 넘어갈 때 괴로움을 많이 겪게 됩니다. 이런 어려움도 RxSwift로 해결할 수 있습니다.

rxswift-RESTAPI1

getPage라는 API 요청을 보내면 JSON 형태의 옵저버블이 나오는 예제를 보여드리겠습니다. map으로 JSON을 Page로 변환하는 체이닝 메서드를 붙이고, 구독을 해서 Page를 이용해서 디스플레이를 하는 로직을 붙일 수 있습니다.

이런 API가 언제 호출될지가 궁금하실텐데요. hot, cold의 두 가지 타입을 만들 수 있습니다. 예제의 경우 보통 cold 형태의 옵저버블로 만들어서 구독이 실행될 때 내부의 함수가 실행되고 결과가 비동기적으로 나와서 아래 부분이 실행되게 됩니다. reload 함수가 불렸을 때는 API 함수 자체는 그냥 넘어가고, 내부 블럭에서 다른 스레드로 만들었다면 subscribe가 불렸을 때 실제 API 호출이 넘어가서 불리게 됩니다.

rxswift-RESTAPI2

역시 간결한 문법을 제공하므로 같은 코드를 위 예제처럼 축약해서 사용할 수 있습니다.

rxswift-RESTAPI3

RxSwift 문법은 아니지만 Swift의 문법을 사용해서 다시 보다 간결하게 바꿀 수 있습니다.

rxswift-RESTAPI4

API를 호출했을때 에러가 나면 다시 호출하고, 몇 번 에러가 났는지 카운트해야 하지만, RxSwift를 사용하면 이 역시 간단하게 구현할 수 있습니다.

rxswift-RESTAPI5

스레드도 쉽게 넘나들 수 있는데, subscribeOn으로 옵저버블이 생성되고 결과가 나오는 것을 어느 스레드에서 사용할지 지정할 수 있고, 나온 결과는 observeOn에서 하단 부분에 대해 적용할 수도 있습니다. 예를 들어 Page.init에서 JSON 파싱이 오래 걸리는 경우라면 백그라운드로 넘겨서 파싱을 한 후 UI 스레드로 넘겨서 결과를 업데이트할 수 있습니다.

그 밖에도 앞서 말씀드린대로 로그를 쉽게 추가할 수도 있습니다.

Property Binding

이벤트를 발생시키는 것에 대해 살펴봤으니 이제 이벤트를 받은 옵저버를 어떻게 이용해야 할지 말씀드리겠습니다. Variable의 경우 Subject로 옵저버이기도 하고 옵저버블이기도 합니다.

rxswift-property1

reloading을 옵저버블로 만들어서 true, false 값이 변할때 값을 보겠다고 만들어 줍니다. 다음에 이를 구독해서 reloading 값이 true인 경우 reloadButton을 dis-enable 시킵니다.

rxswift-property2

여기서 reloading 값이 true면 isEnabled 값이 false여야 하므로, 두 값을 반대로 만들기 위해 map을 사용해서 reloading에 대한 결과를 반대로 만들어 주고, subscribe에서 reloadButton의 isEnabled 값과 enabled 값을 같게 만들어줬습니다.

rxswift-property3

다음으로 옵저버 타입인 isEnabled를 bindTo로 바인드시켜주면 enable 상태를 변화시킬 수 있습니다.

Merge Operator

처음 RxSwift 시작할때 힘들었던 점은 RxJava와 달리 예제가 많이 없다는 점이었습니다. 예를 들어 Merge에 대한 API를 찾기 힘들었던 기억이 있어서 Merge Operator에 대해 예제와 함께 살펴 보겠습니다.

rxswift-merge1

두 가지 구문이 있는데, 먼저 isReloading 상태가 바뀔 때 reloadButton의 isEnabled를 바꾸는 구문이 있습니다. 앞서 예제에서는 0.3초 이내의 탭을 무시하도록 했는데, rx를 tap 했을때 버튼 상태가 바로 바뀌도록 하려는 경우를 가정해보겠습니다. 이 경우 위 구문과 함께 reloadButton이 눌렸을 때도 바뀌어야 하므로, 구문이 두 개가 이어지게 됩니다.

rxswift-merge2

공통된 부분을 공유하기 위해 Observable.from에서 배열을 만들고 이를 merge하면 이벤트가 merge됩니다. 앞서 말씀드린 RxMarbles에서 결과를 확인해볼 수 있습니다. 둘 중에 하나만 발생해도 아래 bindTo 부분이 호출될 수 있습니다.

Operators

rxswift-operators

filter, skip, take 등 기본적인 오퍼레이터 몇 개를 설명드리겠습니다. 오른쪽의 text 형태로 타임라인을 표현했습니다. filter를 사용해서 False인 경우만 내려오게 했고, skip을 사용해서 처음 결과를 무시하고, take를 통해 한 번의 결과만 가져오게 하는 과정을 볼 수 있습니다.

이런 식으로 흐름 중에서 데이터를 가공하고 결과적으로 뷰에 반영할 수 있습니다.

그 밖에 활용 범위

그 밖에도 NotificationCenter를 등록하고 취소하는 귀찮은 작업을 RxSwift을 사용하면 옵저버블을 받듯 알림을 받아서 여러 오퍼레이터로 조작할 수 있습니다. Animation 역시 옵저버블로 받아서 애니메이션이 끝났을 때 체이닝으로 여러 가지 작업을 간단하게 할 수 있습니다. 이런 모든 이벤트를 통합적으로 구성할 수 있는 것이 RxSwift의 장점입니다. 계산기 예제를 GitHub에 올려뒀으니 참고하시면 이해에 도움이 될 것 같습니다.

ReactiveX를 정리하며

일반적으로 프로그래밍을 할 때는 프로그램을 직접 pulling해서 호출하지만, Rx는 반대로 밖에서 이벤트가 발생하면 로직이 실행됩니다. 즉, 데이터가 발생하면 수동적으로 pushing 받아서 사용하는 구조입니다. 여러가지 연산자를 이용해서 함수형 프로그래밍과 비슷하게 체이닝해서 데이터를 가공할 수 있습니다. 기본적으로 비동기에 최적화된 프로그래밍 방식입니다. 특히 앞의 예제들을 Callback, Delegate pattern으로 했을면 어땠을지 상상해본다면 RxSwift가 얼마나 좋은 방식인지 체감할 수 있을 겁니다. 마지막으로 RxSwift를 공부하기 좋은 참고 사이트를 공유하며 마치겠습니다.

참고 사이트


이 글은 Realm과 OSXDev가 공동주최한 iOS Tech Talk의 강연을 요약한 것입니다. 전체 발표 슬라이드는 링크에서 확인하세요.

다음: Swift 시작부터 RxSwift까지 #7: RxSwift로 시작하는 함수형 Reactive 프로그래밍 개론

General link arrow white

컨텐츠에 대하여

이 컨텐츠는 저자의 허가 하에 이곳에서 공유합니다.

유용하

안드로이드, macOS/iOS 앱을 한참 하다 지금은 카카오톡 서버를 개발하고 있습니다. 여기에서 프로필을 볼 수 있습니다.

4 design patterns for a RESTless mobile integration »

close