iOS에서 Combine 프레임워크를 사용한 반응형 프로그래밍: 데이터 바인딩과 스트림 관리 기술.
iOS에서 Combine 프레임워크를 사용한 반응형 프로그래밍: 데이터 바인딩과 스트림 관리 기술
Combine 프레임워크는 iOS 13에서 처음 도입된 반응형 프로그래밍 도구로서, 데이터 바인딩과 스트림 관리를 쉽게 처리할 수 있게 해줍니다. 이 글에서는 Combine의 기본 개념부터 실전에서 효과적으로 사용하는 방법까지 다룹니다.
Combine 프레임워크의 기본 개념
Combine 프레임워크는 Publisher
와 Subscriber
라는 두 가지 주요 개념을 중심으로 돌아갑니다. Publisher
는 데이터를 스트림으로 전달하는 역할을 하며, Subscriber
는 이러한 데이터를 소비하는 역할을 합니다.
Publisher와 Subscriber
Publisher
는 데이터의 발생을 의미하며, 여러 요소를 통해 생성할 수 있습니다. 가장 기본적인 예로 Just
와 Future
가 있으며, 각각 단일 값과 비동기 작업을 나타냅니다.
Just
예제:
swiftimport Combine let justPublisher = Just(5)
Future
예제:
swiftimport Combine let futurePublisher = Future<Int, Never> { promise in DispatchQueue.global().asyncAfter(deadline: .now() + 1) { promise(.success(42)) } }
Subscriber
는 Publisher
가 발행하는 데이터를 받기 위해 subscribe
메서드를 호출합니다. 구독자는 데이터를 수신하고, 이를 처리하거나 표시할 수 있습니다.
swiftlet subscriber = Subscribers.Sink<Int, Never>( receiveCompletion: { completion in print(completion) }, receiveValue: { value in print("Received value: \(value)") } ) justPublisher.subscribe(subscriber)
데이터 바인딩과 데이터 변환
Combine의 강력한 기능 중 하나는 데이터 변환과 바인딩입니다. map
, filter
, scan
같은 연산자를 사용하여 데이터 스트림을 변환할 수 있습니다.
map 연산자
map
연산자는 입력 값을 변환하여 새로운 값을 반환합니다. 예를 들어, 숫자 스트림을 문자열로 변환할 수 있습니다.
swiftlet numberPublisher = Just(4) let stringPublisher = numberPublisher.map { number in return "Number is: \(number)" } stringPublisher.sink { value in print(value) }
filter 연산자
filter
연산자는 조건에 맞는 값만 통과시키는 역할을 합니다. 예를 들어, 짝수만 통과시키는 필터를 만들 수 있습니다.
swiftlet numbers = [1, 2, 3, 4, 5].publisher let evenNumbers = numbers.filter { $0 % 2 == 0 } evenNumbers.sink { value in print(value) }
Subject와 연결 상태 관리
Combine에서 Subject
는 Publisher
와 Subscriber
의 역할을 동시에 수행합니다. 가장 자주 사용되는 Subject
는 PassthroughSubject
와 CurrentValueSubject
입니다.
PassthroughSubject
이 Subject
는 구독 후 발생한 이벤트만 전달합니다.
swiftlet passthrough = PassthroughSubject<String, Never>() passthrough.sink { value in print("Received: \(value)") } passthrough.send("Hello")
CurrentValueSubject
이 Subject
는 현재 값을 저장하며, 구독 시 즉시 전송합니다.
swiftlet currentValue = CurrentValueSubject<Int, Never>(0) currentValue.sink { value in print("Current value: \(value)") } currentValue.send(10)
연결 상태 관리
스트림 구독자는 정상적인 완료나 에러로 끝날 수 있으며, 이를 sink
의 인자로 전달받은 클로저를 통해 처리할 수 있습니다.
swiftlet simplePublisher = [1, 2, 3].publisher let subscriber = simplePublisher.sink( receiveCompletion: { completion in switch completion { case .finished: print("Finished") case .failure(let error): print("Error: \(error)") } }, receiveValue: { value in print(value) } )
Combine 프레임워크의 실제 사용 예제
실제로 Combine 프레임워크는 네트워크 요청, 사용자 인터페이스 업데이트 등 다양한 상황에서 활용될 수 있습니다. 간단한 네트워크 요청 예제를 살펴보겠습니다.
swiftimport Foundation import Combine struct Post: Decodable { let id: Int let title: String } let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1")! let networkPublisher = URLSession.shared.dataTaskPublisher(for: url) .map { $0.data } .decode(type: Post.self, decoder: JSONDecoder()) .eraseToAnyPublisher() networkPublisher.sink( receiveCompletion: { completion in print(completion) }, receiveValue: { post in print(post) } )
이 예제에서는 URLSession의 dataTaskPublisher
를 사용하여 네트워크 요청을 수행하고, 결과를 decode
연산자로 변환한 후, sink
를 통해 데이터를 구독합니다.
이처럼 Combine 프레임워크는 iOS 개발에서 데이터 스트림을 관리하고, 반응형 프로그래밍을 쉽게 구현하는 데에 강력한 도구가 될 수 있습니다. 이를 통해 더 깨끗하고 유지 보수하기 쉬운 코드를 작성할 수 있습니다.