BIBI BLOG

[swift] Concurrency withCheckedThrowingContinuation 알아보기 본문

iOS/Swift

[swift] Concurrency withCheckedThrowingContinuation 알아보기

BIBI⭐️ 2025. 4. 1. 13:14
728x90

withCheckedThrowingContinuation는 Swift 5.5+에서 제공하는 Swift Concurrency API 중 하나로,
“콜백(callback) 기반 비동기 함수”를 async/await로 변환하기 위한 도우미입니다.
쉽게 말해, “completion handler” 스타일 코드를 async throws 함수로 래핑해 주는 역할이죠.


1. 사용하는 이유

Swift의 await 문법은 비동기를 직관적으로 처리할 수 있게 만듭니다.
하지만 기존에는 많은 함수들이 콜백(completion block)을 사용해 결과를 반환합니다.
이런 콜백 함수를 async 함수로 바꾸려면, “코드가 완료되는 시점”에 await 체계를 알려줘야 하는데,
그 과정을 withCheckedThrowingContinuation가 자동으로 도와줍니다.


2. 함수 형태

func withCheckedThrowingContinuation<T>(
    function: String = #function,
    _ body: (CheckedContinuation<T, Error>) -> Void
) async throws -> T
  • T: 반환하려는 타입
  • Error: 실패 시 throw할 에러 타입
  • body 파라미터에서, **CheckedContinuation<T, Error>**를 사용해 resume(returning:) 또는 **resume(throwing:)**를 호출

3. 예시

// 콜백 기반 함수
func loadData(completion: @escaping (Result<String, Error>) -> Void) {
    // 네트워크나 비동기 작업
    DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
        completion(.success("Loaded Data"))
    }
}

// async/await 버전으로 감싸기
func loadDataAsync() async throws -> String {
    try await withCheckedThrowingContinuation { continuation in
        loadData { result in
            switch result {
            case .success(let data):
                continuation.resume(returning: data)
            case .failure(let error):
                continuation.resume(throwing: error)
            }
        }
    }
}
  • loadData는 기존 콜백: 1초 뒤에 성공/실패를 호출
  • loadDataAsync에서 withCheckedThrowingContinuation로 감싸서
    Result를 받으면 resume(returning:), 에러면 resume(throwing:)을 호출
  • 호출 측:
let data = try await loadDataAsync()
print(data)

4. 작동 원리

  • withCheckedThrowingContinuation는 내부적으로 Swift 런타임에 “이 함수는 단 한 번 resume할 수 있다.” 등을 알려,
    동시성 안전을 돕습니다.
  • “checked”라는 말처럼, “resume이 여러 번 불리면 에러”를 일으키는 등, 개발자가 실수로 중복 resume을 방지해줍니다.

5. 주의 사항

  1. resume은 딱 한 번만
    • 여러 번 호출하거나, 호출 안 하면 런타임 에러를 일으킬 수 있음
  2. throwing vs non-throwing
    • withCheckedThrowingContinuation를 쓰면, 실패 시 “throw”가 가능
    • 에러가 필요 없으면 withCheckedContinuation (non-throwing)을 써도 됨
  3. 배경 지식:
    • Swift Concurrency는 “Task가 완료되는 시점”을 알아야 “await”이 끝나도록 설계됨.
    • continuation이 resume되어야만 async 함수가 “완료”됨

6. 요약

  • withCheckedThrowingContinuation: 콜백 함수를 비동기/던질 수 있는(async throws) 함수로 바꾸는 Swift Concurrency 유틸리티
  • 장점:
    • 콜백 기반 API를 깔끔하게 “await” 형식으로 이용 가능
    • 중첩 completion을 줄이고, 에러 관리를 쉽게
  • 사용 방법:
    • try await withCheckedThrowingContinuation { continuation in ... }
    • 기존 completion에서 성공continuation.resume(returning:), 실패resume(throwing:)
  • 주의: 한 번만 resume해야 하며, 중복 resume 시 런타임 에러
728x90
Comments