
안녕하세요!
저번에 Task에 대한 글에서, detached는 따로 자세히 다뤄보자고 했었죠?
이번 글에서는 detached에 대해 깊이 파헤쳐 보려고 합니다!
얼마 전에 앨런 Swift Concurrency for Swift 6 (Part-1) 강의를 듣다가, 이런 설명을 들었어요.
" 내부Task에서 부모Task와 다른 우선순위를 적용하려면 detached를 사용해야 한다."

"어? 그럼 내부 Task에서는 우선순위를 따로 설정하는건 적용이 안 되는 건가????" 하는 의문이 들었습니다.
그래서 직접 실험해보았는데요! 아래처럼 내부 Task에도 우선순위를 설정하고 실행해보았어요.
let task = Task(priority: .high) {
print("부모 Task: \(Task.currentPriority)")
Task(priority: .background) {
print("자식 Task: \(Task.currentPriority)")
}
}
결과
부모 Task: TaskPriority.high
자식 Task: TaskPriority.background
그렇다면 정말로 다른 우선순위를 적용할 때 detached를 무조건 써야 하는 걸까?
detached는 어디에서 사용되는걸까?
그리고 강의에서도 강조했듯이, 공식 문서에서도 가능하면 detached를 사용하지 말라고 권장하는 이유는 뭘까?
그럼 detached 사용하지 않고, 우선 순위를 별개로 부여하는 방법이 있을까?
이 모든 의문을 해결하기 위해 공식 문서를 뒤적이며 공부해봤습니다.
이제, Task.detached의 동작 방식과 주의할 점을 하나씩 살펴봅시다!

Task.detached 란?

Runs the given throwing operation asynchronously as part of a new top-level task.
새로운 최상위 Task로 주어진 throw 가능한 연산을 비동기적으로 실행한다
Task.detached를 사용하면 기존 Task와 완전히 독립적인 실행 흐름을 만든다는 뜻이에요.
즉, 부모 Task의 영향을 받지 않고, 우선순위, 실행 컨텍스트, 취소 상태 등을 상속받지 않는 독립적인 Task가 생성됩니다.
Available when Success conforms to Sendable and Failure is any Error.
Success가 Sendable을 준수하며, Failure가 Error 프로토콜을 따를 때 사용 할 수 있다.
Task가 성공하면 결과 값(Success)을 반환하는데, 이 값은 여러 Task 간 안전하게 공유될 수 있어야 해요.
그래서 Sendable을 준수해야 합니다.
또한,Task가 실패하면, 반드시 실패 원인은 Error 타입으로 표현해야 합니다.
즉, Task가 throw를 던지면, 이를 Error 타입으로 다뤄야 합니다! (오류를 일관되게 처리)
💡Sendable이 뭐에요?
Sendable은 Swift의 동시성(Concurrency) 모델에서 사용되는 프로토콜로, "이 타입은 여러 Task나 스레드에서 안전하게 공유할 수 있어!"라는 걸 컴파일러에게 알려주는 역할을 해요.
즉, Task나 Task.detached 같은 비동기 환경에서 안전하게 데이터를 주고받으려면, 그 데이터가 Sendable을 준수해야겠죠?
정리해보면, detached는 부모Task의 영향을 받지 않는 독립적인 Task를 만들고 오류를 던질 수 있는 연산을 비동기적으로 실행할 수 있다는 뜻으로 정리할 수 있겠습니다 :)
Parameters

priority (우선순위, 기본값: nil)
- 실행할 Task의 우선순위를 지정 (예: .high, .background 등)
- 기본값을 사용하면 우선순위를 명시적으로 설정하지 않음
operation (실행할 비동기 연산)
- 실행할 비동기 코드 블록
- throw 가능하면 try를 사용해야 함
- Sendable을 준수해야 하므로 클로저 내부에서 캡처하는 값이 안전한지 주의해야 함
여기는 Task에서도 다룬 부분이라 짧게 보고 넘어가겠습니다ㅎㅎ
여기서, 서론보면 "공식 문서에서도 가능하면 detached를 사용하지 말라고 권장하는 이유는 뭘까?" 라는 질문을 던졌던거 기억하시나요?
이제 Discussion 부분을 보면 그 이유를 확실히 이해할 수 있을 겁니다!
Discussion
한 문장씩 뜯어보면서 제대로 이해해 봅시당..!

