SwiftUI 비동기 데이터 처리: Combine 프레임워크 사용

작성일 :

SwiftUI 비동기 데이터 처리: Combine 프레임워크 사용

SwiftUI는 Apple에서 제공하는 선언적 사용자 인터페이스 프레임워크로, 사용자 인터페이스를 더 작성하기 쉽게 만들어줍니다. 그러나 많은 경우, 특히 네트워크 요청이나 데이터베이스 접근 같은 비동기 작업이 필요할 때 조금 더 복잡해질 수 있습니다. 이를 간단하게 만들기 위해, SwiftUI는 Combine 프레임워크와 함께 사용됩니다. Combine은 비동기 이벤트 처리를 위한 강력한 도구 모음을 제공합니다.

Combine 프레임워크 소개

Combine은 Apple이 iOS 13 및 macOS Catalina에서 처음 도입한 프레임워크로, 비동기 이벤트 처리를 기반으로 작동합니다. Combine은 기본적으로 퍼블리셔(Publisher)와 서브스크라이버(Subscriber) 패턴을 사용합니다. 퍼블리셔는 데이터를 방출하고, 서브스크라이버가 그 데이터를 받아서 처리합니다. 이를 통해 비동기 데이터 흐름을 효과적으로 관리할 수 있습니다.

퍼블리셔와 서브스크라이버

퍼블리셔는 데이터 스트림을 방출하는 역할을 합니다. 예를 들어, Just, FuturePassthroughSubject 같은 기본 퍼블리셔 클래스들이 있습니다. 서브스크라이버는 퍼블리셔가 방출하는 데이터를 구독하고 처리합니다. 퍼블리셔와 서브스크라이버를 연결하면 하나의 데이터 파이프라인이 만들어집니다.

다음 예시는 Just 퍼블리셔를 사용하여 데이터를 방출하고, 이를 구독하는 기본 구성입니다.

swift
import Combine

let publisher = Just(42)

let subscriber = publisher.sink { value in
    print("Received value: \(value)")
}

SwiftUI와 Combine 연계

SwiftUI와 Combine은 깊이 통합되어 있어, 이를 통해 비동기 데이터를 쉽게 관리할 수 있습니다. @State@Published 프로퍼티 래퍼를 사용하여 상태 변화를 관리하고, Combine의 Publisher와 연결하여 비동기로 데이터를 처리할 수 있습니다.

네트워크 요청 예제

실제 예제로서 간단한 네트워크 요청을 만들어 보겠습니다. 네트워크 요청의 결과를 @Published 프로퍼티에 저장하고, 이 데이터를 SwiftUI 뷰에서 출력합니다.

먼저 네트워크 요청을 수행하는 NetworkManager 클래스를 정의합니다.

swift
import Foundation
import Combine

class NetworkManager: ObservableObject {
    @Published var data: Data? = nil
    private var cancellable: AnyCancellable?

    func fetchData(from url: URL) {
        cancellable = URLSession.shared.dataTaskPublisher(for: url)
            .map { $0.data }
            .replaceError(with: nil)
            .receive(on: DispatchQueue.main)
            .sink { [weak self] data in
                self?.data = data
            }
    }
}

이제 SwiftUI 뷰에서 NetworkManager를 사용하여 데이터를 출력합니다.

swift
import SwiftUI

struct ContentView: View {
    @ObservedObject var networkManager = NetworkManager()

    var body: some View {
        VStack {
            if let data = networkManager.data,
               let string = String(data: data, encoding: .utf8) {
                Text(string)
            } else {
                Text("Loading...")
            }
        }
        .onAppear {
            let url = URL(string: "https://api.example.com/data")!
            networkManager.fetchData(from: url)
        }
    }
}

고도화된 데이터 흐름 관리

위 예제처럼 기본적인 네트워크 요청을 처리하기 시작하면, 보다 복잡한 데이터 흐름 또한 쉽게 관리할 수 있습니다. Combine은 연산자를 통해 데이터 스트림을 변환, 필터링, 결합할 수 있는 다양한 방법을 제공합니다.

예를 들어, map, filter, merge, combineLatest 등의 연산자는 고도화된 데이터 흐름 관리를 쉽게 만들어줍니다.

데이터 변환 및 필터링

다음은 간단한 데이터를 변환하고 필터링하는 예제입니다.

swift
import Combine

let numbers = [1, 2, 3, 4, 5]
let publisher = numbers.publisher

publisher
    .map { $0 * 2 }
    .filter { $0 > 5 }
    .sink { value in
        print("Received value: \(value)")
    }

결론

SwiftUI와 Combine을 결합하면 고도로 직관적이고 효율적인 비동기 데이터 흐름 처리가 가능합니다. Combine의 퍼블리셔-서브스크라이버 모델을 사용하여 네트워크 요청이나 데이터베이스 접근 같은 비동기 작업을 간단하게 처리할 수 있으며, SwiftUI의 선언적 프로그래밍 모델과 자연스럽게 통합됩니다. 이를 통해 개발자는 복잡한 비동기 데이터를 쉽게 관리하고, 보다 유연한 사용자 인터페이스를 만들 수 있습니다.