ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RxSwift - Observable이란?
    Ray Wenderlich/RxSwift 2018. 1. 30. 15:25

    Observables ~ p.54


    What is an observable?

    Rx에는 “observable”, “observable sequence”, “sequence” 이런 단어들이 많이 나온다. 다 같은 의미다.

    가끔 “stream”이란 단어도 나오는데, 우리는 “stream“이란 단어를 사용하도록 하자.


    Observable은 하나의 sequence이고, 여러가지 강점을 갖고 있다.

    그 중 하나가 다들 알겠지만, async하다는 것!


    그리고, Observable이 이벤트를 발생시키는것을 emit한다고 표현한다.

    발생하는 이벤트들은 숫자, 커스텀 인스턴스, 제스쳐(ex. tap) 와 같은 값을 포함할 수 있다.


    그림으로 이해해보자.


    이 그림은 하나의 sequence를 의미한다.

    가로로 긴 화살표는 시간의 흐름을 나타내고 1, 2, 3은 발생하는 이벤트를 나타낸다.

    sequence의 lifetime동안 이벤트는 언제라도 발생할 수 있다.

    참고로 여기서 발생한 1, 2, 3은 next 이벤트에 해당한다.



    Lifecycle of an observable

    이번에는 다른 그림을 살펴보자.

    sequence의 라이프 사이클동안 3개의 tap이벤트가 발생했고, (이 또한 next이벤트에 해당)

    오른쪽에 | 모양이 있다. 이는 completed이벤트에 해당한다.

    이 그림은 어떤 뷰를 세번 탭한 뒤, 뷰가 dismiss되었을 때를 가정할 수 있겠다.

    completed이벤트가 발생하면 sequence가 종료되고, 더 이상 어떤 이벤트도 발생하지 않는다.


    하지만 가끔 sequence에서 에러가 발생할 수 있다.

    위 그림과 달리 X가 있다. 이는 sequence에서 error이벤트가 발생했다는 뜻이다.

    error이벤트도 completed이벤트와 마찬가지로 sequence가 종료되고, 이 sequence에서는 더 이상 이벤트가 발생하지 않는다.

    정리해보면,

    Observable은 라이프 타임에 걸쳐 값을 포함하는 next 이벤트를 발생시킨다.

    - 라이프 타임 중, 오류가 발생하면 error 이벤트를 발생시킨다.

    - 라이프 사이클이 정상적으로 완료되면, completed 이벤트를 발생시킨다.

    - 한번 종료된 sequence에서는 더 이상 이벤트가 발생하지 않는다.


    Event관련된 코드를 보면 더 이해가 잘 되겠다.

    enum Event는 3가지의 case를 갖고 있다. 그 중 next에는 Element에 해당하는 값이 동반되고, error에는 Swift의 에러타입이 동반되는 것을 확인할 수 있다.


    Creating observables

    코드를 통해 살펴보자.

    1. 3개의 Int타입 프로퍼티를 생성했다.

    2. Int타입 sequence를 나타내는 observable이 하나 생성되었다. just메소드는 하나의 파라미터를 받아 한 개의 이벤트를 발생시킨다.

    이름도 참 적절하게 just다. just메소드는 Observable의 클래스메소드이고, 딱 한개의 인자만 받아서 1개의 요소를 갖는 observable을 생성한다.


    두 번째 살펴볼 코드는 of다.

     위와 달리 Int타입을 명시하지 않았다. 스위프트답게 타입추론이 된다.


    이번엔 of의 파라미터로 [Int] 타입이 전달되었다.

    따라서 observable3의 타입은 Observable<[Int]>가 된다.


    이번엔 from을 살펴보자. from은 Array타입을 전달받아 Array안에 있는 요소들을 꺼내서 Sequence를 생성한다.

    즉, observable4는 Observable<Int>타입에 3개 이벤트를 발생시키는 Sequence이다.



    Subscribing to observables

    NotificationCenter에는 익숙할 것이다. observer(Rx에서 말하는 observer말고)들에게 notification을 보내는 방식이다.

    NotificationCenter에서 UIKeyboardDidChangeFrame notification이 발생하는 예제코드를 살펴보자.

    RxSwift에서 subscribe하는 것도 이와 비슷하다. 

    addObserver()대신에 subscribe()를 사용하게 된다.

    NoticiationCenter에서는 .default를 통해 싱글턴 인스턴스를 사용했지만, Rx에서는 다르다. 모든 Observable이 서로 다른 sequence이다.

    observable은 subscriber가 없으면 발생한 이벤트를 전송하지 않는다.


    위에서 Observable.next, .error, .completed 3가지 이벤트를 발생시킨다고 했다.

    next와 error는 각각 element와 error값을 동반한다고도 설명하였다.

    그럼 subscribe하는 과정을 코드를 통해 살펴보자.

    subscribe를 [Option]-[Click]으로 살펴보면 Event<Int> -> Void타입 클로져를 파라미터로 받고 있다.

    그리고 Disposable을 리턴하는데, 이는 뒤에 나온다.

    위 코드가 실행되면 아래 로그가 찍힌다. 총 세 번의 next이벤트와  한 번의 completed이벤트가 발생했다.

    당연한 이야기겠지만,  

    앞으로 Sequence에서 발생한 event 자체보다는 event에 포함된 값(여기선 1,2,3)으로 작업을 많이 하게 된다. (개인적으로 옵셔널과 비슷하다고 보임)


    그렇다면 element에는 어떻게 접근할까? 코드를 보자

    Event enum에는 element라는 프로퍼티가 있었던 것이다! 물론 enum값이 .next일 경우에만

    element는 옵셔널 타입이기 때문에, 옵셔널 바인딩을 사용하여 값에 접근할 수 있다. 코드의 결과는 아래와 같다.

    실제로 Rx에서 퀵하게 값에 접근하기 위해 이런 방법을 많이 쓴다.

    다음으로는 next, error, completed 세 타입의 이벤트 모두를 subscribe하는 operator를 살펴보자.

    바로 위의 코드를 아래처럼 바꿔 쓸 수 있다.

    이 코드는 next이벤트에 대해서만 핸들링하고 있다. next이벤트가 발생하면 그 안에 있는 element를 출력하고 있다.

    (onNext 클로져에서 element를 전달해주기 때문에 위에서처럼 element를 꺼내 바인딩하는 작업이 필요없다.)


    Empty Observable

    (여기서 잠깐 삼천포로 새는것 같은데)

    아까 creating observable을 볼 때, 항상 1개 이상의 element가 있었다. 그럼 인자가 없는 sequence는 어떻게 만들까?

    간단하다. empty operator를 쓰면 된다. 다만 눈여겨볼점은 <Void>로 타입을 명시해주었다. element가 하나도 없기 때문에 타입 추론이 안되기 때문이다.

    그럼 이제 이 empty observable을 subscribe하는 코드를 보자.


    1. next이벤트를 핸들링한다. 그냥 element를 콘솔에 찍어주기로 하자

    2. completed이벤트가 발생하면 마찬가지로 콘솔에 “Completed”를 찍어주자


    결과는 아래와 같다. next이벤트는 발생하지 않았다.

    Empty observable을 어디에 쓰냐? 글쎄, 생성과 동시에 종료되는 sequence를 만들고 싶을 때 쓰면 좋다. (그게 어딘진 몰겠음)


    Never Observable

    (얘네 책 인덱싱 이상하게 하네)

    empty와 반대개념인 never에 대해 알아보자.

    never는 어떤 이벤트도 발생하지 않는 observable이다. 어떤 next이벤트도 발생하지 않으며 심지어 sequence가 끝나지도 않는다.

    위 코드를 실행하면, 콘솔에는 아무것도 찍히지 않는다.


    Range Observable

    지금까지는 Observable을 생성할 때, 우리가 원하는 값을 직접 전달했다. (1, 2, 3 이렇게)

    하지만 이런 방법도 가능하다.

    1. range operator를 이용하여 observable을 생성한다. start인자와 count인자에 값을 전달할 수 있다.

    2. n번째 피보나치를 계산하여 콘솔에 찍고 있다.


    never observable을 제외하면 모두 알아서 completed이벤트를 발생시키고 있다.

    그래서 우리는 observable을 생성하고 subscribe하는 것에만 집중할 수 있었다. 하지만 우리가 모르는 한 가지가 있다.

    그걸 다음장에서 알아보자. (Disposing and terminating)

    댓글 0

Designed by Tistory.