본문 바로가기

iOS (스파르타)/앱 개발 숙련

RxSwift 공부하기 - 1

RxSwift 를 문법 심화때 맛보기로 했었지만 기억이 안나죠?,,? 진짜 맛보기였던것인가?

 

RxSwift 이해하기

RxSwift 는 Reactive Extension + Swift

또한 RxSwift Github에서는 Reactive Programming in Swift 라고 나와있다.

공통적으로 Reactive, Swift라는 단어가 들어가는데 보면 Reactive는 반응과 관련된 단어이니

생각해보면 Swift에 반응을 더한것?! 이라고 생각하면

RxSwift라는 것은 Swift를 반응형 프로그래밍 하는 것

 

반응형 프로그래밍(Reactive Programming)

반응형 프로그래밍이란, 데이터 흐름 및 변경사항을 전파하는데 중점을 둔 프로그래밍 패러다임.

이 패러다임을 사용할 경우, 주변환경/데이터에 변화가 생길 때

연결된 실행 모델들이 이 이벤트를 받아 동작하도록 설계하는 방식이다.

 

var a = 10
var b = 20
 
var sum = a + b
sum              // 30

 

일반적으로 이렇게 코드를 작성하는데, 만약 a의 변수가 바뀐다면

a = 20
sum              // 30

우리가 평소 하던 일반적인 프로그래밍일 경우, sum 타입은 Int타입이고, 대입할 당시의 a의 값을 복사했고,

sum에 a가 바꼈다고 어떠한 작업을 해주지 않았기 때문에 a의 값이 바뀌었다고해서 sum의 값이 바뀌지는 않는다.

 

그런데 반응형 프로그래밍에서는

a = 20
sum              // 40

a값을 20으로 바꾸면, a가 바뀐 이후 우리가 어떠한 작업을 추가적으로 해주지 않아도 sum의 값이 바뀌어야 한다

 

반응형 프로그래밍이 데이터 흐름 및 변경사항을 전파! 하는데 중점을 뒀고 변화가 생길 때 연결된 실행 모델들이 이 이벤트를 받아 동작하도록 설계하는 방식이라고 했다.

 

a라는 데이터의 흐름이 기존 10에서 20으로 변경되었을 때

이 변경사항에 대해서 a와 연결되어 있는 sum(실행모델)이 이벤트를 전파 받아서 어떠한 동작(값 갱신)을 할 수 있는 것

이게 바로 반응형 프로그래밍이다.

 

실행 모델은 값이 바뀌는지 안바뀌는지에 대해서 관찰을 하고있어야하고 값이 바뀌었을 때 전파 해야한다.

 

이걸 가능하게 해주는 것이 RxSwift의 Observable, Obsever, Operator다.

 

물론 충분히 Swift로도 가능하지만 기존 프로그래밍 방법들로 했을 때의 발생할 수 있는 한계점을 해결해 줄 수 있는 것이

Reactive Programming이자 즉 RxSwift이다.

 

RxSwift는 비동기 프로그래밍을 관찰 가능한 순차적 형태와 함수 형태의 연산자를 통해 처리하게끔 도와준다.

 

 

Obsevable, Observer, Subscibe 흐름에 대해 이해하기

관찰 가능한 순차적인 형태가 바로 Observable

해당 이벤트의 변화를 관찰하여 전파 받는게 바로 Observer

 

Observable과 Observer

 

Observable

Observable은 관찰이 가능한 흐름으로, 비동기 이벤트의 시퀀스를 생성할 수 있는 대상을 말한다.

RxSwift의 Observable이란 것에 대한 정의를 보면

