์์์๋ ์๋กญ๊ฒ ๋์จ ๊ฐ๋ ๋ค์ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง์ ๋ํด์ ์์๋ณด์๋ค. ๊ทธ๋ ๋ค๋ฉด ์ ์ด๋ ๊ฒ ์ค๊ณํ๋์ง, ์ค์ ๋ก๋ ์ด๋ป๊ฒ ๋์ํ๋์ง ์์๋ณด์.
Threading Model
New feed reader ์ฑ์ ๋ง๋ ๋ค๊ณ ์๊ฐํด๋ณด์. ๊ณ ์์ค์์ ์ด๋ ํ ๊ฒ๋ค์ด ํ์ํ ์ง ์๊ฐํด๋ณด์.

- User Interface๋ฅผ ์ฒ๋ฆฌํ main thread๊ฐ ์๋ค.
- User๊ฐ ๊ตฌ๋ ํ news feed๋ฅผ ์ถ์ ํ Database๋ ์๋ค.
- ๋ง์ง๋ง์ผ๋ก feed๋ก ๋ถํฐ ์ต์ content๋ฅผ ๋ฐ์์ฌ ๋คํธ์ํฌ ์ฒ๋ฆฌ๋จ์ด ์๋ค.
Grand Central Dispatch
User๊ฐ ์๋ก์ด news feed๋ฅผ ๊ฐ์ ธ์ค๋ผ๋ gesture๋ฅผ ํ๋ค๊ณ ์๊ฐํด๋ณด์. GCD๋ฅผ ์ฌ์ฉํ์ ๋๋ ๋ค์๊ณผ ๊ฐ์ด ์ฒ๋ฆฌํ์๋ค.

User์ gesture๋ฅผ ๋ฐ์ Serial Dispatch Queue์ async ํ๊ฒ ๋์์ ๋๊ธด๋ค.
- ๋ค๋ฅธ Dispatch Queue์์ ์์ ์ ๋ฝ์์ด์ผ๋ก์จ ๋ง์ ์์ ์์ ์ผ์ง๋ผ๋ main thread๊ฐ user์ ๋์์ ๊ณ์ ๋ฐ์ ์ ์๋๋ก ํ๊ธฐ ์ํด์
- serial queue๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ database์ ์ ๊ทผ์ ์์ด ์ํธ ๋ฐฐ์ ๋ฅผ ๋ณด์ฅ

Database Queue์์์ user๊ฐ ๊ตฌ๋ ํ feed๋ค์ iterateํ๋ฉฐ, network ์์ฒญ์ ํ๋๋ก URL Session์ ๋๊ธด๋ค.

