[swift] Combine

2024. 4. 9. 16:06·swift

Combine

Combine은 비동기 및 이벤트 기반 코드를 처리하기 위한 프레임워크로, Publisher-Subscriber 패턴을 기반으로 한다.

 

Publisher 프로토콜은 시간이 지남에 따라 일련의 값을 전달할 수 있는 유형을 선언한다. 퍼블리셔에는 업스트림 퍼블리셔로부터 받은 값에 대해 작업하고 다시 퍼블리시하는 오퍼레이터가 있다.

 

퍼블리셔 체인의 끝에서 Subscriber는 요소를 수신할 때 해당 요소에 대해 작업을 수행한다. 퍼블리셔는 구독자가 명시적으로 요청하는 겨웅에만 값을 내보낸다.

 

Publisher

protocol Publisher {
	associatedtype Output
    associatedtype Failure: Error
    
    func subscriber<S: Subscriber>(_ subscriber: S)
    	where S.Input == Output, S.Failure == Failure
}

 

퍼블리셔는 데이터를 생성하고 내보내는 역할을 한다. 이 데이터는 비동기적으로 생성될 수 있으며, 특정 시간 간격마다 발생할 수도 있다. Publisher는 내보내는 데이터의 유형과 함께 실패할 수 있는 오류 타입도 정의한다.

 

Built-in Publisher (내장 퍼블리셔)

  • Just : 단일 값을 내보내는 가장 간단한 퍼블리셔이다. 주로 테스트 용도로 사용된다.
  • Future : 나중에 값을 제공하는 퍼블리셔이다. 주로 비동기 작업의 결과를 Combine 스트림으로 포장할 때 사용된다.
  • 추가로 iOS에서 기본적으로 제공되는 퍼블리셔 타입도 존재한다.
    • NotificationCenter
    • Timer
    • URLSession.dataTask

Subcriber

protocol Subscriber {
	associatedtype Input
    associatedtype Failure: Error
    
    func receive(subscription: Subscription)
    func receive(_ input: Input) -> Subscribers.Demand
    func receive(completion: Subscribers.Completion<Failure>)
}

 

구독자는 퍼블리셔에게 데이터를 요청하고, 이를 통해 데이터 스트림을 관리한다. 이때, 구독자는 퍼블리셔에게 요청할 데이터의 타입과 실패할 경우의 타입을 정의해야 한다.

 

구독을 한 후에는 구독자가 요청한 개수만큼 데이터를 받을 수 있다. 이렇게 함으로써 퍼블리셔는 구독자의 요청에 따라 적절한 양의 데이터를 생성하고 전달할 수 있다.

 

또한, 구독자는 파이프라인을 취소할 수 있다. 이는 퍼블리셔와의 연결을 해제하고 데이터 스트림을 종료하는 것을 의미한다. 이렇게 함으로써 불필요한 리소스 사용을 방지하고 메모리 누수를 방지할 수 있다.

 

Built-in Subscriber (내장 서브스크라이버)

  • assign : 특정 객체의 키 경로에 퍼블리셔가 제공한 데이터를 할당한다. 이를 통해 퍼블리셔로부터 전달된 값을 객체의 속성에 바인딩할 수 있다.
  • sink : 퍼블리셔가 제공한 데이터를 클로저를 통해 받을 수 있다. 이 클로저를 사용하면 퍼블리셔로부터 전달된 값에 대한 처리 및 로직을 수행할 수 있다.

 

Subscriber & Publisher Pattern

 

 

Subscription (구독)

Subscription은 Combine 프레임워크에서 Pusblisher와 Subscriber 사이의 연결을 나타낸다. 이 연결은 데이터 스트림을 통해 데이터를 수신하고 처리하는 데 사용된다. Subscription은 두 요소 간의 통신을 관리하며, 메모리 관리와 리소스 해제를 담당한다.

 

Subject (Pusblisher)

Subject는 Combine 프레임워크에서 Publisher와 Subscriber 역할을 모두 수행할 수 있는 특별한 유형의 Publisher이다. 즉, Subject는 데이터를 생성하고, Subscriber에게 전달할 수 있으며, 동시에 Subscriber로서 다른 Publisher를 구독할 수도 있다.

 