오류 처리 방법
If the operation throws an error, this method propagates that error.
만약 작업(operation)이 오류를 발생시키면, 이 메서드는 해당 오류를 전파(propagate)합니다.
즉, Task.detached {} 내부에서 오류가 발생하면, 그 오류가 호출된 곳으로 전달됩니다.
하지만 Task.detached()는 부모 Task가 없기 때문에, 오류를 직접 잡아서 처리해야 합니다.
오류를 처리하는 방법은 여러 가지가 있으며, 각 방법마다 장단점이 있기 때문에, 상황에 따라 적절한 방식을 선택해야 합니다.
그럼 각각의 방법을 알아볼까요? 👀
1. do-catch (권장)
do-catch는 오류를 잡아서 로깅하거나, 적절한 대응을 해야 하는 경우에 사용됩니다.
Task.detached {
do {
try someThrowingFunction()
} catch {
print("Detached Task에서 발생한 오류: \(error)")
}
}
이 방법은 코드가 다소 길어질 수 있지만,
오류를 명확하게 처리할 수 있고, catch 블록을 활용하여 다양한 오류 유형에 대한 대응이 가능합니다.
2. try? (옵셔널 반환)
try?는 오류가 발생해도 실행 흐름을 그대로 유지해야 하는 경우에 사용됩니다.
예를 들어, 네트워크 요청이 실패하더라도 기본값을 사용해야 하는 경우 유용합니다.
Task.detached {
let result = try? someThrowingFunction()
print("결과 값: \(result ?? "실패")")
}
이 방법은 오류가 발생해도 nil을 반환하여 코드가 중단되지 않고 계속 실행됩니다.
따라서, 오류를 무시하고 진행해야 하는 상황에서 간단하게 사용할 수 있습니다.
하지만, 오류가 발생해도 원인을 알 수 없고, nil 여부를 추가로 체크해야 하는 번거로움이 있습니다.
3. try! (강제 실행, 오류 발생 시 크래시)
오류가 절대 발생하지 않는다고 확실할 때 사용할 수 있습니다.
Task.detached {
let result = try! someThrowingFunction()
print("결과 값: \(result)")
}
이 방법은 코드가 간결하고, throws를 사용하지 않는 일반 함수처럼 사용할 수 있는 장점이 있습니다.
하지만, 오류가 발생하면 앱이 즉시 크래시가 나기 때문에, 일반적인 상황에서는 사용을 권장하지 않습니다.
Task.detached() 사용을 피해야 하는 이유와 대안
Don’t use a detached task if it’s possible to model the operation using structured concurrency features like child tasks.
작업을 자식 작업(child tasks)과 같은 구조적 동시성(Structured Concurrency) 기능을 사용하여 모델링할 수 있는 경우, detached()를 사용하지 마세요.
일단 이 부분 보니까 detached 사용하지 않고 "구조적 동시성" 기능을 사용하면 개별 우선순위를 부여할 수 있는 듯하죠?
구조적 동시성(StructuredConcurrency)기능을 활용하면 Task가 부모-자식 관계를 유지하면서 더 안전하게 관리될 수 있으며, 오류 전파나 취소 처리가 더 효과적입니다.
따라서 가능하면 Task.detached() 사용하지 않고, Task {} 내부에서 실행하는 방식인 구조적 동시성 기능으로 해결하는 것이 더 좋습니다.
구조적 동시성에대해서는 아래에서 간단히 다뤄보겠습니다ㅎㅎ
설정과 관리 – 우선순위, Task-local Storage, 취소 처리
Child tasks inherit the parent task’s priority and task-local storage, and canceling a parent task automatically cancels all of its child tasks.
자식 작업(child tasks)은 부모 Task의 우선순위(priority)와 Task-local storage를 상속받습니다.
또한, 부모 Task를 취소하면 자동으로 모든 자식 작업도 취소됩니다.
You need to handle these considerations manually with a detached task.
Detached Task를 사용할 경우,
이러한 사항들(우선순위, Task-local storage, 취소 관리)을 직접 처리해야 합니다.
Detached Task는 부모 Task의 메타데이터(우선순위, Task-local storage, 실행 액터, 로컬 변수)를 상속받지 않기 때문에, 필요한 경우 직접 설정해야 합니다.
Task.detached(priority: .high) {
print("높은 우선순위에서 실행되는 Detached Task")
}
이처럼 Detached Task의 데이터를 명시적으로 설정해야 합니다.
💡 Task-local storage란?
Swift의 동시성 모델에서 각 작업(Task) 내에서만 접근 가능한 데이터를 저장하는 메커니즘입니다. 이는 작업 간의 데이터 공유를 방지하고, 각 작업이 독립적으로 동작할 수 있도록 지원합니다. 이러한 기능은 주로 로깅, 추적, 인증 정보 저장 등과 같은 상황에서 유용하게 사용됩니다.
취소 – 참조 유지의 중요성
You need to keep a reference to the detached task if you want to cancel it by calling the Task.cancel() method.
Task.cancel() 메서드를 호출하여 Detached Task를 취소하려면, 반드시 해당 Task의 참조(reference)를 유지해야 합니다.
Discarding your reference to a detached task doesn’t implicitly cancel that task, it only makes it impossible for you to explicitly cancel the task.
Detached Task의 참조(reference)를 버린다고 해서 자동으로 취소되지는 않으며, 단지 명시적으로 취소할 방법이 없어질 뿐입니다.
Detached Task는 detachedTask.cancel()을 호출하여 직접 취소하지 않으면 계속(영원히) 실행됩니다!
// ❌ Task를 변수에 저장하지 않으면, 실행 중단할 방법이 없음
Task.detached {
print("이 Task는 취소할 방법이 없습니다...")
}
따라서, 아래와 같이 반드시 let task = Task.detached {} (직접 참조)형태로 저장하고, 필요할 때 취소할 수 있도록 해야 합니다. (직접 참조를 유지하지 않으면 수동으로 취소할 방법이 없음)
let detachedTask = Task.detached {
while !Task.isCancelled {
print("Detached Task 실행 중...")
try? await Task.sleep(for: .seconds(1))
}
print("Detached Task 취소됨")
}
// 3초 후에 Detached Task를 수동으로 취소
Task {
try? await Task.sleep(for: .seconds(3))
detachedTask.cancel() // 반드시 명시적으로 취소해야 함
}
이처럼 Detached Task는 직접 설정하고 관리해야 하기 때문에, 신경 써야 할 부분이 많아 사용할 때 주의가 필요합니다.
휴..! 드디어 detached 문서 내용은 다 살펴 보았는데요! 어떻게 사용해야 하고, 어떤 점을 주의해야 하는지 한층 명확해지셨나요?!