Network ๊ฒฐ๊ณผ๊ฐ ๋ค์ด์ค๋ฉด, URL Session callback์ด delegate queue์์ ์คํ๋๋ค.
- ์ด ๋ Queue๋ conccurent queue๋ก ์ง์ ํ์ฌ parallelism์ ์ ์ฉ์์ผ ํจ์จ์ ์ผ๋ก ๋์์ํค๋๋ก ํด๋ณด์.
callback์์๋ ๋ฐ์ ๊ฒฐ๊ณผ๋ฅผ Database Queue(Serial)์ ์์ ์ ๋๊ธด๋ค.
- ์์ฐจ์ ์ผ๋ก ๋ฐ์๋๊ธฐ ๋๋ฌธ์ data race ์ํฉ์ ๋ฐ์ํ์ง ์๋๋ค.
- ๊ฐ์ฅ ์ต์ ์ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์๋๊ธฐ ๋๋ฌธ์, ์ด ๊ณผ์ ์์ cache๋ฅผ ์ ์ฉํ ์๋ ์์ ๊ฒ์ด๋ค.
๋ง์ง๋ง์ผ๋ก main thread์ ํด๋น ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ํ์ฌ UI๋ฅผ ์ ๋ฐ์ดํธํ๋ค.
์ด ๊ณผ์ ์ ๋งค์ฐ ํฉ๋ฆฌ์ ์ธ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค. main thread๋ฅผ ๋ง์ง ์์ UI ์ ๋ฐ์ดํธ๋ ์ผ์ด๋๊ฒ ํ์์ผ๋ฉฐ, network ์์ฒญ๋ concurrentํ๊ฒ ์ํํ๋ฉฐ, data base์์๋ serial queue๋ฅผ ์ฌ์ฉํ์ฌ data race ์ํฉ์ด ๋ฐ์ํ์ง ์๋๋ก ํ๋ค. ์ด๋ฒ์๋ ์ฝ๋๋ฅผ ๋ด๋ณด์.
func deserializeArticles(from data: Data) throws -> [Article] { /* ... */ }
func updateDatabase(with articles: [Article], for feed: Feed) { /* ... */ }
// 1. ๋คํธ์ํฌ ์์ฒญ์ ์ํ URLSession(Concurrent Queue)
let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: concurrentQueue)
// 2. Database์์ ๊ฐ์ ธ์จ feed ๋ชฉ๋ก์ ๋ํด ๋ชจ๋ network ์์ฒญํ๋ค.
for feed in feedsToUpdate {
// 3. completion handler์ ์ ํ task๋ system์์ ์์ฒญ์ ๋ฐ์ ํ์ ์ฒ๋ฆฌ๋๋ค.
// ๊ฒฐ๊ณผ๋ delegate queue, ์ฌ๊ธฐ์๋ concurrent queue์์ ๋ฐ๊ฒ ๋๋ค.
let dataTask = urlSession.dataTask(with: feed.url) { data, response, error in
// ...
guard let data = data else { return }
do {
// 4. ๋ฐ์ ๊ฒฐ๊ณผ์ ๋ํด deserialization ํ๋ค.
let articles = try deserializeArticles(from: data)
// 5. ํ๋ฉด์ ์
๋ฐ์ดํธ ๋๊ธฐ์ ์ ๊ฒฐ๊ณผ์ ๋ํด database queue์ task๋ฅผ sync๋ก ๋๊ฒจ ๋ฐ์ํ๋ค.
databaseQueue.sync {
updateDatabase(with: articles, for: feed)
}
} catch { /* ... */ }
}
dataTask.resume()
}์๊น ์๊ฐํ ํ๋ฆ์ ๋ํด ์ฝ๋๋ก ์ค๋ฌด์คํ๊ฒ ์ ํ๋ค. ํ์ง๋ง ์ด ์ฝ๋๋ ์ฑ๋ฅ ์ธก๋ฉด์์ ์จ๊ฒจ์ง ํจ์ ์ด ์๋ค.
GCD and thread bring up
์ด ๋ฌธ์ ๋ฅผ ์ดํดํ๊ธฐ ์ํด์๋ GCD Queue๊ฐ ์ด๋ป๊ฒ work item์ ์ฒ๋ฆฌํ๋์ง ์์์ผ ํ๋ค.

- concurrent queue๋ ์ฌ๋ฌ๊ฐ์ work item์ ํ๋ฒ์ ์ฒ๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์ ์์คํ ์ CPU Core์๊ฐ ํฌํ๋๋ ์์ค๊น์ง ์ฌ๋ฌ๊ฐ์ thread๋ฅผ ๊ฐ์ ธ์จ๋ค.
- ๊ทธ๋ฐ๋ฐ ๋ง์ฝ, Thread๊ฐ Block๋๋ฉด, (๊ทธ๋ฆฌ๊ณ ๋ ๋ง์ ์ํ๋ work๋ค์ด ์๋ค๋ฉด) System์ ํด๋น CPU Core๋ฅผ ์ฑ์ธ ์ ์๋ thread๋ฅผ ๋ ๊ฐ์ ธ์จ๋ค.
- ๋ค๋ฅธ Thread์๊ฒ ์ฒ๋ฆฌ ๊ถํ์ ๋๊ฒจ์ค์ผ๋ก์จ ๋ค๋ฅธ Thread๊ฐ ์ผ์ ํ ์ ์๋๋ก ํ๊ธฐ ์ํด์
- Blocked๋ Thread๋ ๋ค์ ์ฒ๋ฆฌ๋ฅผ ์ํด semaphore์ฒ๋ผ ๋ค์ resource๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ ์ ์๋ค. ๊ทธ๋ ๊ธฐ์ ๋ค์ ์์ ์ด ์ฒ๋ฆฌ๋์ด์ผ block์ด ํด์ ๋ ์ ์๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ ๋ฐฉ์์ ์ฑํํ๋ค.
- ์ด๋ ๊ฒ ์๋กญ๊ฒ ๋ง๋ค์ด์ง thread๋ resource๋ฅผ unlockํ์ฌ ์์ ์ ๊ณ์ ์ด์ด๋๊ฐ ์ ์๊ฒ ํด์ค๋ค.
์ด์ ๋์์ ์ข ์ดํดํ์ผ๋ ๋ค์ news feed์ฑ์ผ๋ก ๋์๊ฐ๋ณด์.
CPU Execution
URLSession์ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ค๋ ๋์์์ Apple watch ์ฒ๋ผ 2๊ฐ์ ์ฝ์ด๊ฐ ์๋ค๊ณ ์๊ฐํด๋ณด์.

