본문 바로가기

Swift/RxSwift

[✨ReactiveX] Reactive Introduce / Observable

728x90

Reactive Introduce

Reactive Programming

Reactive Programming이란?
: 비동기적 데이터 흐름과 전달에 관한 프로그래밍 패러다임입니다. 

이러한 Reactive Programming의 핵심은 모든 것을 비동기적인 데이터의 스트림으로 간주하고 다양한 방법을 통해서 비동기 이벤트를 처리하는 것입니다.

 

👩🏻‍💻 개발자

프로그래머가 특정 기능을 직접 정해서 실행되도록 처리하는 것이 아니라 시스템 이벤트가 발생했을 때 이를 알아서 처리할 수 있도록 하는 것을 말합니다.

  • 시스템 이벤트가 발생했을 때 이를 알아서 처리할 수 있다?
    • 즉, 메서드의 호출로 동작되는 것이 아니라 Observable 안에 데이터를 조회하고 변환하는 메커니즘을 작성하면 Observable이 이벤트를 발생시키면 Observer가 이를 감지하여 준비된 연산하여 결과를 반환합니다.
    • 그렇기 때문에 알아서 처리된다고 볼 수 있습니다.
  • 개발자들은 자신의 코드가 점진적으로 하나씩 작성된 순서에 따라서 실행/완료 되기를 기대하지만 ReativeX에서는 Observer에 의해 임의의 순서에 따라 병렬로 실행되고 나중에 결과가 반환되는 것을 확인할 수 있습니다.

 

👩🏻‍⚖️ 사용자

  • 사용자의 입장에서는 Reactive Programming을 기반으로 작성한 프로그램을 사용할 때 실시간성을 갖는다고 느낄 수 있습니다.
  • 프로그래머가 작성한 순서대로 동작되는 것이 아니라 사용자와 상호 작용하면서 그에 따라 화면/기능이 실시간으로 변하기 때문입니다.
    • 예를 들어서 인스타그램에 특정 게시물에 좋아요를 누르면 페이지를 새로 고침 하지 않아도 바로 좋아요 카운트가 올라가는 것을 볼 수 있습니다.
  • 이를 실현하기 위해서는
    • 프로그램이 지속적으로 특정 값을 관찰해야 합니다.
    • 값을 관찰하다가 변화가 나타나면 특정 연산이 이뤄져야 합니다.

 

🤔 콜백 함수로 비동기 처리를 할 수 있지 않나요?
물론 비동기 처리를 위해서 관찰이 아닌, 단순 콜백 함수를 사용할 수 있습니다. 
하지만, 연속된 비동기 작업이 필요할 경우 콜백 지옥이 나타나게 되는 등의 구조가 복잡해지기 때문에 관찰 방식을 사용하는 것이 더 효율적입니다.

또, 이미 Swift에는 비동기 API(Notification, Delegate, Grand Central Dispatch(GCD), Closures) 가 존재하지만 부분별로 나눠 사용하기 어려우며, 데이터를 다 받고 난 후에 UI Update를 진행합니다.
반면 RxSwift는 데이터 변경을 관찰하고 있기 때문에, 개발자가 작성한 순서대로 작동하는 것이 아니라 사용자와 상호 작용하며 UI를 실시간으로 업데이트해줍니다.

 

 

Observable

Observable

  • Rx에서는 모든 것이 데이터의 스트림이며 이를 Observable이라고 표현합니다.
    • 모든 것은 데이터의 스트림이다.
  • Rx는 이러한 Observable의 변화를 관찰하기 위해서 이를 구독(Subscribe)합니다.
    • RxSwift는 크게 Observable과 Subscribe와의 관계로 이루어진 코드 프레임워크라고 할 수 있습니다.
    • Observable이 이벤트를 방출하면 → 해당 Observable을 구독한 Subscriber가 Observable이 방출한 이벤트를 갖고 액션을 취하는 것이 Rx의 핵심 동작입니다.
    • 그리고 이를 반응형 프로그래밍이라고 합니다.
      • 반응형 프로그래밍?
      • : 어떠한 값의 상태 변화에 따라서 액션을 취하는 프로그래밍을 말합니다.
  • Observable은 특정 형태의 데이터의 스냅샷을 전달하는 일련의 이벤트들을 비동기적으로 생성합니다. 그리고 이를 Observer라는 것에 전달합니다.
  • Observer는 Observable을 Subscribe합니다.
    • 그러면 Observer는 Observable이 발행하는 아이템이나 일련의 시퀀스에 반응할 수 있게 됩니다.
    • 이러한 패턴은 동시적인 작동이 가능하게 합니다.
    • 왜냐하면 Observable이 아이템을 발행할 때까지 기다릴 필요 없이 특정 아이템이 발행되면 그 시점을 감시하는 관찰자를 Observer 내부에 두고 그 관찰자를 통해 발행 알림을 받으면 되기 때문입니다.

 

