본문 바로가기
한눈가계부/데이터 모델

💡 iOS 개발 필수 개념: Future와 AnyPublisher 완벽 정리

by 밤새는 탐험가89 2025. 8. 24.
728x90
SMALL

안녕하세요! iOS 개발자라면 한 번쯤 들어봤을 Combine 프레임워크. 특히 비동기 작업을 다룰 때 자주 사용되는 Future와 AnyPublisher는 그 관계가 조금 헷갈릴 수 있습니다. 이 둘의 차이점과 왜 함께 사용되는지, 핵심만 쏙쏙 뽑아 정리해 드릴게요.


1. Publisher: 데이터의 흐름을 만드는 존재

 Combine에서 가장 중요한 개념은 바로 Publisher입니다. Publisher는 시간의 흐름에 따라 하나 이상의 값을 발행(emit)하는 역할을 합니다. 구독자(Subscriber)는 이 Publisher를 구독하여 값이 발행될 때마다 이를 받아서 처리합니다. Future와 AnyPublisher 모두 이 Publisher 프로토콜을 따릅니다.


2. Future: '단 한 번'의 결과를 약속하는 발행자

 Future는 한 번만 결과를 발행하고 종료되는 특별한 종류의 Publisher입니다. 주로 네트워크 요청, 데이터베이스 저장/삭제와 같이 단일 결과를 반환하는 비동기 작업에 사용됩니다.

Future는 초기화 블록에 promise라는 클로저를 받습니다. 이 promise는 비동기 작업이 완료되었을 때 success 또는 failure를 호출하여 단 한 번의 결과를 전달합니다.

func fetchData() -> Future<Data, Error> {
    return Future { promise in
        // 비동기 작업 시작...
        DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
            // 작업 성공 시
            promise(.success(someData))
            // 실패 시
            // promise(.failure(someError))
        }
    }
}

 

위의 예시처럼 Future는 특정 시점에 단일 데이터를 제공하는 데 최적화되어 있습니다.


3. AnyPublisher: '어떤 발행자라도 될 수 있는' 만능 타입

 AnyPublisher는 특정 Publisher의 실제 타입을 숨기는 '타입 지우기(Type Erasure)' 기능을 가진 제네릭 구조체입니다. 다양한 종류의 Publisher를 모두 AnyPublisher라는 하나의 타입으로 통일시킬 수 있게 해줍니다.

만약 여러 함수가 각기 다른 Publisher를 반환한다면 코드가 복잡해질 수 있습니다. 이때 AnyPublisher를 반환 타입으로 사용하면 코드를 더 깔끔하고 유연하게 만들 수 있습니다.

// 함수 1: Future를 반환
func fetchUserData() -> Future<User, Error> { /* ... */ }

// 함수 2: URLSession.dataTaskPublisher를 반환
func downloadFile() -> URLSession.DataTaskPublisher { /* ... */ }

// 이들을 AnyPublisher로 통일
func getSomeData() -> AnyPublisher<Data, Error> {
    // 내부적으로 Future를 사용하든
    return Future { ... }.eraseToAnyPublisher()
    // 다른 Publisher를 사용하든
    // return URLSession.shared.dataTaskPublisher(for: url)...
}

4. Future와 AnyPublisher는 왜 함께 사용될까?

 이제 퍼즐이 맞춰집니다. Future는 '단일 결과를 약속하는 비동기 작업'을 구현할 때 사용하고, AnyPublisher는 이 작업의 결과를 외부에 더 추상적이고 유연한 타입으로 노출할 때 사용합니다.

// Core Data 삭제 메서드 예시
func deleteTransaction(id: UUID) -> AnyPublisher<Bool, Error> {
    // return Future { ... }.eraseToAnyPublisher()
}

 

위 코드의 의미는 다음과 같습니다.

"이 deleteTransaction 함수는 내부적으로 Future를 사용해 Core Data 삭제라는 단일 비동기 작업을 수행할 거야. 그리고 그 결과를 AnyPublisher라는 일반적인 타입으로 외부에 전달해서, 함수를 사용하는 쪽에서는 내부 구현을 몰라도 되게 만들었어."

 이처럼 Future로 특정 작업을 구현하고 .eraseToAnyPublisher()를 통해 AnyPublisher로 반환하는 것은 Combine에서 흔히 볼 수 있는 관용적인 패턴입니다.

728x90
LIST