- Core๊ฐ 2๊ฐ์ด๋ฏ๋ก GCD๋ feed update result๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด 2๊ฐ์ thread๋ฅผ ๊ฐ์ ธ์จ๋ค.
- ๊ทธ ์์์
databaseQueue.sync๋ฅผ ํธ์ถํ๊ณ ์๊ธฐ ๋๋ฌธ์, ํด๋น task๋ block๋๋ค. - GCD๋ ๋ค์ thread๋ฅผ ๊ฐ์ ธ์ ๋์์ ์ํํ๋ค.
- ๊ทธ ์์๋
databaseQueue.sync๊ฐ ์๊ธฐ ๋๋ฌธ์ block๋๋ค. - 2~3์ด loop๋ฅผ ๋ค ๋๋๊น์ง ๋ฐ๋ณต๋๋ค.
์ด ๊ณผ์ ์์ CPU๋ ๋ค๋ฅธ Thread๊ฐ์ Context Switching์ ์ํํ๋ค. ์ฆ, ์ฐ๋ฆฌ๊ฐ ์์ฑํ ์ฝ๋์์ ์ฝ๊ฒ ๋ง์ ์์ thread๊ฐ ๋ฐ์ํ๊ณ , ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ ํ๊ฐ ์๊ธธ ์ ์๋ค.
Excessive concurrency
Thread ์๊ฐ ๋ง์์ง๋ ๊ฒ์ Application์ ์ข์ง ์์ ์ํฅ์ ๋ผ์น๋ค.
- CPU Core๋ณด๋ค ๋ง์ ์์ thread๋ ์์คํ ์ ๋์์ ๋ญ๋นํ๋ ๊ฒ์ด๋ค.
- Thread Explosion
- 6๊ฐ์ core๊ฐ ์๋ iphone์ ์๊ฐํด๋ดค์ ๋ 100๋ฒ์ feed update๋ฅผ ์ํํ๋ค๋ฉด, ์ฐ๋ฆฌ๋ core์๋ณด๋ค 16๋ฐฐ๋ ๋ง์ thread๋ฅผ ์์ฑํ ๊ฒ์ด๋ค.
- Memory overhead
- Scheduling overhead
๊ฒฐ๊ตญ, core ์๋ณด๋ค ๋ง์ ์์ thread๋ฅผ ํตํด ๊ด๋ฆฌํ๋ ๊ฒ์ memory, scheduling์ ์์ด ๋ฌธ์ ๋ฅผ ์ผ์ผํจ๋ค.
Memory overhead

