SC #10: 분리된 작업

발행: (2026년 1월 20일 오전 06:18 GMT+9)
4 min read
원문: Dev.to

Source: Dev.to

분리된 작업(Detached Task)은 구조화된 동시성 컨텍스트 밖에서 비동기적으로 작업을 실행합니다. 이 컨텍스트를 상속받지 않으면 다음을 상속받지 않게 됩니다:

  • 컨텍스트의 우선순위
  • 컨텍스트의 취소 상태.

작업을 생성하려면 정적 메서드 Task.detached(name:priority:operation:)를 사용합니다:

Task.detached {
    // Ejecuta una operación de forma asíncrona fuera del contexto estructurado de concurrencia
}

기본 예시

func detachedTaskExample() async {
    func asyncFunc(_ string: String) async {
        print(string)
    }
    await asyncFunc("\(1)")
    Task.detached {
        await asyncFunc("\(2)")
    }
    await asyncFunc("\(3)")
}

위 코드는 다음과 같은 결과를 출력할 수 있지만, 순서는 보장되지 않습니다:

1
3
2

분리된 작업의 취소 위험

다음 예시를 고려해 보세요. 여기서 longRunningAsyncOperation은 취소되기 전에 끝나지 않는 비동기 작업이며, detachedTaskExample은 이를 서브태스크로 호출한 뒤 분리된 형태로 호출하기 위해 Task.detached를 생성합니다:

func detachedTaskExample() async {
    let outerTask = Task {
        // Esta subtarea sí se va a cancelar
        await longRunningAsyncOperation(1)

        // Esta tarea desacoplada NO hereda el estado de cancelación
        Task.detached(priority: .background) {
            // Por eso este checkCancellation no hace nada
            try Task.checkCancellation()

            // Por eso esta subtarea no se va a cancelar
            await longRunningAsyncOperation(2)
        }
    }
    outerTask.cancel()
}

private func longRunningAsyncOperation(_ id: Int) async {
    do {
        print("Empezando tarea \(id)")
        try await Task.sleep(for: .seconds(5))
        print("Terminé la tarea")
    } catch {
        print("\(#function) - Tarea \(id) falló con error: \(error)")
    }
}

이 예시의 출력은 다음과 같습니다:

Empezando tarea 1
longRunningAsyncOperation(_:) - Tarea 1 falló con error: CancellationError()
Empezando tarea 2
Terminé la tarea

이 예시에서:

  • 첫 번째 longRunningAsyncOperation 호출은 취소된 Task의 구조화된 컨텍스트 안에서 실행되므로 정상적으로 취소됩니다.
  • 두 번째 호출에서는 try Task.checkCancellation()을 실행해도 취소를 감지할 방법이 없으며, 취소 상태를 상속받지 않기 때문입니다.

분리된 Task를 취소하려면 해당 작업에 대한 참조를 유지하고 수동으로 취소해야 합니다. 이러한 작업은 참조가 해제될 때 자동으로 취소되지 않으므로 명시적으로 관리해야 합니다.

언제 분리된 작업을 사용해야 할까?

다음과 같은 상황에서 분리된 작업을 만드는 것이 적절합니다:

  • 작업을 독립적으로 실행할 수 있을 때.
  • 컨테이너 컨텍스트와 연결될 필요가 없을 때.
  • 컨테이너가 취소되더라도 작업이 계속 실행되어도 괜찮을 때.

유효한 예시 (self에 대한 참조가 없음):

Task.detached(priority: .background) {
    await DirectoryCleaner.cleanup()
}
Back to Blog

관련 글

더 보기 »

SC #11: 작업 그룹

TaskGroup은 동적으로 생성된 subtasks를 포함하며, 이 subtasks는 serial 또는 concurrent 방식으로 실행될 수 있습니다. 그룹은 완료된 것으로 간주됩니다…

SC #8: Task 취소

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

SC #3: Swift 6와의 관계

Swift Concurrency 3 Part Series https://dev.to/david_goyes_a488f58a17a53/series/35092 'Swift Concurrency'는 Swift 6의 기초였지만, Swift 6은 …