틈틈히 적어보는 개발 일기

1. Hello, Combine! 본문

📱 iOS, Swift/📚 Combine

1. Hello, Combine!

itllbegone 2023. 4. 2. 12:41

애플이 말하는 컴바인이란?

“The Combine framework provides a declarative approach for how your app processes events. Rather than potentially implementing multiple delegate callbacks or completion handler closures, you can create a single processing chain for a given event source. Each part of the chain is a Combine operator that performs a distinct action on the elements received from the previous step.” - Apple

"컴바인 프레임워크는 앱이 이벤트를 처리하는 방법에 대한 선언적 접근 방식을 제공합니다. 여러 delegate callback이나 completion handler closure를 잠재적으로 구현하는 대신 지정된 이벤트 소스에 대해 단일 처리 체인을 만들 수 있습니다. 체인의 각 부분은 이전 단계에서 받은 요소에 대해 개별적인 작업을 수행하는 Combine 연산자입니다.”

 

Asynchronous programming

단일 스레드 언어에서는 위에서 아래로 순차적으로 코드가 실행된다

begin
  var name = "Tom"
  print(name) // "Tom"
  name += " Harding"
  print(name) // "Tom Harding"
end

Synchronous한 코드는 이해하기 쉽고, 특정 부분의 데이터가 어떠한 상태 혹은 값을 가지고 있는지에 대해서도 알기 쉽다.

그럼 Async는?

--- Thread 1 ---
begin
  var name = "Tom"
  print(name) // "Tom"

--- Thread 2 ---
name = "Billy Bob"

--- Thread 1 ---
  name += " Harding"
  print(name) // "??"
end

마지막 print(name) 에서 어떠한 값이 나올지 알 수 없다

코드가 언제 어떻게 불릴지는 OS가 관여하므로 매 실행마다 다른 결과를 초래할 수 있다

Foundation and UIKit/AppKit

애플은 지속적으로 iOS에 asynchronous programming을 위한 장치들을 만들고 발전시켜왔다

iOS에서 직접적으로 스레드를 지정, 관리 할 수 없지만 유사한 기능을 가진 low-level API가 있긴 하다 NSThread와 Swift’s modern concurrency인 async/await 이다

이외에 앱 개발 하면서 써봤을만한 것들은 다음과 같다

  • NotificationCenter 특정 이벤트를 observe 하고 있다가 해당 이벤트 발생 시 코드를 실행 ex) keyboard show 등등
  • Delegate Pattern 특정 동작에 대한 행위의 정의를 위임함. 정의된 코드는 언제 어떻게 얼마나 수행될지는 모름 ex) UITableViewDelegate
  • GCD(Grand Central Dispatch), Operations 작업의 수행 방식 (Serial, Concurrent)등을 도와줌. 작업들의 스케쥴링을 도와주는 것들이라고 보면 될듯?
  • [Operations & Operation Queue](https://www.notion.so/Operations-Operation-Queue-60ccd9dd3f4b49f6933a747f344b0460)
  • Closures

Swift’s Modern Concurrency

Swift5.5에서 소개댐 (async/await)

기존에 발생하던 비동기 관련 문제를 Modern Concurrenct API를 활용하면 쉽게 해결할 수 있음

Combine으로 다양한 Operator를 활용해서 네트워킹, 데이터처리, UI이벤트 처리 등 반응형 문제들을 쉽게 해결할 수 있음


Foundation of Combine

Rx에 영감을 받았긴 한데, 차이점을 가지고 있음! 근데 사실상 같은 핵심 개념을 가진거에 동의함

iOS 13부터 지원하기 시작함


Combine basics

Publishers

값을 방출할 수 있는 타입, 다음 3가지 이벤트를 발생시킬 수 있다
1. Output: Publisher가 방출하는 결과
2. successful completion
3. Failure: 에러로 인한 Publisher의 completion

RxSwift의 Observable에 대응하는 타입 Observable과는 다르게 <Output, Failure(Error Handling)>를 방출한다. protocol Publisher<Output, Failure>

→ 그럼 오류 처리를 하고싶지 않거나, 없는 경우에는 어떻게 하냐?

→ Never를 통해서 해당 Publisher가 별다른 에러 핸들링을 하지 않을 것이라는 것을 명시

Subject

Subject 프로토콜로 구현된 Subject들을 말하며
Subject 프로토콜은 Publisher<Output, Failure> 프로토콜 또한 채택하고 있다
Subject는 send() 를 통해서 값을 주입할 수 있으며 이를 통해 이벤트를 방출한다
  • PassTroughtSubject
    RxSwift의 PublishSubject에 대응하며 초깃값 or 버퍼가 없음
  • CurrentValueSubject
    RxSwift의 BehaviorSubject에 대응하며 초깃값 and 퍼버가 존재함

Subscriber

RxSwift의 Observer(Subscribe)에 대응하는 타입
Output, completion 이벤트에 대해 작업을 수행한다

.subscribe와 동일한 .sync, KVO 방식의 .assign 으로 구독하여 이벤트를 받아볼 수 있다


Cancellation(Cancellable)

RxSwift의 Disposable에 대응하는 타입, 사용은 AnyCancellable
DisposeBag은 Combine에서 Set<AnyCancellable>로 Set 타입으로 묶어서 사용한다

Operator

Publisher의 형태를 동일하거나 변환할 수 있는 메소드
operator 체이닝으로 여러 operator를 결합 가능하다

combine에는 withLatestFrom과 같은 일부 operator들이 없음

대신 try+operator 같은 것을이 있음

map은 스트림에서 뱉는 데이터타입을 준수하고 있는 반면

tryMap은 swift5.5의 result타입을 반환함

[Operator] tryMap

try - catch 문을 map과 같이 묶어 녹여낸 operator
Swift5.5의 result타입을 반환한다

만약 JSON Data를 주고받는다고 가정해보자 (네트워킹을 통한 데이터의 송수신도 포함)

이 때 원래라면 다음과 같은 과정으로 try - catch 를 이용하거나 try? 를 이용해서 디코딩 하는 과정을 거칠것이다

// func decode<T>(T.type, from: Data) -> T
do {
    try JSONDecoder().decode(Model.self, from: data)
} catch {
    // Error Handling
    print(error)
}

이를 컴바인 에서는 다음과 같이 간략하게 처리할 수 있도록 슈가코드를 지원한다

이 때 try문이 실패할 경우 Result에서 Faliure로 떨어져 반환하게 된다

.tryMap { data in
    try JSONDEcoder().decode(Model.self, from: data)
}

이를 더욱 간단하게 표현하는 operator은 다음과 같다

// func decode<Item, Coder>(type: Item.type, decoder: Coder) -> Publishers.Decode<Self, Item, Coder>
.decode(Model.self, JSONDecoder())

'📱 iOS, Swift > 📚 Combine' 카테고리의 다른 글

4. Filtering Operators  (0) 2023.05.01
3. Transforming Operators  (0) 2023.04.23
2. Publishers & Subscribers  (0) 2023.04.09
Comments