Marble Diagram

아래 보여지는 그림은 "마블 다이어그램"으로, Observable의 흐름과 전환을 그림으로 표현한 것입니다.

 

  • 위의 왼쪽에서 오른쪽으로 향하는 화살표는 Observable의 타임라인입니다.
    • 왼쪽에서 오른쪽으로 흐릅니다.
  • 위의 화살표에 위치하는 아이템들은 Observable에 의해 발행되는 아이템들입니다.
  • 아이템들과 함께 수직 직선으로 보이는 화살표는 Observable이 성공적으로 completed 이벤트를 발행했음을 의미합니다.
  • 위에서 아래로 향하는 점선 화살표와 박스는 Observable에서 행해지는 특정한 변환을 의미합니다. 박스 안쪽에 적힌 텍스트로부터 이것이 어떤 변환인지 알 수 있습니다.
    • 위의 이미지에서는 뒤집는 변환을 하는 것을 알 수 있습니다.
  • 아래의 왼쪽에서 오른쪽으로 향하는 화살표는 Observable의 변환 결과입니다.
  • 아이템들과 함께 엑스 표시로 보이는 화살표는 error를 의미합니다.

 

Observer 생성

Observer는 아래와 같은 메서드를 구현하고 사용합니다.

  • onNext
    • Observable이 아이템을 발행할 때마다 해당 메서드가 호출됩니다. 해당 메서드는 Observable이 발행하는 아이템을 파라미터로 전달받습니다.
  • onError
    • Observable에서 오류가 발생할 경우 호출됩니다.
    • 해당 메서드가 호출되면 onNext 나 onCompleted는 더 이상 호출되지 않고 라이프사이클이 종료됩니다. 해당 메서드는 error 객체를 파라미터로 전달받습니다.
  • onCompleted
    • 성공적으로 오류 발생 없이 주어진 시퀀스를 모두 발행했다면 호출됩니다.
let one = 1
let two = 2
let three = 3

let observable = Observable.of(one, two, three) // 1

observable.subscribe( // 2
	onNext: { (element) in // 3
		print(element)
	},
	onCompleted: { // 4
		print("끝!")
	}
)

/* 
1 
2 
3 
끝!
*/
  1. of 메서드를 통해 Observable 객체를 생성합니다. 해당 객체는 one, two, three의 데이터 시퀀스를 보유하고 이를 순서대로 발행합니다.
  2. subscribe를 통해 Observable에 대한 Observer를 만들 수 있습니다.
  3. onNext 메서드로 발행된 값을 이용한 동작을 처리합니다.
  4. onCompleted 메서드로 completed에서 수행할 동작을 처리합니다.
    1. 즉, 오류 발생 없이 주어진 시퀀스가 모두 동작될 경우의 수행 동작을 처리합니다.
    2. 위의 예시에서 1, 2, 3의 데이터 stream이 성공적으로 진행되었기에 “끝!”이 출력된 것을 확인할 수 있습니다.

 

🤔 구독을 해제한다?
Rx의 구현체에는 Subscriber라는 특별한 인터페이스가 존재합니다. 이 인터페이스 내의 unsubscribe라는 메서드를 제공하여 현재 subscribe중인 Observer에 대한 subscribe를 해지할 수 있습니다.

연산자 체인을 통해 Observer가 구독중인 Observable들이 더 이상 발행되지 못하도록 체인 내 연결 링크는 끊어버립니다.

 

Hot Observable VS Cold Observable

(코드예시랑 같이 볼 것)

Observable에 따라서 event를 방출하는 시점이 다릅니다.