그런데, 최상위(부모 Task가 없는)Task랑 Detached Task랑 다른점이 정확히 뭘까요??
Task랑 Detached Task의 다른점이 부모 Task의 설정을 상속하지 않는다는건데.. 부모 Task가 없는 Task는 부모 Task에 설정을 상속받지 않는 최상위 Task잖아요!! 같이 알아봅시다!!!
최상위(부모 Task가 없는)Task랑 Detached Task랑 다른점
부모 Task가 없는 일반 Task(Task{})
실행될 때 현재 시스템(OS)의 실행 환경을 기반으로 적절한 우선순위를 자동으로 설정합니다.
현재 실행 중인 액터(Actor Context), Task-local storage 등을 상속받을 수 있습니다.
즉, 부모 Task가 없더라도 실행 환경을 자동으로 따라가면서 실행됩니다. (OS가 자동으로 환경에 맞게 설정해줌)
Task {
print("부모 Task가 없는 일반 Task 실행 중!")
// ✅ OS가 적절한 실행 환경을 자동으로 설정
}
Detached Task(Task.detached {})
현재 실행 환경(액터(Actor Context), Task-local storage)을 상속받지 않기때문에 직접 설정해줘야 합니다.
우선순위는 명시하지 않으면 .background 우선순위로 실행될 가능성이 높습니다
즉, Detached Task는 실행될 때 주변 환경을 따르지 않고, 완전히 새로운 공간에서 실행됩니다.
Task.detached {
print("Detached Task 실행 중!")
// ❌ 실행 컨텍스트를 따르지 않음 (기본적으로 .background에서 실행될 가능성이 큼)
}
Task.detached(priority: .high) {
print("Detached Task 실행 중!") // 직접 높은 우선순위를 설정
}
.background로 실행될 "가능성이 큼"이라고 되어있는데, 아닐때도 있는거겠죠?
일반 Task 내부에서 실행되거나, 시스템(OS)이 개입하면 다른 우선순위가 적용될 수도 있다고 합니다!
상황 | Detached Task의 기본 우선순위 |
명시적으로 설정한 경우 | 설정한 우선순위 그대로 실행 |
명시하지 않은 경우 (기본값) | .background로 실행될 가능성이 큼 |
일반 Task 내부에서 실행된 경우 | OS나 실행 환경에 따라 달라질 수 있음 |
OS가 동적으로 우선순위를 조정하는 경우 | 상황에 따라 .userInitiated 같은 다른 우선순위로 실행될 수도 있음 |
즉, Detached Task는 실행 컨텍스트를 상속받지 않지만, OS가 개입하면 실행 우선순위가 달라질 수도 있습니다.
그러므로 Detached Task를 사용할 때는 실행 환경을 직접 설정하는 것이 가장 안전합니다!
정리
구분 | 부모가 없는 일반 Task (Task {}) | Detached Task (Task.detached {}) |
부모 Task | 없음 (최상위 Task) | 없음 (완전 독립적인 Task) |
우선순위 (Priority) | 명시하지 않으면, 생성된 컨텍스트의 기본 우선순위 사용 | 명시하지 않으면, 낮은 우선순위(.background)로 설정될 가능성 있음 |
Task-local storage | 있음 (현재 실행 중인 Actor의 Task-local storage 사용 가능) | 없음 (Task-local storage를 상속받지 않음, 직접 설정해야 함) |
실행 액터(Actor Context) | 현재 실행 중인 Actor에서 실행됨 | 기본적으로 전역 실행 컨텍스트(Global Execution Context)에서 실행됨 |
취소 (Cancellation) | 다른 Task에서 참조하고 있다면 cancel() 호출 가능 | 직접 참조를 유지하지 않으면 취소할 방법이 없음 |
구조적 동시성 (Structured Concurrency) | 포함됨 (다른 Task와 구조적으로 연관 가능) | 포함되지 않음 (완전히 독립적) |
오키오키~~
현재 실행환경에 영향을 받느냐 아니냐가 중요한 부분같네요!!
자, 다시 본론으로 돌아와서.. 서론에서 적은 코드 처럼 냅다 자식 Task에 priority를 때려넣는 방법... 과연 사용해도 될까?
결론부터 말하자면, 이렇게 사용해도 동작은 하지만 구조적 동시성(Structured Concurrency)의 원칙에 어긋나기때문에 권장되지 않습니다! 그렇다면 아까 다룬다고 했던 구조적 동시성에대해 알아봐야겠죠????
구조적 동시성(Structured Concurrency)란?
작업(Task)과 그 하위 작업 간의 부모-자식 관계를 명확히 정의하여 코드의 가독성, 유지보수성, 안정성을 향상시키는 동시성 관리 방식
Swift의 동시성 모델에서는 부모 Task가 자식 Task를 포함하고 관리해야 합니다. 이를 통해:
✅ 우선순위 상속 → 자식 Task는 부모 Task의 우선순위를 유지
✅ 취소 전파 → 부모 Task가 취소되면 모든 자식 Task도 자동 취소
✅ Task-local storage 공유 → 부모-자식 Task 간 안전한 데이터 공유 가능
즉, 작업 간 명확한 계층 구조를 유지함으로써, 우선순위 역전(Priority Inversion) 같은 문제를 방지할 수 있습니다.
구조적 동시성에 관련된 자세한 내용은 다음 Task 그룹 (TaskGroup, ThrowingTaskGroup)관련 글에서 자세히 다루고, 이번글에서는 이정도로만 알고 넘어가겠습니다!
자.. 서론에 적었던 코드를 이제 살펴봅시다
let task = Task(priority: .high) {
print("부모 Task: \(Task.currentPriority)")
Task(priority: .background) {
print("자식 Task: \(Task.currentPriority)")
}
}
처음에 위 코드가 구조적 동시성 원칙에 어긋난다고했죠?
그 의미는 부모 Task의 우선순위를 자식 Task가 상속 받아야 하는데, 그렇지 않기 때문이었습니다. (부모-자식 관계가 구조적으로 보장되지 않음)
자식Task에서 부모Task와 다른 우선순위를 적용하려면 detached를 사용해야 한다.
즉, 의문의 시작인 이 설명의 뜻은 부모Task의 실행 환경을 상속받지 않도록 하려면 Detached Task를 사용해야한다는 의미였습니다.
그러니까, detached를 사용하지 않은 상태에서 부모와 자식Task의 우선순위가 다르면 자식Task는 부모Task와 완전히 독립적으로 분리되어있지 않기때문에 부모Task의 실행 컨텍스트를 일부 유지할 가능성이 있습니다.
그걸 우선순위 역전(Priority Inversion)이라고 하는데요.
위에 적은 코드는 await을 사용하지 않았기 때문에, 자식Task가 즉시 실행될 가능성이 높아서 우선순위 역전(Priority Inversion)이 잘 생기지는 않습니다.
하지만 await 비동기 코드를 작성하게 되면 이야기가 달라집니다..
부모 Task가 .background이고, 자식 Task는 .high 우선순위를 가지는 비동기 코드를 작성한다고 가정해봅시다.
(부모Task 우선순위 < 자식Task 우선순위)
Task(priority: .background) {
print("부모Task - ", \(Task.currentPriority))
await Task(priority: .high) {
print("자식Task - ", \(Task.currentPriority))
}.value
}
결과 (자식Task 우선순위 변동 .high -> .background)
부모Task - TaskPriority.background
자식Task - TaskPriority.background ❗️
이렇게 부모 Task가 .background이면, 자식 Task도 자동으로 .background로 실행될 가능성이 커집니다.
즉, 내부 Task의 우선순위를 변경해도 적용되지 않을 가능성이 높기때문에 내부 Task에서 priority를 변경하는 것은 비효율적일 수 있습니다.
다른 코드도 살펴 보죠!!
이번에는 부모Task의 우선순위는 .high이고 자식Task는 .low로 가정해봅시다. (부모Task 우선순위 > 자식Task 우선순위)
Task(priority: .high) {
print("부모Task - ", Task.currentPriority)
await Task(priority: .low) {
print("자식Task - ", Task.currentPriority)
}.value
}
결과
부모Task - TaskPriority.high
자식Task - TaskPriority.high
자식 Task가 부모 Task의 우선 순위로 변경되었네요?!
Swift가 역전을 방지하기 위해 Task 우선 순위를 올려주었기때문입니다!
잠깐 그러면, 자식Task가 우선순위가 더 높을때도 낮을때도 다 부모Task를 따라서 가는걸까요???
이번에는 부모Task를 .low로 자식Task를 .high로 설정해보겠습니다.
Task(priority: .low) {
print("부모 Task", Task.currentPriority.rawValue)
await Task(priority: .high) {
print("자식 Task", Task.currentPriority.rawValue)
}.value
}
부모Task 우선순위 > 자식Task 우선순위이니까 자식Task가 .low로 변할까요??????
결과
부모 Task TaskPriority.low
자식 Task TaskPriority.high
부모 Task가 .low이더라도, 자식 Task의 우선순위(.high)는 유지됩니다.
즉, .backgroun 우선순위때랑은 다르게 낮은 우선순위 Task가 높은 우선순위 Task를 기다릴 때는 우선순위 승격이 일어나지 않는거죠!
이로 인해, 부모 Task가 높은 우선순위 Task를 기다려야 하는 문제가 발생할 수 있습니다.
그럼, 자식 Task의 우선순위를 별도로 부여하고 싶다면 어떻게 해야 할까요?
withTaskGroup(priority:)을 사용하여 개별 우선순위 부여
Task {
await withTaskGroup(of: Void.self) { group in
group.addTask(priority: .high) {
print("우선순위 높은 작업 실행!")
}
group.addTask(priority: .low) {
print("우선순위 낮은 작업 실행!")
}
}
}
이렇게 사용하면 구조적 동시성을 유지하면서 개별 우선순위 부여 할 수 있습니다.
부모 Task의 취소가 자동으로 자식 Task에도 전파되며 Task-local storage 및 실행 컨텍스트도 유지됩니다.
TaskGroup과 withTaskGroup까지 다루면 글이 너무 길어질 것 같아서 다음 글에서 좀 더 자세히 다뤄보도록하겠습니다!
궁금하신 분들은 동시성 읽어보시거나 링크 걸어둘테니 들어가서 살펴보세요!
그럼! 대체 언제! detached를 사용해야하는거야?!