์ฝ๊ฒ ์ ์ ์๊ฒ ์ง๋ง, block๋ thread๋ ๊ฒฐ๊ตญ ๋์ค์ ๋์์์ ๋ณธ์ธ์ ์์ ์ ์ํํด์ผ ํ๋ค. ์ด์ ์์ ์์ ์ด ์ค๋จ๋ ์ํ๋ฅผ ๊ธฐ์ตํ๊ณ ์์ด์ผ ํ๊ณ , ์ด๋ ๊ณง memory์ ์ ์ฅ๋๊ฒ ๋๋ค.
๊ฐ๊ฐ์ thread์์๋ ์คํ ํ๋ฆ์ ์ ์ฅํ๋ stack์ด ์๊ณ , ๊ทธ์ ๊ด๋ จ๋ kernal ์๋ฃ๊ตฌ์กฐ๊ฐ thread๋ฅผ ์ถ์ ํ๊ณ ์๋ค. ๋ช๋ช ์ค๋ ๋๋ lock์ผ๋ก ๋ถ์กํ์์ด, ๋ค๋ฅธ thread์ ๋์์ด ํ์ํ ์๋ ์๋ค. ์ฆ, ์ด๋ฐ ๋น์ฅ ๋์ํ์ง ์๋ thread๋ค์ด ๋ง์ ์์ memory์ ์์์ ๋ถ์ก๋ ์ํ๊ฐ ๋ฒ์ด์ง๋ค.
๋ด์ฉ์ด ํท๊ฐ๋ฆฐ๋ค๋ฉด 07: ์ฐ๋ ๋(Thread)์ ์ฐธ๊ณ ํ์.
Scheduling overhead
Thread๊ฐ ๋ง์์ง๋ ๊ฒ์ ๋ฉ๋ชจ๋ฆฌ ์ธก๋ฉด์์๋ง ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ ์๋๋ค. ๊ฒฐ๊ตญ ์ด๋ฐ Thread๋ค์ด ์ธ์ ์ฒ๋ฆฌ๋ ๊ฒ์ธ์ง๋ฅผ ๊ด์ฅํ๋ ์ค์ผ์ฅด๋ง๋ ํด์ผ ํ๋๋ฐ, ๋ง์์ง ์๋ก ์ด๋ฐ ๊ณผ์ ์ ๋์ฑ ๋ณต์กํด์ง๊ธฐ ๋ง๋ จ์ด๋ค.

์ ํ๋ Core์๋ฅผ ๊ฐ์ง ์ํ์์ Thread explosion์ด ๋ฐ์ํ๋ฉด, ๊ณผ๋ํ Context Switching์ ๋ฐ์์ํฌ ์ ์๋ค. ์ด๋ ๊ฒ ๋ฆ์ด์ง ์ฒ๋ฆฌ๋ ๊ฒฐ๊ตญ ์ค์ํ ์ฒ๋ฆฌ๋ฅผ ๋ฆ๊ฒํ๊ฒ ๋ง๋ค ์ ์๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก CPU๊ฐ ํจ๊ณผ์ ์ผ๋ก ๋์ํ๋ ๊ฒ์ ๋ฐฉํดํ๋ค.
Swift Concurrency
์์์ ์ดํด๋ณธ ๊ฒ๊ณผ ๊ฐ์ด Thread explosion์ GCD์์ ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ์ด๋ค. ๊ทธ๋ผ์๋ ์ด ๋ถ๋ถ์ ์ฌ์ธํ๊ฒ ์บ์นํ์ฌ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋์น๊ธฐ ์ฌ์ด ๋ถ๋ถ์ด๋ค. ์ด๋ฐ ๋ถ๋ถ์์ Swift์ ์ธ์ด์ค๊ณ๋ concurrency๋ฅผ ์ค๊ณํ๋๋ฐ ์์ด ๋ค๋ฅธ ์ ๊ทผ์ ๋์ ํ๋ค.

