Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- traits
- custom navigation bar
- swift concurrency
- swift 백준
- task cancellation
- SWIFT
- UIKit
- custom ui
- DP
- claen architecture
- rxdatasources
- swift dashed line
- swift navigationcontroller
- 타임라인 포맷팅
- RxSwift
- swift 점선
- reactorkit
- BFS
- domain data
- Tuist
- swift bottomsheet
- identifiable
- uikit toast
- task cancel
- paragraph style
- button configuration
- swift custom ui
- custombottomsheet
- tusit font 추가 방법
- coordinator
Archives
- Today
- Total
김경록의 앱 개발 여정
[Swift Concurrency] Task의 취소 본문
작업의 즉시 멈춤이 아닌, ‘취소를 전파’하는 개념
- Swift의 Task는 취소를 요청받더라도, 즉시 중단되는 것이 아니다.
- 대신, “취소되었다는 신호” 를 내부적으로 가지고 있고, 작업 내에서 그 신호를 직접 확인하고 적절히 대응해야 함.
- 이걸 "cooperative cancellation" 이라고도 함. 작업이 스스로 확인하고 정리하는 방식.(협동적 취소)
부모-자식 관계와 취소 전파
- Swift의 structured concurrency에서는 부모 Task가 있고, 그 안에 자식 Task가 만들어질 수 있어.
- 부모 Task가 취소되면, 자식 Task에게도 취소가 전파됨.
- 하지만! 자식 작업이 완전히 끝날 때까지 (심지어 에러가 발생했더라도), 부모 작업은 기다림.
- 즉, 취소되더라도 자식 작업은 graceful하게 끝나야 하며, 그동안 부모는 대기 상태.
취소 상태 확인: Task.isCancelled
- 작업 내부에서 현재 취소 상태인지 확인하고 싶을 때 사용
func someTask() async {
if Task.isCancelled {
print("취소 요청이 들어왔습니다.")
return
}
// 작업 수행
}
- 반복문이나 긴 작업 처리 중간중간에 Task.isCancelled를 확인하는 것이 일반적인 패턴.
try Task.checkCancellation()
- 이 함수는 Task.isCancelled를 체크하고, 취소되었다면 에러를 던짐.
- 에러 타입은 CancellationError
- Task가 취소되었을 때는 일반적인 에러 처리 흐름을 따름
- try 구문에서 Task.checkCancellation() 호출 시 CancellationError가 throw됨 → 이를 do-catch로 처리 가능
항목 설명
취소 방식 | 즉시 멈추는 게 아닌, 신호를 전달 |
부모-자식 구조 | 부모 취소 → 자식에게 전파되지만, 자식이 끝날 때까지 기다림 |
상태 확인 | Task.isCancelled 로 수동 확인 |
취소 체크 및 에러 던지기 | try Task.checkCancellation() |
에러 처리 | CancellationError 로 잡아서 분기 가능 |
✅ 중첩된 Task와 취소 전파
1. 중첩된 Task는 별도의 컨텍스트로 동작
- Swift에서 Task는 기본적으로 새로운 독립적인 실행 컨텍스트를 만든다.
- 즉, 상위 Task 내에서 Task { }로 생성한 Task는 부모와 별개임.
- 그래서 부모 Task가 취소되더라도, 내부에서 만든 Task에는 취소가 전파되지 않는다.
swift
복사편집
func parentTask() async {
Task {
// 이 Task는 부모와 별개
// 부모가 취소돼도 여기까지는 취소가 전파되지 않음
await doWork()
}
}
- 위 예제에서 내부 Task는 **“중첩되어 있지만 독립적”**인 구조.
- 취소 전파가 안 되는 이유는 같은 구조적 컨텍스트가 아니기 때문.
✅ 구조적 동시성에서는 취소가 제대로 전파됨
📌 예시 1: async let 사용 시
swift
복사편집
func example() async {
async let result1 = doSomething()
async let result2 = doSomethingElse()
// 부모가 취소되면 result1, result2 도 함께 취소됨
let _ = await (try? result1, try? result2)
}
- async let은 parent-child 관계가 유지되며, 구조적으로 연결되어 있음
- 부모가 취소되면 자식도 취소됨
📌 예시 2: withTaskGroup
swift
복사편집
func example() async {
await withTaskGroup(of: Void.self) { group in
group.addTask {
await workA()
}
group.addTask {
await workB()
}
group.cancelAll() // → 모든 작업에 취소가 전파됨
}
}
✅ 직접적인 취소 처리를 구현하지 않아도 되는 경우
취소에 대응하는 API는 자동으로 취소됨
- 예를 들어 URLSession.shared.data(from:) 같은 API는 내부적으로 CancellationError를 던질 준비가 되어 있는 구조야.
- 즉, 우리가 따로 Task.isCancelled를 확인하지 않아도, Task가 취소되면 이 함수가 자동으로 취소되고 에러를 throw함.
func fetchData(from url: URL) async throws -> Data {
let (data, _) = try await URLSession.shared.data(from: url)
return data
}
- 이 작업이 포함된 Task가 취소되면, data(from:)가 취소되고 CancellationError가 throw됨.
- 별도의 checkCancellation() 필요 없음.
- Task.sleep 도 이런 경우
'TIL' 카테고리의 다른 글
[Swift Concurrency] 구조적 동시성의 취소(feat: 명시,암시적 취소전파) (0) | 2025.04.18 |
---|---|
[Swift Concurrency] Structured Concurrency 구조적 동시성 (0) | 2025.04.15 |
[Swift] Identifiable (0) | 2025.03.28 |
[RxSwift] Single<Void> 와 Completable (0) | 2025.03.13 |
[Clean Architecture] DTO와 도메인 모델의 차이와 분리해서 사용해야하는 이유 (0) | 2025.03.13 |