본문 바로가기
iOS/Combine

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

by 최지철 2024. 9. 23.
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
반응형