- Core ์์ ๋ง๋ Thread๋ง ์ฌ์ฉํ๋ค.
- Blocking Thread๊ฐ ์์ด์ง๋ค.
- Full Thread Context Switching์ด ์์ด์ง๋ค.
- ๋์ ๊ฐ๋ฒผ์ด Object์ธ
Continuation์ ์ฌ์ฉํ๋ค.- ์์ ์ ์ฌ๊ฐ ์ฌ๋ถ๋ฅผ ์ถ์ ํ๋ค.
- Continuation๊ฐ์ switching์ด ๋ฐ์ํ๋ค.
- Full Thread Context Switching๋์ function call๋ก ๋์ฒดํ ์ ์๋ค.
์ฆ, Swift concurrency์์๋ runtime์ CPU Core ์๋งํผ์ Thread๋ง ์์ฑํ์ฌ ์ ๋ ดํ๊ณ ํจ์จ์ ์ผ๋ก work item์ด block๋์์ ๋ Switching์ ์ํํ๋ค. ์ด๋ฐ ๋์์ ์ํํ๊ธฐ ์ํด์๋ runtime์ Thread๋ฅผ ์ฐจ๋จํ์ง ์๋ Contract์ด ํ์ํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ธ์ด ์ญ์ ์ด๋ฅผ ์ง์ํ ์ ์์ด์ผ ํ๋ค.
Language features
์ด์ Swift์ Concurrency์์๋ ์ด Runtime Contract๋ฅผ ์ ์งํ ์ ์๋ ๊ธฐ๋ฅ์ ๋ง๋ จํ๋ค. ์ธ์ด ์ฐจ์์์ ์ ๊ณตํ๋ ๋๊ฐ์ง ๊ธฐ๋ฅ์ ์ค๋ช ํ๊ฒ ๋ค.
await์ ์ฌ์ฉ๊ณผ thread๋ฅผ non-block์ผ๋ก ์ฌ์ฉํ๋ค.- Swift runtime์ task์ ์์กด์ฑ์ ์ถ์ ํ๋ค.
์ด์ ์ news feed ์ฝ๋๋ฅผ Swift concurrency๋ฅผ ์ ์ฉํด ๋ค์ ์ ์ด๋ณด์.
func deserializeArticles(from data: Data) throws -> [Article] { /* ... */ }
func updateDatabase(with articles: [Article], for feed: Feed) async { /* ... */ }
// 1. Concurrent Queue์์ network ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ์ง ์๊ณ , concurrency๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด `TaskGroup`์ ์ฌ์ฉํ๋ค.
await withThrowingTaskGroup(of: [Article].self) { group in
for feed in feedsToUpdate {
// 2. `TaskGroup`์์ Child task๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๊ฐ์ feed๊ฐ update๋์ด์ผ ํจ์ ๋ช
์ํ๋ค.
group.async {
// 3. feed์ url์ ๊ธฐ๋ฐ์ผ๋ก ๋คํธ์ํฌ ์์ฒญํ๋ค.
let (data, response) = try await URLSession.shared.data(from: feed.url)
// 4. ๊ฒฐ๊ณผ๋ฅผ deserializeํ๋ค.
let articles = try deserializeArticles(from: data)
// 5. async function์ธ updateDatabase๋ฅผ ํธ์ถํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์
๋ฐ์ดํธํ๋ค.
await updateDatabase(with: articles, for: feed)
return articles
}
}
}์ฌ๊ธฐ์ ์ฃผ๋ชฉํ ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ๋ค.
asyncfunction์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐawaitํค์๋๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค.awaitํค์๋๋ ํ์ฌ ์์ ํ๊ณ ์๋ Thread๋ฅผ Blockํ๋ ๊ฒ์ด ์๋๋ค. non-blocking์ด๋ค.- block์ด ์๋๊ณ ํด๋น ์์
์
suspend์ํค๊ณ , ๋ค๋ฅธ ์์ ์ ํ๋ฌ ๊ฐ๋ค.
๊ทธ๋ฐ๋ฐ ๊ฐ๋ง ์์ด๋ณด์. ์ด๋ป๊ฒ ์์ ์ด thread๋ฅผ ํฌ๊ธฐํ๊ณ ๋๊ฐ ์ ์์๊น?
await and non-blocking of threads
async function์ด ์ด๋ป๊ฒ ๊ตฌํ๋์ด ์๋์ง ์์๋ณด๊ธฐ ์ ์, ์ด๋ป๊ฒ non-async function์ด ๋์ํ๋์ง ์์๋ณด์.
Non-async functions

Program์์ ๋์ํ๋ ๋ชจ๋ Thread๋ ํจ์ call์ํ๋ฅผ ์ ์ฅํ๊ธฐ ์ํ stack์ ๊ฐ์ง๊ณ ์๋ค.