Built-in Subject

  • PassthroughSubject : PassthroughSubject는 현재의 상태와 무관하게 외부에서 데이터를 제공할 떄 사용된다. PassthroughSubject는 구독한 Subscriber에게 현재부터 발생하는 이벤트를 전달한다.
  • CurrentValueSubject : CurrentValueSubject는 초기값을 가지고 시작하며, 이후에 새로운 값을 내보낼 때마다 해당 값을 구독자에게 전달한다. 따라서 CurrentValueSubject는 현재 값을 유지하고 있는 상태를 유지하며, 이를 통해 최신 데이터를 제공할 수 있다.

@Published

@Published 속성은 ObservableObject 프로토콜을 따르는 클래스 내에 선언되며, 해당 속성의 값이 변경될 때마다 관련된 Publisher를 자동으로 발행한다. $를 이용해서 퍼블리셔에 접근할 수 있다.

class Weather {
	@Published var temperature: Double
    init(temperature: Double) {
    	self.temperature = temperature
	}
}

let weather = Weather(temperature: 20)
let subscription = weather.$temperatur.sink {
	print("Temperature now: \($0)")
}
weather.temperature = 25

// Temperature now: 20.0
// Temperature now: 25.0

 

Operator (연산자)

  • 변환 연산자 : 데이터를 변환하거나 가공하는 데 사용된다.
    • map
    • flatMap
    • scan
  • 필터링 연산자 : 데이터 스트림에서 특정 조건을 만족하는 데이터만을 선택하는 데 사용된다.
    • filter
    • compactMap
  • 결합 연산자 : 여러 데이터 스트림을 결합하여 하나의 데이터 스트림으로 합치는 데 사용된다.
    • merge
    • combineLatest
    • zip
  • 시간 연산자 : 시간과 관련된 작업을 수행하는 데 사용된다.
    • debounce
    • throttle
    • delay

 

Scheduler (스케줄러)

Combine에서는 작업을 수행할 스레드나 큐를 관리하기 위해 스케줄러를 사용한다. 스케줄러는 Combine에서 비동기 작업을 제어하는 데 사용되며, 작업을 특정 스레드에서 실행하거나 작업을 지연시키는 등의 작업을 수행할 수 있다.

  • subscriber(on:)을 이용해서, publisher가 어느 스레드에서 수행할 지 결정할 수 있다.
    • 무거운 작업은 메인스레드가 아닌 다른 스레드에서 작업할 수 있게 도와준다.
  • receive(on:)을 이용해서 operator, subscriber가 어느 스레드에서 수행할 지 결정할 수 있다.
    • UI 업데이트에 필요한 데이터를 메인스레드에서 받을 수 있게 도와준다.

일반적인 패턴

let jsonPublisher = MyJSONLoaderPublisher() // Some publisher.

jsonPublisher
    .subscribe(on: backgroundQueue)
    .receive(on: RunLoop.main)
    .sink { value in
		label.text = value
}

 

UI 업데이트 시

// 이렇게 쓰기보단
pub.sink {
    DispatchQueue.main.async {
        // Do update ui
    }
}

// 이렇게 쓸 것
pub.receive(on: DispatchQueue.main).sink {
        // Do update ui
}

 

 

'swift' 카테고리의 다른 글
  • [swift] ARC
  • [swift] URLSession
  • [swift] File Manager
  • [swift] UNUserNotificationCenter
GwanSon
GwanSon
버그는 도전, 코드는 해결. 열정있는 개발을 하자.
  • GwanSon
    관슨의 개발일지
    GwanSon
  • 전체
    오늘
    어제
    • 분류 전체보기 (56)
      • iOS (3)
      • swift (15)
      • UIKit (0)
      • swiftUI (2)
      • 알고리즘 (8)
      • CS (8)
      • 면접 (11)
      • Flutter (4)
      • 회고 (2)
      • 잡담 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    백준
    2025 토스 Next
    후기
    ios
    챌린지
    네이버 부스트캠프 후기
    부스트캠프 10기
    모듈화
    부스트캠프
    네이버 부스트캠프
    토스
    boj
    tuist
    Swift
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
GwanSon
[swift] Combine
상단으로

티스토리툴바