Hot Observable🔥은 구독 여부에 관계 없이 요소를 방출해주는 Observable,
Cold Observable🧊은 구독이 되어야지 비로서 요소가 방출이 되는 Observable 입니다.

 

  • Hot Observable은 생성되자마자 데이터에 대한 발행을 시작합니다.
    • 따라서 데이터 발행 중간부터 Observable을 subscribe할 수도 있습니다.
    • Subject
  • 반면 Cold Observable은 Observer가 구독할 때까지는 데이터를 발행하지 않습니다.
    • 따라서 이를 subscribe한 Observer는 전체 데이터 시퀀스를 전달받습니다.

 

Observable의 다양한 Operators

  • Observable과 Observser는 표준 Observer Pattern을 확장한 개념입니다.
  • Rx가 유용한 진짜 이유는 다양한 Operators에 있습니다.
  • Operator는 Observable이 발생하는 연속된 아이템들을 변환, 결합, 조작하는 기능을 가졌습니다. 이 Operator 들은 선언적인 방법을 통해서 연속적인 비동기 호출을 구성할 수 있는 방법을 제공합니다.
    • 일반적인 비동기 시스템이 가진 중첩 콜백의 단점을 제거 했다는 것에 높은 평가를 받습니다.
    • 대부분의 Operator들이 Observable 상에서 동작하고 Observable을 반환합니다.
      • 그렇기 때문에 하나의 Observable에 대해 연속적으로 Operator를 적용하는 것을 가능하게 합니다.
      • 이들은 초기 Observable로부터 순차적으로 처리됩니다.

 

Creating Observables : 새로운 Observable을 만드는 Operator들 입니다.
  • Creator
  • Defer
  • Empty/Never/Throw
  • From
  • Interval
  • Just
  • Range
  • Repeat
    • repeatElement
  • Start
  • Timer

 

Transforming Observables : Observable이 emit한 아이템들을 변환하는 Operator들 입니다.
  • ToArray
  • Map
  • Buffer
  • Flatmap
  • FlatMapLatest
  • GroupBy
  • Scan
  • Window

 

Filtering Observables : 기존의 Observable에서 특정 조건에 맞는 아이템만 발행하는 Operator들입니다.
  • Debounce
  • DistinctUntilChanged
  • ElementAt
  • Filter
  • First
  • Last
  • IgnoreElements
  • Sample
  • Skip
  • SkipLast
  • Take
  • TakeLast

 

Combining Observables : 여러 개의 Observable들을 하나의 Observable로 만드는 Operator들입니다.
  • And/Then/When
  • CombindLatest
  • Join
  • Merge
  • StartWith
  • Switch
  • Zip

 

Error Handling Operators : Observable로부터 오는 오류를 확인하고 복구할 수 있도록 도와주는 Operator들입니다.
  • Catch
  • Retry

 

Utility Operators : Observable과 함께 동작하는 서포트 역할의 Operators들입니다.
  • Delay
  • Do
  • Materialize/Dematerialize
  • ObserveOn
  • Serialize
  • Subscribe
  • SubscribeOn
  • TimeInterval
  • Timeout
  • Timestamp
  • Using

 

Conditional and Boolean Operators : 하나 이상의 Observable 또는 Observable이 발행한 아이템을 평가하는 Operator들 입니다.
  • All
  • Amb
  • Contains
  • DefaultIfEmpty
  • SequenceEqual
  • SkipUntil
  • Skipwhile
  • TakeUntil
  • TakeWhile

 

Mathematical and Aggregrate Operators : Observable이 발행하는 항목 전체를 대상으로 동작하는 Operator들입니다.
  • Average
  • Concat
  • Count
  • Max
  • Min
  • Reduce
  • Sum

 

Converting Observables : Observable을 다른 객체나 자료 구조로 변환합니다.
  • To

 

Connectable Observable Operators : 좀 더 세세한 조작이 가능한 Observable들입니다.
  • Connect
  • Publish
  • Refcount
  • Replay

 

Chaining Operators

대부분의 연산자들은 Observable 상에서 동작하고 Observable을 반환합니다.

  • 그렇기 때문에 연산자들을 연달아 호출할 수 있는 연산자 체인을 제공합니다.
  • 연산자 체인에서 각각의 연산자는 이전 연산자가 반환한 Observable을 기반으로 동작하며 동작에 따라 Observable을 변경합니다.
  • 먼저 실행된 연산자가 반환한 Observable을 기반으로 다음 연산자가 동작하기 때문에 순서를 잘 고려해야 합니다.