SC #11: 작업 그룹

발행: (2026년 1월 20일 오전 07:27 GMT+9)
5 min read
원문: Dev.to

I’m happy to translate the article for you, but I don’t have the full text of the post. Could you please paste the content you’d like translated (excluding the source line you already provided)? I’ll keep the source link at the top, preserve all formatting, code blocks, URLs, and technical terms, and translate the rest into Korean.

TaskGroup

TaskGroup는 동적으로 생성된 하위 작업들을 포함하며, 순차적으로 또는 동시에 실행될 수 있습니다. 그룹은 모든 하위 작업이 완료될 때만 종료된 것으로 간주됩니다.

withTaskGroup(of:returning:isolation:body:)addTask(priority:operation:)를 사용하여 하위 작업을 추가할 수 있는 컨텍스트를 생성합니다.

기본 예제: 이미지 다운로드

func downloadPhoto(url: URL) async -> UIImage {
    // …
}

await withTaskGroup(of: UIImage.self) { taskGroup in
    let photoURLs = await listPhotoURLs(inGallery: "Vacaciones")
    for photoURL in photoURLs {
        taskGroup.addTask {
            await downloadPhoto(url: photoURL)
        }
    }
}

TaskGroup은 각 하위 작업을 동시에 실행하는 forEach와 같이 동작하며, 결과를 저장합니다.

결과 수집

컬렉션으로

반환 타입을 컬렉션으로 정의할 수 있습니다(예: [UIImage].self). 모든 서브태스크를 시작한 뒤, 그룹의 AsyncSequence를 사용해 결과를 기다리고 최종 컬렉션을 구성합니다.

let images: [UIImage] = await withTaskGroup(
    of: UIImage.self,
    returning: [UIImage].self
) { taskGroup in
    let photoURLs = await listPhotoURLs(inGallery: "Vacaciones")
    for photoURL in photoURLs {
        taskGroup.addTask {
            await downloadPhoto(url: photoURL)
        }
    }

    var images = [UIImage]()
    for await result in taskGroup {
        images.append(result)
    }
    return images
}

reduce 사용

TaskGroupAsyncSequence를 구현하므로 reduce 연산자를 사용할 수도 있습니다.

await withTaskGroup(of: UIImage.self, returning: [UIImage].self) { taskGroup in
    let photoURLs = try! await listPhotoURLs(inGallery: "Vacaciones")

    for photoURL in photoURLs {
        taskGroup.addTask {
            try! await downloadPhoto(url: photoURL)
        }
    }

    return await taskGroup.reduce(into: [UIImage]()) { partialResult, image in
        partialResult.append(image)
    }
}

ThrowingTaskGroup

어떤 하위 작업이 오류를 발생시킬 수 있을 때는 withThrowingTaskGroup(of:returning:isolation:body:)를 사용합니다.

try await withThrowingTaskGroup(of: UIImage.self, returning: [UIImage].self) { taskGroup in
    let photoURLs = try await listPhotoURLs(inGallery: "Vacaciones")

    for photoURL in photoURLs {
        taskGroup.addTask {
            try await downloadPhoto(url: photoURL)
        }
    }

    return try await taskGroup.reduce(into: [UIImage]()) { partialResult, image in
        partialResult.append(image)
    }
}

오류 발생 시 동작

  • ThrowingTaskGroup은 하위 작업이 예외를 발생시켜도 자동으로 실패하지 않습니다; 해당 하위 작업은 실패로 표시되지만 그룹은 계속 실행됩니다.
  • 오류를 전파하고 남은 작업을 취소하려면 group.next()를 사용해 각 하위 작업을 명시적으로 언패킹해야 합니다.
try await withThrowingTaskGroup(of: Void.self) { group in
    group.addTask { throw SomeError() }
    // 여기서는 그룹이 실패하지 않음
}
try await withThrowingTaskGroup(of: Void.self) { group in
    group.addTask { throw SomeError() }
    try await group.next()   // 오류를 전파하고 진행 중인 작업을 취소함
}

next()

group.next() 은(는) 서브태스크의 결과를 하나씩 무작위 순서로 제공하고, 서브태스크가 실패하면 해당 오류를 발생시킵니다. 이를 통해 각 오류를 개별적으로 처리할 수 있습니다.

while let result = try await taskGroup.next() {
    print("Got a new result:", result)
}

작업 취소

  • group.cancelAll()을 사용하여 전체 작업 집합을 취소할 수 있습니다.
  • addTask(priority:operation:)으로 이미 취소된 그룹에 작업을 추가하면, 작업은 생성된 직후 즉시 취소됩니다. 작업이 시작조차 하지 않도록 하려면 addTaskUnlessCancelled(priority:operation:)를 사용하십시오.
for photoURL in photoURLs {
    let didAddTask = taskGroup.addTaskUnlessCancelled {
        try await downloadPhoto(url: photoURL)
    }
    print("Added task: \(didAddTask)")
}
Back to Blog

관련 글

더 보기 »

SC #8: Task 취소

Swift와 SwiftUI에서 Task 취소 > 참고: Swift에서 Task를 취소한다고 해서 실행이 즉시 중단된다는 보장은 없습니다. 각 Task는 계속해서 …

SC #10: 분리된 작업

Detached Task는 구조화된 동시성 컨텍스트를 벗어나 비동기적으로 작업을 실행하는 분리된 작업입니다. 이를 둘러싼 구조화된 동시성 컨텍스트를 상속하지 않습니다. 이 c를 상속하지 않음...

SC #4: async/await 구문

async/await 함수 선언 비동기 함수는 async 키워드로 표시해야 합니다. 함수가 오류를 발생시킬 수 있는 경우, catch 키워드를 추가합니다.