ํ๋์ stack์ ์ดํด๋ณด์. ํ๋์ ํจ์๊ฐ call๋๋ฉด ์๋ก์ด frame์ด stack์ push๋๋ค. ์๋กญ๊ฒ ๋ง๋ค์ด์ง frame์ ์ง์ญ ๋ณ์ ์ ์ฅ, ๋ฐํ ์ฃผ์ ์ ๋ฌ, ๋ค๋ฅธ ๊ธฐํ ์ฉ๋๋ฅผ ์ํด ์ฌ์ฉ๋๋ค. ์ผ๋จ ํจ์๊ฐ ๋์์ ๋ฐ์น๊ณ ๋ฐํํ๋ฉด, stack frame์ pop๋๋ค.
Async functions

func updateDatabase(with articles: [Article], for feed: Feed) async throws {
// skip old articles ...
try await feed.add(articles) // 1. `updateDatabase` ํจ์ ๋ด๋ถ์์ `feed.add` ํจ์๊ฐ ํธ์ถ๋๋ค.
}
// on Feed
func add(_ newArticles: [Article]) async throws {
let ids = try await database.save(newArticles, for: self) // await ์ดํ์ ํ์ํ ๋ณ์๋ค์ stack frame์ ์ ์ฅ๋๋ค.
// 2. ์ด๋ฐ ์ด์ ๋ก, `id`, `article`์ stack frame์ ์ ์ฅ๋๋ค.
for (id, article) in zip(ids, newArticles) { // 3, 4. newArticle์ heap frame์์ ์ถ์ ๋๋ค.
articles[id] = article
}
}
// on Database
func save(_ newArticles: [Article], for feed: Feed) async throws -> [ID] { /* ... */ }Database ๊ตฌํ์ฒด์ save method๊ฐ ์๊ณ , Feed๊ตฌํ์ฒด์ add method๊ฐ ์๋ค๊ณ ์๊ฐํด๋ณด์.
updateDatabaseํจ์ ๋ด๋ถ์์feed.addํจ์๊ฐ ํธ์ถ๋๋ค.- stack frame์ ์ด suspension point์์ ์ฌ์ฉํ ํ์๊ฐ ์๋ ์ง์ญ ๋ณ์๋ฅผ ์ ์ฅํ๋ค.
addํจ์์ ์์๋await๋ก ํ์๋ ํ๋์ suspension point๊ฐ ์๋ค.id,article์ suspension point ์ ์๋ ํ loop body์์์ ์ฆ๊ฐ ์ฌ์ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ์ฌ์ด์ suspension point๋ ์๋ค.
- ์ด๋ฐ ์ด์ ๋ก,
id,article์ stack frame์ ์ ์ฅ๋๋ค. - ์ถ๊ฐ์ ์ผ๋ก heap์๋ ๋๊ฐ์ async frame์ด ์๋ค.
updateDatabase,add- ์ด์ ์กด์ฌ ์ด์ ๋, suspendsion point๋ฅผ ๋๋๋ค์ด ์ ์ฅํด์ผ ํ๋ ์ ๋ณด๋ฅผ ๋ด๊ธฐ ์ํจ์ด๋ค.
newArticlesargument๋await์ ์ ์ ์๋์์ผ๋await์ดํ์ ์ฌ์ฉ๋์ด ์ง๋ค.
- ์ด๋ฐ ๊ฒฝ์ฐ๋ฅผ ๋๋นํ์ฌ add async frame์
newArticles์ด ์ ์ฅ๋๋ฉฐ, ์ด๋newArticles์ ์ถ์ ํ ๊ฒ์ด๋ค. - ์ด์
saveํจ์๊ฐ ์คํ๋๋ฉด,add๋save๋ฅผ ์ํ ์๋ก์ด stack frame์ผ๋ก ๋์ฒด๋๋ค.- ์๋ก์ด stack frame์ pushํ๋ ๊ฒ ๋์ , top์ ์๋ stack frame์ ๋์ฒด๋๋ค.
- ์ด๋ ํ์ ํ์ํ ๋ณ์(
newArticles)๊ฐ ์ด๋ฏธ async frame list์ ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ด๋ค.