public class Observable<Element> : ObservableType {

 

제네릭 클래스로 구성이 되어있다.

비동기 이벤트를 어떤 관찰 가능한 형태로 만든다는 것은, 비동기 이벤트를 제네릭 타입의 Observable이란 클래스 인스턴스를 만든다는 것과 같은 것이다.

 

비동기 이벤트를 관찰 가능한 형태로 만든 것이 바로 Observable이고, 이 Observable은 실제 그 비동기 이벤트가 일어났을 때, 이를 알리기 위해 그 이벤트에 대한 항목(Item)을 시퀀스로 방출한다.

이 비동기 이벤트가 방출하는 항목은 바로 Observer가 받는다.

 

Observer

Observer는 Observable을 구독한다.

Observer는 내가 원하는 비동기 이벤트를 방출하는 Observable이 있을 때, 해당 "Observable을 구독"을 할 경우,

그 Observable이 비동기 이벤트가 실행되어 항목(Item)을 방출했을 때,

그 항목을 받을 수 있다.

Observer가 Observable을 구독할 수 있게 해주는 것이 바로 Subscibe 라는 메서드이다.

또한 Observer가 이 Subscribe를 통해 Observable을 구독했을 때,

총 세가지 클로저를 파라미터로 넘겨줘서 이벤트를 처리 시킬 수 있는데 Subscibe라는 메서드의 원형을 보면,

public func subscribe(
    onNext: ((Element) -> Void)? = nil,
    onError: ((Swift.Error) -> Void)? = nil,
    onCompleted: (() -> Void)? = nil,
    onDisposed: (() -> Void)? = nil
) -> Disposable

위와 같이 onNext, onError, onCompleted라는 파라미터가 있고(onDisposed는 설명 생략)

모두 타입이 클로저 타입인 것을 알 수 있다.

우리가 기존에 어떤 비동기 이벤트를 넘기고 싶을 때 클로저로 넘겼던 것과 같은 맥락이다.

 

Observer는 내가 구독하려는 Observable이 항목(Item)을 방출했을 때 어떤 작업을 할 것인지,

만약 해당 Observable이 오류가 발생했을 때는 어떤 작업을 할 것인지, 더이상 이벤트가 발생하지 않고 종료됐을때는 어떤 작업을 할 것인지를 subscribe의 메서드 파라미터를 통해 클로저로 같이 넘겨주는 것이다.

 

onNext: Observable이 새로운 항목(Item)을 방출할 때마다 이 클로저가 호출된다. 이때 Observable이 방출하는 항목을 클로저의 파라미터로 전달 받는다.

onError: Observable은 기대하는 데이터가 생성되지 않았거나 다른 이유로 오류가 발생했을 때, 이 오류를 구독자인 Observer에게 알리기 위해 이 메서드를 호출한다.

onCompleted: Observable은 이벤트가 종료되어 더이상 호출되지 않을 때, 이벤트가 완료 되었음을 구독자인 Observer에게 알리기 위해 이 메서드를 호출한다.

 

정리하자면

비동기 이벤트를 관찰 가능한 형태로 만든 것이 Observable,

Observable은 해당 비동기 이벤트가 발생했을 때 항목(Item)을 방출함

관찰 가능한 형태인 Observable을 관찰하는 것이 Observer,

Subscribe(onNext:...) 메서드를 통해 Observable을 구독할 수 있다.

 

 

UIButton 클릭 이벤트로 보는 Observable과 Observer, Subscribe

UIButton의 클릭 이벤트는 비동기 이벤트라 RxSwift에서 Observable이 될 수 있다.

참고로 RxSwift에는 UIKit에 대한 정보가 없기 때문에, UI와 관련된 Reactive Programming을 하려면 RxCocoa를 사용해야 한다.

(그렇다고 RxCocoa만 import하면 안되고, RxSwift로 같이 import해주어야 한다.)

 

이전에 했던 것 오류난것 무시,,하기

UIButton은 UIKit에 속해있기 때문에 RxCocoa를 import해서 UIButton의 tap에 대한 비동기 이벤트 처리를 다음과 같이 작성할 수 있다. (참고로 여기서 tap이벤트란, .touchUpInside에 대한 동작임)

testButton.rx
          .tap
          .subscribe(onNext: {
              print("Observable이 항목을 방출 했다!")
          },
          onError: { error in
              print("에러가 발생 했다!")
          },
          onCompleted: {
              print("해당 이벤트가 끝났다!")
          })
          .disposed(by: disposedBag)

위처럼 작성하면 되는데

위 코드는 지금까지 이론에 공부한 내용 그대로

testButton에 대해 tap event가 발생했을 경우, subscribe(onNext:...)를 통해 "구독"을 해서

해당 Observable이 방출하는 항목에 대해 받을 수 있고,

이때 이 메서드의 파라미터로

onNext(항목이 방출 됐을 때, 즉 버튼이 눌렸을 때 실행시킬 클로저)

onError(에러가 발생했을 때 실행시킬 클로저)

onCompleted(이벤트가 종료되었을 때 실행시킬 클로저)

를 각각 넘겨줄 수 있다.

 

그러면 실제로 버튼이 눌렸을 때(Observable의 항목이 방출됐을 때)

Observer가 등록해놓은 클로저가 실행이 된다.

 

Observer를 만든적이 없고 Observable이 항목 방출했을 때 실행할 클로저만 넘겨줬는데 구독이 되어 항목을 받을수 있는 이유는

subscribe(onNext:...)로 클로저를 넘겨줄 경우, 해당 메서드안에서 자체적으로 AnonymousObserver란 것을 생성해서, 

해당 Observable에 subscribe를 해준다.

 

결론적으로,

subscribe(onNext:...)메서드를 사용할 경우, 메서드 내부에서 옵저버를 자체적으로 생성해서 우리가 따로 Observer를 생성하지 않고

파라미터로 클로저만 넘겨줘도 Observable을 구독하여 방출하는 항목을 받을 수 있게 된 것이다.

참고로, Observer를 직접 생성할 수도 있는데 대표적으로 Observable이자 Observer 역할을 하는 Subject가 있다