공식 문서에서 가능하면 Task.detached()를 사용하지 말라고 권장하고 있는데..
그럼 대체 어디서 사용하는걸까..?
아래와같이 몇몇 특정한 경우에는 Task.detached()를 반드시 사용해야 할 때가 있다고합니다! 함께 알아보시죠!!
백그라운드에서도 계속 실행되어야 하는 작업
백그라운드에서 실행되면서도 현재 Task의 실행 컨텍스트와 독립적인 작업을 실행할 때 Task.detached()가 필요합니다.
예를들어 백그라운드에서 사용자의 위치를 주기적으로 서버에 전송해야하거나, 파일 업로드를 해야할때는 부모 Task가 취소되더라도 네트워크 요청은 계속 유지해야겠죠?
예시 코드 함께 보시죠!
위치 전송 작업
func updateLocationToServer(_ location: CLLocation) {
Task.detached(priority: .background) {
try await LocationService.shared.sendLocation(location)
print("위치 정보 서버 업데이트 완료")
}
}
파일 업로드 작업
func uploadFile(_ fileData: Data) {
Task.detached(priority: .background) {
print("파일 업로드 시작 (백그라운드 실행)")
try await FileUploader.shared.upload(fileData)
print("파일 업로드 완료")
}
}
메인 Actor와 독립적인 작업 실행 (UI 업데이트 방지)
Swift에서는 UI 관련 코드는 @MainActor에서 실행되는데, UI 스레드의 영향을 받지 않고 백그라운드에서 실행해야 하는 경우 Task.detached()가 필요할 수 있습니다.
즉, UI업데이트를 방해하지 않고, 무거운 연산(이미지 처리, 데이터 변환 등)을 백그라운드에서 수행하도록 설정할 수 있습니다.
func processImageInBackground(_ image: UIImage) {
Task.detached(priority: .background) {
print("백그라운드에서 이미지 처리 실행 중...")
let processedImage = await heavyImageProcessing(image)
await MainActor.run {
print("메인 스레드에서 UI 업데이트 실행")
updateUI(with: processedImage)
}
}
}
Task-local Storage를 상속받지 않도록 해야 할 때
일반적인 Task {}는 부모 Task의 Task-local Storage 값을 상속받습니다.
하지만, 로깅(Log)이나 사용자 인증 정보 초기화 작업같이 특정 작업에서는 Task-local Storage를 초기화하고 새롭게 실행해야 할 수도 있습니다.
struct Logger {
@TaskLocal static var userSessionID: String?
}
func logEventInNewContext() {
Task.detached {
Logger.userSessionID = nil // 기존 Task-local Storage 값 초기화
print("새로운 Task-local Storage에서 로그 기록 중...")
await logEvent()
}
}
Task {}를 사용하면 기존의 userSessionID를 상속받을 수도 있지만,
Task.detached()를 사용하면 Task-local Storage를 초기화한 상태에서 실행 가능합니다.
정리
상황 | Task.detached() 필요 여부 | 이유 |
백그라운드에서 네트워크 요청 실행 | ✅ 사용해야 함 | 부모 Task가 취소되더라도 요청이 중단되지 않음 |
UI 업데이트와 무관한 비동기 작업 실행 | ✅ 사용해야 함 | UI 스레드에서 실행되지 않도록 독립 실행 가능 |
앱이 백그라운드 상태에서도 실행되어야 하는 작업 | ✅ 사용해야 함 | 백그라운드 실행을 보장할 수 있음 |
Task-local Storage를 상속받지 않고 실행해야 할 때 | ✅ 사용해야 함 | 기존 Task-local Storage를 초기화해야 함 |
부모 Task의 실행 컨텍스트(우선순위, 실행 액터)와 완전히 독립적으로 실행해야 할 때 | ✅ 사용해야 함 | 실행 환경을 새롭게 설정 가능 |
일반적인 구조적 동시성을 유지해야 할 때 | ❌ 사용하면 안 됨 | Task {} 또는 withTaskGroup()을 사용하는 것이 더 적절함 |
부모 Task와 자식 Task가 같은 실행 컨텍스트를 유지해야 할 때 | ❌ 사용하면 안 됨 | Task.detached()는 실행 컨텍스트를 상속받지 않음 |
마무리..