5๋ฒ๊น์ง ์งํํ ํ์, save function์ ์คํ์ด suspend๋์๋ค๊ณ ์๊ฐํด๋ณด์. ์ํฉ์ด ์ด๋ ๋ค๋ฉด, thread๊ฐ block๋์ด ์๋ ๊ฒ๋ณด๋ค ๋ค๋ฅธ ์์
์ ํ๊ธฐ ์ํด ์ฌ์ฌ์ฉ ๋๋ ๊ฒ์ด ๋ณด๋ค ์ข๋ค. ์์ ์ฌ์ง์ stack์ ๋ค๋ฅธ ์์
์ด ๋ค์ด์์๊ณ , ๊ฐ์ ๋ฐฉ์์ผ๋ก async frame์ ์์
์ฌํญ์ ์ ์ฅํ๋ ๊ฒ์ ๋ํ๋๋ค.

suspension point๋ฅผ ๊ฑธ์ณ ํ์ํ ๋ชจ๋ ์ ๋ณด๊ฐ heap์ ์ ์ฅ๋์ด์๊ธฐ ๋๋ฌธ์, conitinue ์คํ์ ํตํด ๋์ค์ ์ฌ์ฉ๋ ์ ์๋ค. ์ด async frame list๊ฐ conituation์ runtime ํํ์ด๋ค.

์ด๋์ ๋ ์๊ฐ์ด ์ง๋ ํ์, database ์์ฒญ์ด ๋๋ฌ๊ณ , ๋ช๋ช thread๊ฐ ๋น์๋ค. ์ด thread๋ ์ด์ ์ ์์ ์ ์์ฒญํ thread์ผ ์๋ ์๊ณ ๋ค๋ฅธ thread์ผ ์๋ ์๋ค. (core๊ฐ์์ ๋ง๊ฒ ์์ฑ๋ thread๋ฅผ ๋งํ๋ค.) ์ด๋ ๊ฒ ๋น thread์์ ์์ ์ด ๊ณ์๋๋ค.

