Swift Concurrency Companion

Swift Concurrency 완전 대응 해설서

Swift 공식 Concurrency 챕터의 흐름을 빠짐없이 따라가며, 각 개념을 실무 관점으로 쉽게 풀어쓴 학습 문서다.

원문 링크: The Swift Programming Language - Concurrency

1) Concurrency 개요

핵심

Swift는 언어 차원 지원으로 많은 race를 컴파일 단계에서 차단하고, 일부 런타임 race는 실행 중단으로 보호한다.

스레드와 관계

모델은 스레드 위에서 동작하지만, 개발자는 스레드를 직접 조작하지 않아도 된다. async 함수는 스레드를 양보할 수 있다.

2) async/await 기본

func listPhotos(inGallery name: String) async -> [String] { ... }
let names = await listPhotos(inGallery: "Summer Vacation")

3) 실행 순서 이해 (중단/재개)

4) async를 호출할 수 있는 위치

중요: 동기 코드에서 async를 안전하게 감싸 "기다리는" 범용 우회는 제공되지 않는다(교착/경쟁 위험).

5) Task.sleep과 학습용 지연

`Task.sleep(for:tolerance:clock:)`은 현재 task를 일정 시간 중단해 concurrency 동작을 학습/시뮬레이션할 때 유용하다.

func listPhotos(inGallery name: String) async throws -> [String] {
    try await Task.sleep(for: .seconds(2))
    return ["IMG001", "IMG99", "IMG0404"]
}

6) Asynchronous Sequences

for try await line in handle.bytes.lines {
    print(line)
}

7) 병렬 호출: await 순차 vs async let 병렬

순차 (`await` 연속)

앞 결과가 필요할 때 사용. 호출 하나가 끝난 후 다음 호출로 진행.

병렬 (`async let`)

결과를 나중에 한 번에 쓰면 유리. 시작은 동시에, 소비 시점에 `await`.

async let a = downloadPhoto(named: photoNames[0])
async let b = downloadPhoto(named: photoNames[1])
let photos = await [a, b]

8) Tasks와 TaskGroup

let photos = await withTaskGroup(of: Data.self) { group in
    for name in photoNames { group.addTask { await downloadPhoto(named: name) } }
    var results: [Data] = []
    for await p in group { results.append(p) }
    return results
}

9) Task Cancellation

10) Unstructured Concurrency

11) Isolation 개요

12) Main Actor

@MainActor
func show(_ photo: Data) { ... }

func downloadAndShowPhoto(named name: String) async {
    let photo = await downloadPhoto(named: name)
    await show(photo)
}

13) Actors

actor TemperatureLogger {
    var measurements: [Int]
    private(set) var max: Int
    ...
}

14) Global Actors

15) Sendable Types

struct TemperatureReading: Sendable {
    var measurement: Int
}

@available(*, unavailable)
extension FileDescriptor: Sendable {}

실무 체크리스트

실습 프로젝트 (컴파일/런타임 재현)

Q

Q. async면 자동으로 빨라지나?

A. 아니다. 블로킹 완화는 되지만 디코드/렌더/알고리즘 비용은 별도 최적화가 필요하다.

Q. actor만 쓰면 race가 끝나나?

A. 공유 상태 race는 줄지만 취소/재진입/MainActor 경계/리소스 정리는 별도 설계가 필요하다.