-
[SE-0520] Discardable result use in Task initializersSwift 2026. 4. 25. 09:58
안녕하세요. 그린입니다 🍏
이번 포스팅에서는 SE-0520 — Task 이니셜라이저에서의 Discardable result 처리에 대해 정리해보겠습니다 🙋🏻

Intro
- Proposal: SE-0520
- Author: Konrad 'ktoso' Malawski
- Status: Accepted
Motivation
현재 아래 코드는 아무런 경고 없이 컴파일됩니다.
Task { // no warning try boom() } print("Yay!")간단한 예시에서는 에러를 놓쳤다는 게 명확하지만, 실제 코드베이스에서는 노이즈가 많아서 에러를 조용히 무시했다는 사실을 놓치기 쉽거든요.
이 문제는 Swift 커뮤니티에서 여러 차례 제기되었습니다.
- Task initializer with throwing closure swallows error
- Pitch: non-discardable throwing tasks
- Pitch: Improved error handling in unstructured task initializers
원래 Task {} 문법은 주로 fire-and-forget 용도로 설계되었고, throw된 에러를 처리하는 경우를 충분히 고려하지 않았습니다.
이 동작은 Swift의 에러 핸들링 모델과 일관성이 없고, 에러가 조용히 무시되어 찾기 어려운 버그로 이어집니다 🐛
Detailed Design
concurrency 라이브러리는 Task.init, Task.detached, Task.immediate, Task.immediateDetached에 typed throws를 도입했습니다.
이를 기반으로 throw 타입(throws(Failure))을 인식하는 새로운 경고 메커니즘을 도입합니다.
Failure 타입이 Never가 아닌 경우에만 경고가 발생합니다.
워닝 동작은 다음과 같아요~
Task { } // no warning Task { throws in ... } // warning: Unstructured throwing task was not used, which may accidentally ignore errors thrown inside the task [#NoUseUnstructuredThrowingTask] // note: To silence this warning, handle the error inside the task, or store/discard the task value explicitly Task { throws(Boom) in ... } // warning: Unstructured throwing task was not used, which may accidentally ignore errors thrown inside the task [#NoUseUnstructuredThrowingTask] // note: To silence this warning, handle the error inside the task, or store/discard the task value explicitly Task { throws(Never) in ... } // no warning동일한 변경사항이 모든 unstructured task 이니셜라이저에 적용됩니다.
경고를 없애는 방법
명시적으로 값을 무시하면 경고를 없앨 수 있습니다.
_ = Task { throws in ... }혹은 실제로 값을 사용하는 것이 권장되는 방법입니다.
throw된 에러를 관찰하려면 이렇게 하면 됩니다.
let task = Task { throws in } let value = try await task.value // task가 실패하면 에러를 throw합니다
Source Compatibility / ABI
- 소스 호환성은 유지되지만, 새로운 경고가 발생할 수 있습니다.
- 경고는 _ = Task { try boom() }처럼 명시적으로 무시하면 됩니다.
- 컴파일 타임 진단 동작만 변경되므로 ABI에는 영향이 없습니다.
Alternatives Considered
아무것도 하지 않기
커뮤니티에서 충분히 오랫동안 문제로 제기되어 왔기 때문에, 제안자는 현 상태를 유지하는 건 적절하지 않다고 판단했어요.
non-throwing 이니셜라이저에서도 discardableResult 제거하기
throw하지 않는 Task는 대부분 의도적인 fire-and-forget입니다.
결과값에 관심이 있다면 이미 task를 저장하거나 즉시 await했을 테니까요.
그래서 제안자는 throw하지 않는 이니셜라이저에는 이 변경을 적용하지 않기로 했습니다.
Conclusion
작지만 굉장히 실용적인 변경입니다.
Task { try something() }처럼 작성했다가 에러를 조용히 삼키는 버그는 실제 코드베이스에서 찾기 굉장히 어렵거든요.
이번 변경으로 컴파일러가 명시적으로 경고를 내려주니, 에러 처리에 대한 개발자의 의도를 코드에 드러낼 수 있게 됩니다 🙌
Swift의 에러 핸들링 철학인 "에러는 반드시 처리되어야 한다" 와 한층 더 일관성 있게 맞춰진 변경이라고 생각합니다.
References
swift-evolution/proposals/0520-discardableresult-task-initializers.md at main · swiftlang/swift-evolution
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution
github.com
Pitch: Remove discardableResult from throwing task initializers
Hi everyone, continuing the effort to improve small yet valuable things in the Concurrency library, I’d like to propose an often discussed but never finished change to Task.init and friends: removing the @discardableResult when the operation is throwing.
forums.swift.org
'Swift' 카테고리의 다른 글
[SE-0524] Add withTemporaryAllocation using Output(Raw)Span (1) 2026.05.09 [SE-0521] Improved Syntax for Optionals of Opaque and Existential Types (0) 2026.05.01 [SE-0519] Borrow and Inout types for safe, first-class references (2) 2026.04.11 [SE-0518] tide-Sendable (0) 2026.04.05 Swift 6.3 (0) 2026.03.29