Modern Concurrency in Swift 를 읽고 간단 정리
Modern Swift Concurrency의 등장
애플이 비동기 프레임워크에 대해 중요하게 발표한 마지막 시기는
GCD(Grand Central Dispatch)가 나왔을 때다.
다만 이는 순수 Swift 코드가 아니라, Objective-C의 것을 빌려 쓴 것이다.
Swift 5.5에서 부터 Swift 고유의 asynchronous, concurrent 코드를 작성할 수 있게 된다.
Asynchronous와 Concurrent
잠깐 간단하게 짚고 넘어가자면 아래와 같다.
Synchronous (동기)
ㄴ 작업이 순차적으로 실행 / 하나의 작업이 완료되기 전에 다른 작업을 시작하지 않음
Asynchronous(비동기)
ㄴ 작업이 완료될 때 까지 기다리지 않고 다른 작업을 계속해서 수행할 수 있음.
Serial(직렬)
ㄴ 작업을 순차적으로 하나씩 처리
Concurrent(동시성)
ㄴ 여러 작업이 동시에 실행될 수 있음
Synchronous (동기) / Asynchronous(비동기)는 작업의 실행 흐름 (시간적 흐름)에 초점
Serial(직렬) / Concurrent(동시성)은 작업의 순서에 초점
비동기 실행은 서로 다른 프로그램의 조각을 하나의 쓰레드에서 다양한 순서로 수행을 가능하게 한다.
때로는 다중 쓰레드에서 동시에 여러 작업들이 동작하기도 한다.
다만 비동기 context에서는 함수 수행의 정확한 순서를 보장하기 어렵다.
우리가 흔히 사용하는 비동기 호출의 예시는 네트워크 요청, 그리고 completion 클로저다.
(completion 콜백을 기다리는 동안 앱은 다른 일을 할 수 있다)
그 외에 의도적으로 프로그램의 일부를 병렬로 처리하고 싶다면, Concurrent API 들을 사용하면 된다.
하지만 이는 data-race 같은 동시성 문제를 발생시킬 수 있기 때문에 주의해야 한다.
주의해야 하지만, 쫄지 않아도 된다.
동시성 문제에 대한 주의를 기울이면, CPU를 아주 잘 사용하면서 더욱 빠른 앱을 구사할 수 있다.
기존 Concurrent API 들의 문제점
왜 Swift는 새로운 Concurrency 모델을 필요로 했을까 ?
Swift 5.5 이전 우리는 비동기 코드 작성을 위해 GCD를 사용하거나,
Operation, Thread, pthread 같은 API를 사용하기도 했다.
이 API들은 모두 공통 foundation을 갖는다. (POSIX threads)
ㄴ 프로그래밍 언어에 제약받지 않는 표준화된 모델이다.
ㄴ 각각의 실행 흐름은 쓰레드이고 다중 쓰레드들이 오버랩되어 동시에 수행된다.
Operation, Thread 같은 Thread wrapper들은 쓰레드 관리를 개발자에게 요구한다.
쓰레드의 생성과 제거, 수행 순서, 쓰레드간 공유 데이터 관리 등 신경쓸게 많다.
오류가 발생하기 쉽고 매우 번거롭다.
GCD도 별반 다를 것 없다.대표적인 문제점들은 아래와 같다.
Thread explosion
- 너무 많은 쓰레드가 context switching을 요청 --> 성능 저하
Priority Inversion
- 동일 큐에서 낮은 우선순위의 작업이 높은 우선순위의 작업의 수행을 block
Lack of execution hierarchy
- 비동기 코드에서 작업 간의 우선순위나 관계가 명확하지 않아 제어와 관리가 어려움
이러한 단점들을 해소하기 위해 새로운 동시성 모델이 Swift 5.5에 등장했다.
Modern Swift Concurrency
앞으로 살펴 볼 Modern Concurrency가 어떤 특징을 갖고 있는지 간단하게 살펴보자.
1. COOPERATIVE THREAD POOL
- CPU 코어 개수만큼 쓰레드를 유지
- 런타임에 쓰레드 생성 / 제거, 쓰레드 스위칭 비용이 절감됨.
- 대신 쓰레드 풀 내에 이용 가능한 쓰레드에서 빠르게 suspend, resume 수행
- supsend를 통해 비동기 메서드가 대기하는 동안 다른 작업들이 실행될 수 있다.
2. async/await Syntax
- async await syntax 사용
- 컴파일 타임 / 런 타임에 해당 코드가 suspend, resume 될 것을 안다.
- 비동기 메서드들을 안전하게 코드로 강제할 수 있다.
- 강한 참조 방지 - escaping 클로저 더이상 없음
3. Structured Concurrency
- 구조화된 동시성
- 각각의 task들은 계층 구조를 갖게 된다.
- 부모 task가 취소 된다면 모든 자식 task도 취소됨.
- 런타임에 부모가 완료되기 전에 모든 자식들을 완료 대기 시킬 수도 있음.
4. Context-aware Code compilation
- 컴파일러는 비동기로 동작해야 하는 코드를 알고 있다.
- 공유 State를 수정하는 것과 같은 unsafe한 코드들에 대해 컴파일 에러를 발생시킨다.
- Actor - 컴파일 시간에 동기 및 비동기 접근을 구분하고, 안전하지 않은 코드를 작성하기 어렵게 만들어 데이터 손상을 방지
'iOS > Concurrency' 카테고리의 다른 글
Concurrency (5) Intermediate async/await & Checked Continuation (0) | 2024.09.01 |
---|---|
Concurrency (4) Custom Asynchronous Sequences With AsyncStream (0) | 2024.08.24 |
Concurrency (3) AsyncSequence & Intermediate Task (0) | 2024.08.15 |
Concurrency (2) Getting started With async/await (0) | 2024.08.15 |
swift docs - Concurrency (1) | 2023.11.03 |