해당글은 Swift Concurrency 1편부터 이어지는 내용입니다.
꼭 처음부터 보고 봐주시길 바랍니다.
저번시간에는 구조화가 되어 있음으로 즉,
부모 - 자식 관계나 범위가 계층 구조로 이루어져 있었습니다.
하지만 특정한 Task 에는 구조화가 없을 경우도 있죠.
import Foundation
// 비동기 작업을 수행하는 함수
func fetchData(url: URL) async throws -> Data {
let (data, _) = try await URLSession.shared.data(from: url)
return data
}
func performUnstructuredTask() {
// 명시적으로 Task를 생성합니다.
let task = Task {
do {
let url = URL(string: "https://KingJaeHyung.com/v1")!
let data = try await fetchData(url: url)
print("Data: \(data)")
} catch {
print("Error: \(error)")
}
}
// 5초뒤, 작업 캔슬
Task {
try await Task.sleep(for: .secondes(5))
task.cancel()
}
}
// 메인 실행
performUnstructuredTask()
하지만 해당 방법은 부모 작업이 끝나더라도 계속 실행될 수 있습니다. 좀 더 명확하게 접근해 보죠
import Foundation
// 비동기 작업을 수행하는 함수
func fetchData(url: URL) async throws -> Data {
let (data, _) = try await URLSession.shared.data(from: url)
return data
}
// 부모 작업
func parentTask() async {
print("Parent task started")
// Unstructured task 생성
let unstructuredTask = Task {
do {
let url = URL(string: "https://KingJaeHyung.com/v1")!
let data = try await fetchData(url: url)
print("Unstructured task data: \(data)")
} catch {
print("Unstructured task error: \(error)")
}
}
// Parent task를 잡시 대기 시킵니다.
try await Task.sleep(for: .secondes(15))
print("부모님이 일을 마치셨다!")
// 부모 task가 끝나더라도 unstructuredTask는 계속 실행됩니다.
// 해제하려면 강제로 unstructuredTask를 취소해야 합니다.
// unstructuredTask.cancel()
}
Task {
await parentTask()
}
즉 비구조화 작업은 위 코드와 같이
독립적
으로 생성됩니다.
즉(2) 부모 작업의 수명을 벗어나 독립적으로 관리해야 할 때 좋죠.
다만, 이는 즉 방대해질수록 관리하기가 어려워집니다.
명시적
으로 작업을 취소하여야 하기 때문이죠.
Unstructured Concurrency와 마찬가지로 Detached tasks는 가장 높은 유연성을 제공합니다.
즉 언제든 어디든 비동기 코드를 실행 할수 있으며, 부모 에게 어떠한 것도 상속 받지 않습니다.
Actor, prioirty 마저도 상속 받지 않죠.
즉 다시말해,컨텍스트
상속을 받지 않습니다.
import Foundation
// 비동기 작업을 수행하는 함수
func fetchData(url: URL) async throws -> Data {
let (data, _) = try await URLSession.shared.data(from: url)
return data
}
// 부모 작업
func parentTask() async {
print("Parent task started")
// detachedTask task 생성
let detachedTask = Task.detached { // 여기를 주목!
do {
let url = URL(string: "https://KingJaeHyung.com/v1")!
let data = try await fetchData(url: url)
print("detachedTask task data: \(data)")
} catch {
print("detachedTask task error: \(error)")
}
}
// Parent task를 잡시 대기 시킵니다.
try await Task.sleep(for: .secondes(15))
print("부모님이 일을 마치셨다!")
// 부모 task가 끝나더라도 detachedTask 계속 실행됩니다.
// 해제하려면 강제로 detachedTask 취소해야 합니다.
// detachedTask.cancel()
}
Task {
await parentTask()
}
여기서 중요한 점은
컨텍스트 상속
에 차이가 있습니다.
Unstructured Task
는 부모로 부터 상속을 받습니다. 즉Actor
와prioirty
를 상속은 받는다는 말이죠
하지만Detached tasks
는 부모로 부터 아무것도 받는 것이 없습니다.
Task.detached
를 사용하여 생성합니다.Task { --- }
를 사용하여 생성합니다.부모의 취소 상태
를 상속받지 않습니다.
부모의 컨텍스트를 상속받지 않습니다.
즉, 독립적
으로 실행됩니다. ( 글로벌 )헷갈리는 부분이 많아서. 차이점을 명확하게 짚고 가시면 좋을것 같습니다.
다음 시간에는SwiftConcurrency Data Race 1부
로 돌아 오겠습니다.
감사합니다.