[WWDC 2021] Meet async/await in Swift
What's new in Swift ์์์ ๋ณด๋ค๊ฐ async/ await ๋ฌธ๋ฒ์ ์๋กญ๊ฒ ์๊ฐํ๋๊ตฐ์ ..!
doc๋ฅผ ํตํด ๋จผ์ ์ ๋ฆฌํ๋ ์ ์ด ์๋๋ฐ ์์์ ๋ณด๋ฉด์ ๋ณต์ตํ๋ ๊ฒธ, ๋ค์ ํ๋ฒ ์ดํด๊ฐ ์ ์๊ฐ actor ๋ถ๋ถ์ ๋ค์ ๊ณต๋ถํด๋ณด๋ ค๊ตฌ ํฉ๋๋ค !!
์๋ ๋น๋์ค์ doc๋ฅผ ๋ณด๋ ๊ฒ์ ๊ฐ๋ ฅํ ์ถ์ฒ๋๋ฆฝ๋๋ค์
https://developer.apple.com/videos/play/wwdc2021/10132
Meet async/await in Swift - WWDC21 - Videos - Apple Developer
Swift now supports asynchronous functions — a pattern commonly known as async/await. Discover how the new syntax can make your code...
developer.apple.com
https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html
Concurrency — The Swift Programming Language (Swift 5.6)
Concurrency Swift has built-in support for writing asynchronous and parallel code in a structured way. Asynchronous code can be suspended and resumed later, although only one piece of the program executes at a time. Suspending and resuming code in your pro
docs.swift.org
์ฐ์ sync์ async์ ์ฐจ์ด์ ๋ํด ์ค๋ช ํฉ๋๋ค.
thread๋ฅผ ์์ฑํ ๋ ์ฒซ๋ฒ์งธ์ ๊ฒฝ์ฐ(sync) ๊ฐ ๋ฉ์๋ ์ํ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํฉ๋๋ค.
ํ์ง๋ง ์๋ thread์ฒ๋ผ prepareThumnail ๋ฉ์๋์ completionHandler๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ด ๋ฉ์๋๊ฐ ๋๋๊ธฐ ์ ๊น์ง ๋ค๋ฅธ ๋ฉ์๋๋ค์ ์์ ๋กญ๊ฒ ์ํํ ์ ์์ฃ . prepareThumnail๋ handler๋ก ๋๋ฌ์์ ์๋ฆด ์ ์๊ณ ์
์ด ์ธ์๋ delegate๋ฅผ ์ฌ์ฉํ ๋น๋๊ธฐ ๋ฑ ๋ค์ํ ๋น๋๊ธฐ API๋ค์ด ์์ต๋๋ค. completionHandler๋ ๋น๋๊ธฐ API ์ค ํ๋์ฃ
๋ชจ๋ ๋น๋๊ธฐ API์ ๋ํด ๊ณตํต์ ์ด ์์ต๋๋ค. ๋ฉ์๋๋ฅผ ํธ์ถํ ๋, thread๋ฅผ ๋ธ๋ฝ์ํค์ง ์๊ณ ๋ค๋ฅธ ์์ ์ ์ํํ๋๋ก ํ๋ ๊ฒ์ ๋๋ค.
์์๋ฅผ ๋ด ์๋ค.
์์ ์์๋ ๊ฐ cell์ ๋ํ image๋ฅผ ํธ์ถํ๋ ์ํฉ์
๋๋ค. UIImage๋ฅผ ๋ฐํํ๊ธฐ๊น์ง์ ๊ณผ์ ์ ํจ๊ป ๋ณด๊ฒ ์ต๋๋ค.
์ฒซ๋ฒ์งธ๋ก url string์ผ๋ก ๋ถํฐ thumbnailURLRequest๋ฅผ ํธ์ถํฉ๋๋ค.
URLRequest๊ฐ ์์ฑ ๋ ๊ฒ์
๋๋ค.
๋๋ฒ์งธ๋ก URLRequest๋ dataTask๋ก๋ถํฐ data๋ฅผ ์ป์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ data๋ก๋ถํฐ UIImage๋ฅผ ์ป์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฐ์ image๋ก๋ถํฐ cell์ thumbnail ๋ฅผ renderํฉ๋๋ค.
๊ฐ๊ฐ์ ์์
์ ์ ๋จ๊ณ์ ์์กดํฉ๋๋ค. ์ฆ ์ ๋จ๊ณ๊ฐ ๋จผ์ ์ํ๋์ด์ผ ์์ ์ด ์ ์ ์ํ ๋ ์ ์๋ค๋ ๊ฒ์ด์ง์ .
์๋ ๋๊ฐ์ ๋ฉ์๋๋ data๋ฅผ ๋น ๋ฅด๊ฒ ๋ฐ์ ์ฌ ์ ์์ต๋๋ค. ํ์ง๋ง ํ์ ํ์๋ ๋ฉ์๋๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ด๋ก๋ํ๊ณ image๋ฅผ ๊ตฌ์ฑํ๋๋ฐ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ๋ฉ์๋์
๋๋ค.
์ด๋ฌํ ์์
๋ค์ ์ํด ๋น๋๊ธฐ API๋ ํ์๋ก ๋ฉ๋๋ค.
์๋ ์ฝ๋๋ ์์ flow๋ฅผ ์์ฑํ ์ฝ๋์
๋๋ค. ํ์ง๋ง ์ฌ๊ธฐ์๋ ๋ฌธ์ ์ ์ด ์์ต๋๋ค.
fetchThumnail ํธ์ถ์๋ fetchThumnail ๋ฉ์๋ ์ํ์ด ๋๋ฌ์๋ ๋ง์ฝ ์คํจํ๋๋ผ๋ ์๋ ค์ง๊ธธ ๋ฐ๋๋๋. ํ์ง๋ง ํ์ฌ guard ์์ ํธ์ถ์๋ฅผ ๋ ๋๋ ์ค์
๋๋ค.
Guard let else return์ ํตํด completion์ fail์ ์ ๋ฌํด์ผ ํ์ง๋ง ๊น๋จน์ ์๋ ์์ฃ . ๊ทธ๋ฌ๋ฉด fetchThumnail์ ์ด์ ๋ํ ์๋ฆผ์ ๋ฐ์ง ๋ชปํ๊ณ ๊ณ์ spin ๋๋ ui๊ฐ ๋ํ๋ ๊ฒ์
๋๋ค. completionHandler์ ๊ตฌํํ์ง ์์์ ๋ฐ๋ผ swift error handling ๋ฉ์ปค๋์ฆ์ ์ด์ฉํ์ง ๋ชปํ ์๋ ์์ต๋๋ค.
ํญ์ swift check๊ฐ ์๋ํ์ฌ ๋ณด์ฅ๋ฐ๊ธธ ๋ฐ๋ผ์ง๋ง swift์์ ์ด๊ฒ์ ๊ฐ์ ํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด result type์ ์ฌ์ฉ ํ ์ ์์ต๋๋ค. ์ ๋ณด๋ค ๋ ์์ ํด์ก์ง๋ง ๋ ์ฝ๋๊ฐ ๋๋ฌ์์ก์ฃ ใ
๊ทธ๋์ async/await ๋ฌธ๋ฒ์ด ํด๊ฒฐํด์ฃผ๊ณ ์ ํ์ํ์์ต๋๋ค.
Async/await๋ฅผ ์ฌ์ฉํ ์ฝ๋๋ฅผ ๋ค์ ๋ด ๋ด
์๋ค.
ํ๋์ ๋ณด์๋ ์ฝ๋๊ฐ ํจ์ฌ ๋ ๊ฐ๋จํด์ก์ฃ ?
๋น๋๊ธฐ ํจ์๋ฅผ ๋ํ๋ ๋ async ํค์๋๋ฅผ ๋ถ์ฌ์ค๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ๋ ์ฝ๋์ await ํค์๋๋ฅผ ๋ถ์ฌ์ค๋๋ค.
await๊ฐ ๋ถ์ ํจ์๋ suspend๊ฐ ์์์ง ๋ชจ๋ฅธ๋ค๋ ๊ฒ์ ๋ํ๋ ๋๋ค. ๋น๋๊ธฐ ํจ์์์ suspend๋ ๋ฌด์์ ์๋ฏธํ ๊น์ ?
fetchThumnail ํจ์๋ฅผ ํธ์ถํ ๋ thumbnailURLRequest๋ฅผ ํธ์ถํ ๊ฒ์ด๊ณ ์ด ์์
์ ํ๋๋ฐ thread๋ ์์ ํ ์ฌ๋ก์กํ ๊ฒ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ thumbnailURLRequest๊ฐ ๋๋๊ณ error๋ฅผ ๋ฐ์ํ๋ ๊ฐ์ ๋ฆฌํดํ๋ ๋ค์ fetchThumbnail๋ก control์ ๋๊ธธ ๊ฒ์
๋๋ค. ์ด๊ฒ์ด ์ผ๋ฐ์ ์ธ ํจ์๊ฐ ์ค๋ ๋ control์ ํฌ๊ธฐํ ์ ์๋ ์ ์ผํ ๋ฐฉ๋ฒ์
๋๋ค.
ํ์ง๋ง ๋น๋๊ธฐ์ ์ธ ํจ์๋ฅผ ํธ์ถํ ๊ฒฝ์ฐ ์กฐ๊ธ ๋ค๋ฆ
๋๋ค. ํจ์๊ฐ ๋๋ ๊ฒฝ์ฐ control์ ๋๊ธฐ์ง๋ง ์ผ๋ฐ ํจ์์ ๋ฌ๋ฆฌ ์์ ํ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ์ค๋ ๋ ์ ์ด๋ฅผ ํฌ๊ธฐํ ์ ์์ต๋๋ค. ์ฆ, suspending์
๋๋ค.
์ผ๋ฐํจ์์ ๊ฐ์ด control์ ์ฐ๋ ๋์๊ฒ ๋๊น๋๋ค.
๊ทธ๋ฆฌ๊ณ suspend๊ฐ ๋๋ฌ์๋ ๋ค์ ์ฌ๊ฐํ๋๋ก ํฉ๋๋ค.
ํ์ง๋ง await๋ฅผ ์ด๋ค๊ณ ํด์ ํจ์๊ฐ ๋ฐ๋์ suspend ๋๋ค๋ ์๋ฏธ๋ ์๋๋๋ค.
๋ ๋ค๋ฅธ ์์๋ Doc์์ ๊ฐ์ ธ์๋ดค์ต๋๋ค.
let photoNames = await listPhotos(inGallery: “Summer Vacation”)
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
let photo = await downloadPhoto(named: name)
show(photo)
listPhotos(inGallery:)์ downloadPhoto(named:) ํจ์ ๋ชจ๋ ๋คํธ์ํฌ ์์ฒญ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ์๋ฃํ๋๋ฐ ์ค๋ ์๊ฐ์ด ์์๋ฉ๋๋ค. async๋ฅผ ์ฌ์ฉํด ๋น๋๊ธฐ๋ก ๋ง๋ค๋ฉด ์ด ํจ์๊ฐ ์ค๋น๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋๋จธ์ง ์ฝ๋๊ฐ ๊ณ์ ์คํ๋ ์ ์์ต๋๋ค.
์๋๋ ์์ ์์ ์ ๋ํด ๊ฐ๋ฅํ ์คํ ์์ ์ค ํ๋์
๋๋ค.
1. ์ฝ๋๋ ์ฒซ๋ฒ์งธ ๋ผ์ธ์์ ์์๋๊ณ ์ฒซ๋ฒ์งธ await ์ ๋ง๋ฉ๋๋ค. listPhotos(inGallery:) ํจ์๋ฅผ ํธ์ถํ๊ณ ํด๋น ํจ์๊ฐ return ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ์คํ์ ์ผ์์ค๋จํฉ๋๋ค.
2. ์ด ์ฝ๋์ ์คํ์ด ์ผ์์ค๋จ๋๋ ๋์, ๊ฐ์ ํ๋ก๊ทธ๋จ ์์ ์๋ ๋ค๋ฅธ concurrent code ๊ฐ ์คํ๋ฉ๋๋ค.
์๋ฅผ๋ค์ด long-running background task๊ฐ ํฌํ ๊ฐค๋ฌ๋ฆฌ์ ๋ชฉ๋ก์ ๊ณ์ ์
๋ฐ์ดํธ ํ๊ณ ์์ ์ ์๊ฒ ์ต๋๋ค.
์ task ๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ค์ suspension point (await์ด ํ์๋)๋ฅผ ๋ง๋ ๋ ๊น์ง ์คํ๋ ๊ฒ ์
๋๋ค.
3. listPhotos(inGallery:) ๊ฐ return์ ํ ํ์, ์ฝ๋๋ ์ด ์์ ๋ถํฐ ์คํ์ ๊ณ์ํฉ๋๋ค. photoNames ํ๋กํผํฐ์ ๋ฐํ๋ ๊ฐ์ ํ ๋นํฉ๋๋ค.
4. sortedNames๊ณผ name์ ์ ์ํ๋ ์ฝ๋๋ ์ผ๋ฐ์ ์ธ synchronous code ์
๋๋ค. ์ด ๋ผ์ธ๋ค์๋ await ํ์๋ ๊ณณ์ด ์์ผ๋ฏ๋ก ๊ฐ๋ฅํ suspension points ๊ฐ ์์ต๋๋ค.
5. downloadPhoto(named:) function ์ ์ฝํ ๋, await ์ด ํ์๋์์ต๋๋ค. ์ด ์ฝ๋๋ ๋ค๋ฅธ concurrent code ํํ
์คํ๋ ๊ธฐํ๋ฅผ ์ฃผ๋ฉด์ function์ด return ๋ ๋ ๊น์ง ์คํ์ ๋ค์ ์ค๋จํฉ๋๋ค.
6. downloadPhoto(named:) ๊ฐ return ๋ ํ์, return value๊ฐ photo ํ๋กํผํฐ์ ํ ๋น๋๊ณ photo๋ฅผ argument๋ก pass ํ๋ฉฐ show(_:) ๋ฅผ ์ฝํฉ๋๋ค.
์ฝ๋์์ possible suspension points ๋ await ์ผ๋ก marked ๋๊ณ
์ด๋ asynchronous function์ด return๋ ๋ ๊น์ง current piece of code๊ฐ ์คํ์ด ์ค์ง๋ ์ ์์์ ๋ํ๋
๋๋ค.
์ด๊ฒ์ yielding the thread (์ค๋ ๋ ์๋ณด)๋ผ ํ ์ ์๋๋ฐ ์๋ํ๋ฉด ํ๋ฉด ๋ค์์ ํ์ฌ ์ค๋ ๋์์ ์ฝ๋์ ์คํ์ ์ค๋จํ๊ณ ํ์ฌ ์ค๋ ๋ ๋ด ๋ค๋ฅธ ์ฝ๋๋ฅผ ๋๋ฆด ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. await๊ฐ ๋ถ์ ์ฝ๋๋ ์ค์ง๋ ์ ์๊ธฐ ๋๋ฌธ์ ํ๋ก๊ทธ๋จ ๋ด ์๋์ ๊ฐ์ ํ๋ก๊ทธ๋จ์ ํน์ ์์น์์๋ง ๋ค๋ฅธ ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
์ด๋ for ๋ฌธ์์๋ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
Asynchronous Sequences
์ ์นํฐ์์ listPhotos(inGallery:) ํจ์๋ ์ ์ฒด ๋ฐฐ์ด์ด ์ค๋น๊ฐ ๋์์๋ ์ด๋ฅผ ํ๋ฒ์ ๋ฆฌํดํ์ต๋๋ค.
๋ ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ๋น๋๊ธฐ ์ํ์ค๋ฅผ ์ฌ์ฉํ์ฌ ํ ๋ฒ์ ์ปฌ๋ ์
์ ํ ์์๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์
๋๋ค. ๋น๋๊ธฐ ์ํ์ค์ ๋ํ ๋ฐ๋ณต์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
import Foundation
let handle = FileHandle.standardInput
for try await line in handle.bytes.lines {
print(line)
}
์ผ๋ฐ์ ์ธ for-in ๋ฃจํ๋ฅผ ์ฌ์ฉํ๋ ๋์ ์ ์์ ์์๋ for๊ณผ await๋ฅผ ๊ฐ์ด ์ฌ์ฉํฉ๋๋ค. ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ ๋์ ๋น์ทํ๊ฒ await๋ฅผ ์ฐ๋๊ฒ์ ์ค์ง์ ์ด ๋ ์ ์์์ ๋ํ๋ ๋๋ค. for -await -in ๋ฃจํ๋ ์ ์ฌ์ ์ผ๋ก ๊ฐ ๋ฐ๋ณต์ ์์์์ ๋ค์ ์์๊ฐ ์ด์ฉ๊ฐ๋ฅํด์ง๋๊น์ง ์คํ์ ์ค์งํฉ๋๋ค. For-in ๋ฃจํ๊ฐ Sequence ํ๋กํ ์ฝ์ ์์ํด์ผ ํ๋๊ฒ ์ฒ๋ผ for -await -in ๋ฃจํ๋ AsyncSequence๋ฅผ ์์ํด์ผ ํฉ๋๋ค.
await๋ก suspend๋์์๋ ์๋ ์ฝ๋๋ transaction์ผ๋ก ์คํ๋์ง ์์ต๋๋ค. ํ์ง๋ง ์๋ ์ฝ๋๋ ๋ค๋ฅธ ์ค๋ ๋์์ ์ํ๋ ์ ์์ต๋๋ค. ์ด์ ๋ํ ์ด์๋ https://developer.apple.com/videos/play/wwdc2021/10133๋ฅผ ์ฐธ๊ณ ํ์ธ์
Protect mutable state with Swift actors - WWDC21 - Videos - Apple Developer
Data races occur when two separate threads concurrently access the same mutable state. They are trivial to construct, but are notoriously...
developer.apple.com
Summary
1. async ํจ์๋ฅผ suspend ํฉ๋๋ค.
2. await async ํจ์๊ฐ suspend ๋ ์ ์์์ ํ์ํฉ๋๋ค.
3. suspend๋๋ ๋์ ํด๋น thread๋ ๋ค๋ฅธ ์์
์ ์์ ๋กญ๊ฒ ์ํํฉ๋๋ค.
4. async ํจ์๊ฐ resume๋๋ฉด async ํจ์๋ก๋ถํฐ ๊ฒฐ๊ณผ๊ฐ ๋ฐํ๋ฉ๋๋ค.
๋ค๋ฅธ ๊ณณ์์ async/await๋ฅผ ์ฌ์ฉ ํ๋ ์์๋ฅผ ๋ด๋ด
์๋ค.
Testing code์
๋๋ค.
thumnailView๋ฅผ ๊ตฌ์ฑํ๊ณ ์๋ image ์ฝ๋์ ๋๋ค. ๊ฐ ์์ด๋๋ฅผ ํตํด ์ด๋ฏธ์ง๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
์ด ๋ถ๋ถ์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ณํ์ ์๋์ ๊ฐ์ต๋๋ค. ํ์ง๋ง complier ์๋ฌ๊ฐ ๋ฐ์ํ๋๋ฐ์ onApear ํจ์๋ sync ํด๋ก์ ๋ก async ํค์๋๋ฅผ ๋ถ์ผ ์ ์์ต๋๋ค.
์ด์ ๋ํ ํด๊ฒฐ์ฑ
์ผ๋ก async ํจ์์ธ Task๋ฅผ ์ฌ์ฉํฉ๋๋ค.
async Task๋ ํด๋ก์ ์ ์์
์ ํจํค์งํํ๊ณ global DispatchQueue์ ๋น๋๊ธฐ ํจ์์ ๊ฐ์ด ์ฌ์ฉ ๊ฐ๋ฅํ next ์ค๋ ๋์์ ์ฆ์ ์คํํ ์ ์๋๋ก ์์คํ
์ผ๋ก ๋ณด๋
๋๋ค.
์ด๊ฒ์ ์ฃผ์ํ ์ด์ ์ async ์ฝ๋๊ฐ sync context์์์ ํธ์ถ๋ ์ ์๋ค๋ ์ ์
๋๋ค.
๋๋ core data์์ data๋ฅผ handlingํ๋ ์์์์๋ ์ญ์
Core data์์ completion Handler๋ก ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ฅผ getPersistentPosts์ ๋ฆฌํดํ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ continuation์ด๋ผ๊ณ ํฉ๋๋ค.
๋ค์ ์ฝ๋๋ก ๋ด ๋ด ์๋ค. withCheckedThrowingContinuation ํจ์๋ฅผ ํตํด continuation์ผ๋ก ๋ฐ์์จ ๊ฐ์ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
continuation์ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด์ง๋ง ์ฃผ์์ฌํญ(contract)๊ฐ ์์ต๋๋ค.
resum์ ๋ชจ๋ path์ ํ๋ฒ ๊ผญ ์ฌ์ฉ๋์ด์ผ ํฉ๋๋ค. ํ์ง๋ง ํ path์ ์ฌ๋ฌ๋ฒ ํธ์ถ๋ ๊ฒฝ์ฐ ๋ฐํ์ ์๋ฌ๋ฅผ ํธ์ถํ ๊ฒ์
๋๋ค.
Task์ Action์ ๋ค์ ์ธ์ ์ ๋ณด๊ณ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค .. Concurrency ์ธ์ ์ด ์ ๋ง ๋ง๋๊ตฐ์ ๋ค ํ๋ ํ๋ ์ฝ์ด ๋ด์ผ๊ฒ ์ต๋๋ค ..!