func updateDatabase(with articles: [Article], for feed: Feed) async throws {
// skip old articles ...
try await feed.add(articles)
}
// on Feed
func add(_ newArticles: [Article]) async throws {
let ids = try await database.save(newArticles, for: self) // 1.
for (id, article) in zip(ids, newArticles) {
articles[id] = article
}
}
// on Database
func save(_ newArticles: [Article], for feed: Feed) async throws -> [ID] { /* ... */ }- async frame์์ ๊ฐ์ฅ ์ต๊ทผ ์์ ์ stack์ผ๋ก ๋ถ๋ฅธ๋ค. ์คํ๊ฒฐ๊ณผ๋ก, IDs๋ฅผ ๋ฐํ ๋ฐ๋๋ค.
save๋ฅผ ์ํ stack frame์add๋ฅผ ์ํ stack frame์ผ๋ก ๋์ฒด๋๋ค.- ์ด์ thread๋
zip์ฐ์ฐ์ ์ํํ ์ ์๋ค. zip ์ฐ์ฐ์ nonasync ์์ ์ด๊ธฐ ๋๋ฌธ์, ์๋ก์ด stack frame์ ๋ง๋ ๋ค.- Swift๋ ์ฌ์ ํ OS์ stack๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, async, nonasyncํ Swift code๋ชจ๋ ํจ์จ์ ์ผ๋ก C ์ Objective-C๋ฅผ ํธ์ถํ ์ ์๋ค.
- ๊ทธ ๋ฐ๋๋ ๊ฐ๋ฅํ๋ค.
- zip function์ด ๋๋๋ฉด, stack frame์ pop๋๊ณ ๊ณ์๋๋ค.
Tracking of dependencies in Swift task model
์ง๊ธ๊น์ง์ ๋ด์ฉ์ ๋ณด๋ฉด, ํจ์๊ฐ await๋ฅผ ๊ธฐ์ค์ผ๋ก continuations๋ก ๊นจ์ง ์ ์๋ค๋ ๊ฒ์ ๋ฐฐ์ ๋ค. ๋ฌผ๋ก ์๋ํ๋ thread๋ก ๋์๊ฐ ์๋ ์๋ค. ์ด๋ฐ ์ ์์ ํด๋น ์ง์ ์ potential suspenstion point๋ผ ๋ถ๋ฆฐ๋ค.
func deserializeArticles(from data: Data) throws -> [Article] { /* ... */ }
func updateDatabase(with articles: [Article], for feed: Feed) async { /* ... */ }
await withThrowingTaskGroup(of: [Article].self) { group in
for feed in feedsToUpdate {
group.async {
let (data, response) = try await URLSession.shared.data(from: feed.url) // โ
// โผ๏ธ
let articles = try deserializeArticles(from: data)
await updateDatabase(with: articles, for: feed)
return articles
}
}
}์ด ๊ฒฝ์ฐ, โ
๋ถ๋ถ์ async function์ด๊ณ , โผ๏ธ ๋ถ๋ถ์ โ
์์
์์ continuation์ด ๋ฐ์ํ ํ ๊ณ์๋๋ ์์
์ด๋ค. continuation์ async function์ด ์๋ฃ๋ ํ์๋ง ์คํ๋ ์ ์๋ค. ์ด๊ฒ์ด Swift concurrency runtime์์ ์ถ์ ํ๋ ์์กด์ฑ์ด๋ค.
๋น์ทํ๊ฒ, ์ต์๋จ์ ๋ณด์ด๋ TaskGroup์์๋ parent task๋ ํ์์ child task๋ฅผ ๋ง๋ค ์ ์๋๋ฐ, ๊ฐ๊ฐ์ child task๊ฐ ์๋ฃ๋์ด์ผ parent task๊ฐ ๊ณ์๋ ์ ์๋ค. ์ด๋ ๊ฒ scope๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฝ๋์ ์์กด์ฑ์ด ํํ๋ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ๊ฒ๋ค์ Swift compiler์ runtime์ ๋ช
์์ ์ผ๋ก ์๋ ค์ง๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฐ Task๋ Swift runtime์ ์๋ ค์ง task(Continuation, child task)๋ง await ํ ์ ์๋ค. ์ด๋ ๊ฒ ์ ์ฝ์ด ๊ฑธ๋ ค์๊ธฐ ๋๋ฌธ์, Swift concurrency ์์ ํ์
์ผ๋ก ๋ง๋ค์ด์ง Swift concurrency๋ runtime์ task๊ฐ์ dependency chain์ ๋ช
ํํ๊ฒ ์ ๊ณตํ๋ค.
Cooperative thread pool
๊ฒฐ๊ตญ ์ด๋ฐ ๊ณผ์ ์ ํตํด, thread๋ task dependency์ ๋ํด ์ถ๋ก ํ ์ ์๊ณ , ๋ค๋ฅธ task๋ฅผ ์ ํํ ์ ์๋ค. ์ฆ, ์์ ๊ณผ์ ๋ค์ ํตํด์ thread๊ฐ ํญ์ ๋ฌด์ธ๊ฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ runtime contract๋ฅผ ๋ฌ์ฑํ๋ค.
- ์ด๋ Default executor๋ก Swift concurrency๋ฅผ ์ง์ํ๋ ์๋ก์ด ํํ์ thread pool์ด๋ค.
- ์๋ก์ด thread pool์ CPU ์ฝ์ด ์๋งํผ๋ง thread๋ฅผ ๊ฐ์ง๊ณ ์๋ค.(spawn)
- ๋ฑ์์ฒ๋ผ ํฉ์ด์ง concurrency๋ฅผ ์ ์ดํ๋ค.
- Worker thread๋ block๋์ง ์๋๋ค.
- thread explosion์ ํผํ๊ณ , ๊ณผ๋ํ context switching์ ๋ฐฉ์งํ๋ค.
- workitem์ด block๋๋ฉด ๋ ๋ง์ thread๋ฅผ spawnํ๋ GCD์ concurrenct queue์ ๋ค๋ฅด๊ฒ Swift์ thread๋ ์์ผ๋ก ๋์๊ฐ ์ ์๋ค.