휴.. 저희 이제 마무리하면서 서론에서 나열해놨던 의문들에대해 답해볼까요?
💡 공식 문서에서도 가능하면 detached를 사용하지 말라고 권장하는 이유는 뭘까?
:실행 환경, 우선순위, Task-local storage, 취소 관리를 상속받지 않기 때문에 실행을 직접 설정하고 관리해야 할 것들이 많아서!
💡 detached 사용하지 않고, 우선 순위를 별개로 부여하는 방법이 있을까?
: withTaskGroup(priority:)을 사용!
💡 다른 우선순위를 적용할 때 detached를 무조건 써야 하는 걸까?
: 아님! detached를 꼭 써야 하는 건 아니며, 되도록이면 withTaskGroup(priority:)을 사용하는 것이 권장됨.
💡 detached는 어디에서 사용하는가?
: 백그라운드에서 계속 실행되어야 하는 작업인 파일 다운로드, 위치 정보 전송 등을 해야할때
UI 업데이트를 방해하지 않고 무거운 연산을 처리해야할때
Task-local Storage 값을 상속받지 않아야할때
긴 여정이었는데, 어떠셨나요?
이 글이 detached에 대해 이해하는 데 조금이라도 도움이 되었다면 좋겠습니다! 😊
혹시 잘못된 부분이 있다면 댓글로 알려주세요! 바로 수정하겠습니다.
읽어주셔서 감사합니다! 🙌
'Swift' 카테고리의 다른 글
[Concurrency] Task 톺아보기 (3) | 2025.03.02 |
---|---|
[Swift] Split과 Components (0) | 2023.01.29 |
[Swift] Method 랑 Computed Property 중 어떤걸 사용해야할까? (0) | 2023.01.29 |
[Swift] 생성자(initializer) (1) | 2023.01.29 |
[Swift] Method (메소드) (0) | 2023.01.29 |