iOS/Combine

[iOS/Combine] Combine의 Publisher(Just, Sequence, Future, Fail, Empty, Deferred)

최지철 2024. 9. 23. 12:55
728x90
반응형

Combine의 핵심 구성 요소는 Publisher Subscriber로, Publisher는 데이터를 발행하고 Subscriber는 이를 구독하여 처리합니다.

 

Publisher

Combine의 핵심 프로토콜로, 데이터 스트림을 생성하고 구독자에게 전달하는 역할

Publisher는 타입을 가집니다:

  • Output: 발행하는 데이터의 타입
  • Failure: 오류의 타입

Just

  • Just는 단일 값을 발행하고 완료하는 가장 간단한 Publisher입니다. 주로 고정된 값을 전달할 때 사용합니다.
import Combine

let justPublisher = Just("Hello, Just!")
let subscriber = justPublisher.sink(
    receiveCompletion: { completion in
        print("완료: \(completion)")
    },
    receiveValue: { value in
        print("값: \(value)")
    }
)
// 출력:
// 값: Hello, Just!
// 완료: finished
  • 간단하고 직관적
  • 테스트나 디버깅 시 유용
  • 고정된 데이터를 전달할 때 효율적

Sequence

  • Sequence Publisher는 Swift의 Sequence 타입을 Publisher로 변환합니다.
    배열, 범위 등 시퀀스 데이터를 발행할 때 사용됩니다.
import Combine

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

let subscriber = sequencePublisher.sink(
    receiveCompletion: { completion in
        print("완료: \(completion)")
    },
    receiveValue: { value in
        print("값: \(value)")
    }
)
// 출력:
// 값: 1
// 값: 2
// 값: 3
// 값: 4
// 값: 5
// 완료: finished
  • 시퀀스 데이터를 쉽게 발행
  • 다양한 시퀀스 타입과 호환 가능
  • 데이터 스트림을 자연스럽게 처리

Future

  • Future는 비동기 작업의 결과를 한 번만 발행하는 Publisher입니다.
    주로 네트워크 요청이나 비동기 계산 결과를 전달할 때 사용됩니다.
import Combine

func fetchData() -> Future<String, Error> {
    return Future { promise in
        DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
            promise(.success("데이터 로드 완료"))
        }
    }
}

let futurePublisher = fetchData()
let subscriber = futurePublisher.sink(
    receiveCompletion: { completion in
        print("완료: \(completion)")
    },
    receiveValue: { value in
        print("값: \(value)")
    }
)
// 2초 후 출력:
// 값: 데이터 로드 완료
// 완료: finished
  • 비동기 작업의 결과를 쉽게 전달
  • 오류 처리 가능
  • 단일 값 발행에 적합

Fail

  • Fail은 즉시 오류를 발행하고 완료하는 Publisher입니다.
    오류를 테스트하거나 오류 시나리오를 시뮬레이션할 때 유용합니다.
import Combine

enum MyError: Error {
    case somethingWentWrong
}

let failPublisher = Fail<String, MyError>(error: .somethingWentWrong)
let subscriber = failPublisher.sink(
    receiveCompletion: { completion in
        print("완료: \(completion)")
    },
    receiveValue: { value in
        print("값: \(value)")
    }
)
// 출력:
// 완료: failure(MyError.somethingWentWrong)

 

Empty

  • Empty는 아무 값도 발행하지 않고 즉시 완료하는 Publisher입니다.
    특정 상황에서 아무 작업도 하지 않도록 할 때 사용됩니다.
import Combine

let emptyPublisher = Empty<String, Never>()
let subscriber = emptyPublisher.sink(
    receiveCompletion: { completion in
        print("완료: \(completion)")
    },
    receiveValue: { value in
        print("값: \(value)")
    }
)
// 출력:
// 완료: finished
  • 아무 데이터도 필요하지 않은 상황에서 유용
  • 다른 Publisher와 결합할 때 기본 값으로 사용 가능

Deferred

  • Deferred는 실제로 구독할 때 Publisher를 생성하는 Publisher입니다.
    Publisher 생성 시점을 지연시키고 싶을 때 유용합니다.
import Combine

func createDeferredPublisher() -> AnyPublisher<String, Never> {
    return Deferred {
        Future { promise in
            promise(.success("Deferred 값"))
        }
    }
    .eraseToAnyPublisher()
}

let deferredPublisher = createDeferredPublisher()
let subscriber = deferredPublisher.sink(
    receiveCompletion: { completion in
        print("완료: \(completion)")
    },
    receiveValue: { value in
        print("값: \(value)")
    }
)
// 출력:
// 값: Deferred 값
// 완료: finished
  • Publisher 생성 시점 제어
  • 지연 초기화
  • 동적인 Publisher 생성 가능
728x90
반응형