[swift] Swift PromiseKit과 디자인 패턴

Swift는 비동기 작업을 처리하기 위해 다양한 방법을 제공하는데, 그 중에 하나인 PromiseKit은 매우 인기 있는 오픈 소스 라이브러리입니다. PromiseKit을 사용하면 비동기 작업을 보다 간편하게 처리할 수 있으며, 코드를 보다 쉽게 관리할 수 있는 디자인 패턴을 구현할 수 있습니다.

PromiseKit은 PromiseResolver라는 두 가지 클래스를 중심으로 구성됩니다. Promise는 비동기 작업의 결과를 반환하기 위한 객체이고, Resolver는 비동기 작업의 성공 또는 실패를 처리하기 위한 객체입니다.

PromiseKit 기초 사용법

PromiseKit을 사용하기 위해서는 먼저 해당 라이브러리를 프로젝트에 추가해야 합니다. 이후에는 다음과 같은 단계를 따라서 PromiseKit을 사용할 수 있습니다.

  1. Promise 생성하기: Promise 객체를 생성하여 비동기 작업을 시작합니다.
  2. 작업 수행하기: 비동기 작업을 수행하는 블록을 Promise 객체에 전달합니다.
  3. 작업 결과 반환하기: 비동기 작업이 완료되면 작업의 결과를 Promise 객체에 반환합니다.
  4. 결과 처리하기: then 메서드를 사용하여 작업의 결과를 처리합니다. then 메서드는 성공 또는 실패를 처리하는 클로저를 인자로 받습니다.

아래는 PromiseKit을 사용하여 비동기 작업을 처리하는 간단한 예제입니다.

import PromiseKit

func fetchData() -> Promise<Data> {
    return Promise { seal in
        // 비동기 작업을 수행하는 코드
        URLSession.shared.dataTask(with: URL(string: "https://example.com")!) { data, _, error in
            if let error = error {
                seal.reject(error)
            } else if let data = data {
                seal.fulfill(data)
            }
        }.resume()
    }
}

fetchData()
    .done { data in
        // 비동기 작업이 성공한 경우 처리하는 코드
        // data를 처리하는 로직
    }
    .catch { error in
        // 비동기 작업이 실패한 경우 처리하는 코드
        // error를 처리하는 로직
    }

위 예제에서는 fetchData 함수가 Promise<Data> 객체를 반환하고 있습니다. 이후 done 메서드와 catch 메서드를 사용하여 작업의 결과를 처리하고 있습니다. done 메서드는 작업이 성공한 경우를 처리하기 위한 클로저를 인자로 받고, catch 메서드는 작업이 실패한 경우를 처리하기 위한 클로저를 인자로 받습니다.

PromiseKit과 디자인 패턴

PromiseKit은 비동기 작업을 처리하는 것뿐만 아니라 코드를 더욱 깔끔하고 관리하기 쉬운 디자인 패턴을 구현하는 데에도 사용할 수 있습니다. 대표적인 예로는 체이닝(Chaining)과 병렬 처리(Parallel Processing)가 있습니다.

체이닝

PromiseKit을 사용하면 비동기 작업을 연속적으로 처리할 수 있으며, 각 작업의 결과를 다음 작업으로 전달할 수 있습니다. 이를 체이닝이라고 부릅니다. 체이닝을 사용하면 비동기 작업을 보다 간결하게 표현할 수 있고, 작업 순서를 조절하기도 쉽습니다.

아래는 체이닝을 사용하여 비동기 작업을 처리하는 예제입니다.

fetchData()
    .then { data -> Promise<[String]> in
        // data를 가공하여 [String] 배열을 반환하는 비동기 작업 수행
    }
    .then { strings -> Promise<Void> in
        // strings를 가공하여 다른 작업을 수행하는 비동기 작업 수행
    }
    .done {
        // 최종적으로 작업 결과를 처리하는 코드
    }
    .catch { error in
        // 작업 실패 처리 코드
    }

위 예제에서는 fetchData 함수를 통해 비동기 작업을 시작하고, 이후 then 메서드로 작업의 결과를 전달하고 있습니다. 체이닝을 사용하면 연속된 비동기 작업을 순서대로 실행할 수 있으며, 작업이 실패한 경우에도 catch 메서드를 통해 적절한 처리를 할 수 있습니다.

병렬 처리

PromiseKit을 사용하면 비동기 작업을 병렬로 처리할 수 있습니다. 병렬 처리는 여러 개의 비동기 작업을 동시에 실행하고, 모든 작업이 완료되었을 때 결과를 처리할 수 있는 기능입니다. 병렬 처리를 사용하면 상호 의존하지 않는 작업을 동시에 실행하여 전반적인 성능을 향상시킬 수 있습니다.

아래는 병렬 처리를 사용하여 비동기 작업을 처리하는 예제입니다.

let fetchImage = fetchImageData() // 이미지 데이터를 가져오는 비동기 작업
let fetchUserInfo = fetchUserProfile() // 사용자 정보를 가져오는 비동기 작업

when(fulfilled: fetchImage, fetchUserInfo)
    .done { image, userInfo in
        // 이미지 데이터와 사용자 정보를 처리하는 코드
    }
    .catch { error in
        // 작업 실패 처리 코드
    }

위 예제에서는 when(fulfilled: ...) 메서드를 사용하여 두 개의 비동기 작업을 병렬로 실행하고 있습니다. 모든 작업이 완료되면 done 메서드로 결과를 처리할 수 있으며, 작업이 실패한 경우에는 catch 메서드를 통해 적절한 처리를 할 수 있습니다.

결론

Swift PromiseKit은 비동기 작업을 보다 쉽고 간편하게 처리하며, 코드의 가독성을 높일 수 있는 디자인 패턴을 제공합니다. 체이닝과 병렬 처리를 통해 비동기 작업을 효율적으로 처리할 수 있으며, 이를 통해 앱의 성능을 향상시킬 수 있습니다. 따라서 Swift 개발자라면 PromiseKit을 활용하여 비동기 작업을 처리하는 데에 적극적으로 활용해보는 것을 권장합니다.

참고 자료