2022.10.11 (ํ)
ps) ์ด ๊ธ์ ์์ฑํ๋ค๊ฐ swift-book์์ swift ๋ฌธ๋ฒ ์ค๋ฅ ๋ฐ๊ฒฌํด์ PR๋ ๋ฆผ. ๐ ๐
Swfit์ธ์ด๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ์ํ ์์
์ ๋์์ฃผ๋๋ก ์ค๊ฒ๋์์ต๋๋ค. ๊ธฐ์กด์ Swift์ธ์ด์์๋ ๋น๋๊ธฐ์์
์ completion handler๋ฅผ ์ด์ฉํ์ฌ ์ฒ๋ฆฌํ์ต๋๋ค. ํ์ง๋ง ์ด๋ ๋จ์ ์ด ๋ช๊ฐ์ง๊ฐ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ์ด๋ฏธ์ง์ด๋ฆ ๋ฆฌ์คํธ๋ฅผ ๋ถ๋ฌ์ค๊ณ ์ฒซ๋ฒ์งธ ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ก๋ํ ํ, ํ๋ฉด์ ๋ณด์ฌ์ฃผ๋ ์ํฉ์ด๋ผ๋ฉด,
listPhotos(inGallery: "Summer Vacation") { photoNames in
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
downloadPhoto(named: name) { photo in
show(photo)
}
}
์ด๋ฏธ ์ค์ฒฉ ํด๋ก์ ๋ฅผ ํตํด ์ฝ๊ธฐ ์ด๋ ค์ด ์ฝ๋๊ฐ ๋ ๋ฟ๋๋ฌ, ๋น๋๊ธฐ ์์
์ด ๋ ์ถ๊ฐ๋๋ค๋ฉด ๋ ์ค์ฒฉ๋์ด ๋ณต์กํด์ง ๊ฒ๋๋ค.
๊ทธ๋ฆฌ๊ณ ํด๋น ์์
์ด ์ด๋ค ์ค๋ ๋์์ ์์
๋ ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ UI์ ๊ด๋ จ๋ ์์
์ DispatchQueue.main
์ผ๋ก ๊ฐ์ธ์ฃผ์ด์ผ ํฉ๋๋ค.
listPhotos(inGallery: "Summer Vacation") { photoNames in
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
downloadPhoto(named: name) { photo in
DispatchQueme.main { // โ
show(photo)
}
}
}
ํ๊ฐ์ง ๋, ํด๋น ์์
์ด ๋๋ฒ ์ฐ์ด๊ธฐ ๋๋ฌธ์ ํจ์ํ์์ผ์ผ ํ ๊ฒฝ์ฐ, ๋ชจ๋ ์ํฉ(์๋ฌ๊ฐ ๋ ๊ฒฝ์ฐ)์์ completion handler๋ฅผ ๋ฐํํ๋์ง ๊ณ ๋ คํด์ผํฉ๋๋ค. ์๋ ์ฝ๋๋ ์๋ฌ์ฒ๋ฆฌ๋ฅผ ๊ณ ๋ คํ์ง ์์์ต๋๋ค. ๋ง์ผ ๊ณ ๋ คํ๋ค๋ฉด listPhotos
, downloadPhoto
์ completion handler๊ฐ Result
ํ์
์ผ๋ก ๋ฆฌํด๋๊ฒ ์์ ํ๊ณ ํด๋น ์ค๋ฅ์ ๋ง๊ฒ showPhoto
์ completion handler๋ฅผ ๋ฐํํด์ฃผ์ด์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์ ๊ฐ๋ฐ์์ ์ค์๋ก ์ธํด ๋ฐ์ํ ์ ์๋ ์ค๋ฅ๊ฐ ๋ค์ ์๊น๋๋ค.
func showPhoto(completion: @escpaing ((UIImage) -> Void)) {
listPhotos(inGallery: "Summer Vacation") { photoNames in
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
downloadPhoto(named: name) { photo in
completion(photo) // โ
}
}
}
๋ง์ง๋ง์ผ๋ก, retain cycle์ด ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. ํด๋ก์ ๋ด๋ถ์ self ํ๋กํผํฐ๋ฅผ ์ด์ฉํด์ ์ ๊ทผํ ๋ ์ด๋ ์ฐ๋ ๋์์ ์ ๊ทผํ๊ฒ ๋ ๊ฒ์ธ์ง ๊ณ ๋ คํด์ผ ํฉ๋๋ค. escaping closure์ ๊ฒฝ์ฐ ์ผ๋ฐ ํด๋ก์ ์๋ ๋ค๋ฅด๊ฒ, ๋ ํผ๋ฐ์ค ์นด์ดํ
์ด ๋๊ธฐ ๋๋ฌธ์ ์ถ๊ฐ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ํด์ฃผ์ด์ผํฉ๋๋ค. [weak self]
๋ฅผ ํตํด ๋ ํผ๋ฐ์ค ์นด์ดํ
์ ์ ๊ฑฐํ์ฌ retain cycle ๋ฐ์์ ์๋ฐฉํด์ผ ํ์ง๋ง, ๋ฌด๋ถ๋ณํ [weak self]
์ ์ฌ์ฉ์ ๋ฐํ์ ์ค๋ฒํค๋๋ฅผ ์ผ์ผํค๊ณ , ์ต์
๋์ ์ฒดํฌํด์ค์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์๊น๋๋ค.
listPhotos(inGallery: "Summer Vacation") { [weak self] photoNames in // โ
let sortedNames = self?.photoNames.sorted() ?? [defaultImageName] // โ
let name = sortedNames[0]
downloadPhoto(named: name) { [weak self] photo in // โ
DispatchQueme.main { [weak self] // โ
self?.show(photo) // โ
}
}
}
completion handler์ ๋จ์ ์ ์ ๋ฆฌํ๋ฉด ์๋์ ๊ฐ์ ๊ฒ๋ค์ด ์์ต๋๋ค.
- ์ค์ฒฉํด๋ก์ ๋ก ์ธํด ์ฝ๋์ ๊ฐ๋ ์ฑ ์ ํ
- ๊ฐ๋ฐ์์ ์ค์๋ก ์ธํด ๋ฐ์ํ ์ ์๋ ๋ค์์ ์ค๋ฅ ์ํฉ ์กด์ฌ
- self capture -> retain cycle
- ์๋ฌ ํธ๋ค๋ง
๋น๋๊ธฐ ํจ์(asynchrounous function/method)๋ ์คํ ๋์ค ๋ฉ์ถ ์ ์๋ ํน๋ณํ ์ข ๋ฅ์ ํจ์์ ๋๋ค. ํ์ ์ ๋ฐํํ๊ฑฐ๋, ์๋ฌ๋ฅผ ๋์ง๊ฑฐ๋, ์์ ๋ฐํํ์ง ์๋ ๊ธฐ์กด ํจ์์๋ ์กฐ๊ธ ๋ค๋ฆ ๋๋ค. 3๊ฐ์ง ์ค ํ๋๋ฅผ ํ๊ธด ํ์ง๋ง, ์์ ์ค๊ฐ์ ๋ฉ์ถ ์ ์์ต๋๋ค.
๋น๋๊ธฐ ํจ์๋ฅผ ์์ฑํ ๋๋ ํ๋ผ๋ฏธํฐ ๋ค์ async
ํค์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ์ ๋ฐํํ ๊ฒฝ์ฐ์ ํ์
์ ํ์ดํ(->) ๋ค์ ์์ฑํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ค๋ฅ๋ฅผ ๋์ง ์ ์๋ ๋น๋๊ธฐ ํจ์์ผ ๊ฒฝ์ฐ์ async throws
๋ก ์์ฑํ ์ ์์ต๋๋ค.
func listPhotos(inGallery name: String) async -> [String] {
let result = // ... some asynchronous networking code ...
return result
}
ํจ์์ ์๋์ ์ค๊ฐ์ ๋ฉ์ถ๋ ํค์๋๋ await
์
๋๋ค.
let photoNames = await listPhotos(inGallery: "Summer Vacation") // โ๏ธ
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
let photo = await downloadPhoto(named: name) // โ๏ธ
show(photo)
completion handler์ ์์ ์ฝ๋๋ฅผ async/await์ ์ด์ฉํ์ฌ ์ฝ๋๋ฅผ ์์ฑํด๋ณด๋ฉด ์์ ๊ฐ์ต๋๋ค. ์ฌ์ง๋ค์ ์ด๋ฆ์ ๋ถ๋ฌ์ค๋ ์์
์ด ์์๋๋ฉด ํด๋น ์ค์์ ํจ์๋ ๋ฉ์ถ๊ณ , ์์
์ ๋งก๊ณ ์๋ ์ค๋ ๋๋ ๋ค๋ฅธ ์์
์ ์คํํฉ๋๋ค. ๋ชจ๋ ๋ถ๋ฌ์์ก๋ค๋ฉด ํด๋ค์ ์ค๋ถํฐ ๋ค์ ์์
์ ์์ํ์ฌ photoNames
์ ๊ฒฐ๊ณผ๋ฅผ ํ ๋นํ๊ณ ๋ค์ ์ค๋ก ๋์ด๊ฐ๋๋ค. await
ํค์๋๊ฐ ๋ถ์ด์๋ค๋ฉด, ์์ ๊ฐ์ด ๋์ํ๊ณ ์๋๋ผ๋ฉด ์ผ๋ฐ ํจ์์ฒ๋ผ ๋๊ธฐ์ ์ผ๋ก ๋์ํฉ๋๋ค.
await
ํค์๋๊ฐ ํ์๋ ์ฝ๋๋ ํด๋น ์์
์ด ์๋ฃ๋์ด ๋ฐํ๋ ๋๊น์ง ๋ค์ ์์
์คํ์ ๋ฉ์ถ๊ณ , ๊ธฐ๋ค๋ฆฌ๋ผ๋ ์๋ฏธ์
๋๋ค. ์ด ๋ป์ yielding the thread๋ผ๊ณ ๋ ํฉ๋๋ค. ์๋ํ๋ฉด Swift๊ฐ ์์
์ด ๋์๋๊ณ ์๋ ์ค๋ ๋์์ ํด๋น ์์
์ ๋ฉ์ถ๊ณ ๋ค๋ฅธ ์ฝ๋๋ฅผ ๋์์ํค๊ธฐ ๋๋ฌธ์
๋๋ค. await
์์๋ง ์คํ์ ๋ฉ์ถ ์ ์๊ธฐ ๋๋ฌธ์ ํน์ ๋ถ๋ถ์์๋ง ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
- ๋น๋๊ธฐ ๋ฉ์๋ ๋ฐ ํ๋กํผํฐ ๋ด๋ถ
@main
ํค์๋๋ก ํ์๋ structure, main, enum- Unstructured child task ๋ด๋ถ (์๋์์ ์ค๋ช )
listPhotos(inGallery:)
ํจ์๋ ๋ชจ๋ ์ด๋ฏธ์ง ๋ฆฌ์คํธ๋ฅผ ๋ถ๋ฌ์จ ๋ค์์ ๋ค์ ์์
์ด ์คํ๋ฉ๋๋ค. Swift์ ๋น๋๊ธฐ ์คํธ๋ฆผ์ ์ด์ฉํ๋ฉด ์ด๋ฏธ์ง ๋ฆฌ์คํธ์ ๊ฐ์ด collectionํ์
์ธ ๊ฒฝ์ฐ ํ๋์ element๋ง ๋ถ๋ฌ์ฌ ๋๊น์ง๋ง ๊ธฐ๋ค๋ฆฌ๊ฒ ํ ์ ์์ต๋๋ค.
import Foundation
let handle = FileHandle.standardInput
for try await line in handle.bytes.lines {
print(line)
}
for - await - in
๊ตฌ๋ฌธ์ ํตํด ๊ฐ iteration๋ง๋ค ๊ฐ์ด ์ค๋น๋ ๋๊น์ง ๋ฉ์ถ๊ณ ๊ฐ์ด ์ค๋น๋๋ฉด ๋ค์ ๋์ํ๊ฒ๋ํ ์ ์์ต๋๋ค. ๋ง์ฝ iteration์ด 10๋ฒ์ด๋ผ๋ฉด ์ด 10๋ฒ ๋ฉ์ถ ๊ฒ์
๋๋ค. AsyncSequence
ํ๋กํ ์ฝ์ ์ฑํํ ํ์
์ด๋ผ๋ฉด for-await-in
๊ตฌ๋ฌธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
await
ํค์๋๋ก ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ ์ค์ง ํ๋ฒ์ ํ๋์
๋๋ค. ์ฆ, caller(๋น๋๊ธฐํจ์๋ฅผ ๋ถ๋ฅด๋ ํจ์)๊ฐ ๋น๋๊ธฐ ํจ์๋ฅผ ๋ถ๋ฅด๊ณ ์๋ค๋ฉด ๋ค์ ์ฝ๋๋ก ๋์ด๊ฐ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ด๋ฏธ์ง 3๊ฐ๋ฅผ ๋์์ ๋ค์ด๋ฐ๋ ์ํฉ์ด๋ฆฌ๊ณ ํฉ์๋ค.
let firstPhoto = await downloadPhoto(named: photoNames[0])
let secondPhoto = await downloadPhoto(named: photoNames[1])
let thirdPhoto = await downloadPhoto(named: photoNames[2])
let photos = [firstPhoto, secondPhoto, thirdPhoto]
show(photos)
์์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ์ฒซ๋ฒ์งธ ์ด๋ฏธ์ง๊ฐ ๋ค์ด๋ก๋๋ ํ, ๋๋ฒ์งธ ์ด๋ฏธ์ง๊ฐ ๋ค์ด๋ก๋๋๊ณ , ๋๋ฒ์งธ ์ด๋ฏธ์ง๊ฐ ๋ค์ด๋ก๋๋ ํ ์ธ๋ฒ์งธ ์ด๋ฏธ์ง๊ฐ ๋ค์ด๋ก๋๋ฉ๋๋ค. ๋ชจ๋ ์์ฐจ์ ์ผ๋ก ๋ค์ด๋ก๋๊ฐ ์งํ๋์ง๋ง, ์ด๋ฏธ์ง ๋ค์ด๋ก๋๋ ๋ชจ๋ ๋ ๋ฆฝ์ ์ผ๋ก, ์ฆ ๋ณ๋ ฌ์ ์ผ๋ก ์งํ๋์ด์ผํ๋ ์์ ์ ๋๋ค.
๋น๋๊ธฐ ํจ์๋ฅผ ๋ณ๋ ฌ์ ์ผ๋ก ํธ์ถํ๊ธฐ ์ํด์๋ async
ํค์๋๋ฅผ let
ํค์๋ ์์ ๋ถ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋น ์์๋ฅผ ์ฌ์ฉํ ๋ await
ํค์๋๋ฅผ ๋ถ์
๋๋ค.
async let firstPhoto = downloadPhoto(named: photoNames[0])
async let secondPhoto = downloadPhoto(named: photoNames[1])
async let thirdPhoto = downloadPhoto(named: photoNames[2])
let photos = await [firstPhoto, secondPhoto, thirdPhoto]
show(photos)
์์คํ
์์์ด ์ถฉ๋ถํ๋ค๋ฉด, ์ด๋ฏธ์ง 3๊ฐ ๋ค์ด๋ก๋ ์์
์ด ๋์์ ์งํ๋ฉ๋๋ค. ๋ค์ด๋ก๋ํ๋ ๋น๋๊ธฐํจ์๋ก ์ธํ ์คํ์ด ๋ฉ์ถ์ง ์๊ธฐ ๋๋ฌธ์ await
ํค์๋๋ก ํ์๋์ง ์์ต๋๋ค. ๋์ ์, photos ์์๊ฐ ํ ๋น๋ ๋, ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ๊ณ 3๊ฐ์ ๋น๋๊ธฐ ํจ์๊ฐ ๋ชจ๋ ์๋ฃ๋ ๋๊น์ง caller์ ์คํ์ด ์ค๋จ๋ฉ๋๋ค.
await๊ณผ async-let ์ ๋ฆฌ
๊ณตํต์ | ์ฐจ์ด์ | |
---|---|---|
await | 1. caller๋ ์ค๋จ๋๊ณ ๋ค๋ฅธ ์ฝ๋๊ฐ ์คํ๋๋ค. 2. ๋ชจ๋ await ํค์๋๋ฅผ ํตํด ์คํ ์ค์ธ ์์
์ด ์ค๋จ๋๋ค. |
1. ๋ค์ ์ฝ๋๊ฐ ๋น๋๊ธฐํจ์์ ๊ฒฐ๊ณผ์ ์์กดํ๊ณ ์์ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค. 2. ์์ฐจ์ ์งํ |
async-let | ์์ ๊ฐ์ | 1. ๋ค์ ์ฝ๋๊ฐ ๋น๋๊ธฐํจ์์ ๊ฒฐ๊ณผ์ ์์กดํ๊ณ ์์ง ์์ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค. 2. ๋ณ๋ ฌ์ ์งํ |
๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํด์ผํ ์์
์ ์ฒ๋ฆฌํ ๋ ์คํ๋๋ ์์
์ ๋จ์์
๋๋ค. ๋ชจ๋ ๋น๋๊ธฐ ์ฝ๋๋ค์ task์ ์ผ๋ถ๋ก์ ์๋๋ฉ๋๋ค. ์์์ ์ค๋ช
ํ async-let
ํค์๋๋ ์๋์ผ๋ก ์์ Task๋ฅผ ์์ฑํ์ฌ ์ฒ๋ฆฌํฉ๋๋ค. Swift๋ ๊ฐ๋ฐ์๊ฐ ์ง์ task group์ ์์ฑํ๊ณ ์์ Task๋ฅผ ์ฝ์
ํ ์ ์๋๋ก ํ์ฌ Task๋ณ ์ฐ์ ์์์ cancellation๋ฅผ ์ปจํธ๋กคํ ์ ์๊ฒ ํด์ค๋๋ค.
Task๋ ๊ณ์ธต์ (hierarchy)์ผ๋ก ์ ๋ฆฌ๋ฉ๋๋ค. Task Group๋ด์ ๊ฐ Task๋ ๊ฐ์ ๋ถ๋ชจ Task๋ฅผ ๊ฐ์ง๊ณ , ๊ฐ Task๋ ์์ Task๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. Task์ Task Group์ด๋ผ๋ ๋ช
์์ ์ธ ๊ด๊ณ๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ structured concurrency๋ผ๊ณ ๋ ๋ถ๋ฆ
๋๋ค. Task์ Task Group์ ์ฌ์ฉํจ์ผ๋ก์, ๊ฐ๋ฐ์์ ์ค์๊ฐ ์กฐ๊ธ ์๊ธธ์ง๋ผ๋, ๋ช
์์ ์ธ ๊ด๊ณ๋ฅผ ํตํด Swift๋ ์ปดํ์ผ ํ์์ ์ค๋ฅ๋ฅผ ์ฐพ์๋ผ ์ ์๊ณ , ๋ถ๋ชจ Cancellation -> ์์ Cancellation
์ ๊ฐ์ ์์
๋ ํ ์ ์์ต๋๋ค.
await withTaskGroup(of: Data.self) { taskGroup in
let photoNames = await listPhotos(inGallery: "Summer Vacation")
for name in photoNames {
taskGroup.addTask { await downloadPhoto(named: name) }
}
}
Unstructured Concurrency
๋ถ๋ชจ Task๋ฅผ ๊ฐ์ง์ง ์๋ Task๋ ์กด์ฌํ๋๋ฐ ์ด๋ฅผ Unstructured Concurrency๋ผ๊ณ ํฉ๋๋ค. ๊ฐ๋ฐ์๊ฐ Task๋ฅผ ์ ๋ถ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐ์์ ์ค์๋ก ์ธํด ๋ฐ์ํ ์ค๋ฅ๋ค์ด ์๊น๋๋ค. ํ์ฌ actor์์ unstructured concurreny task๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ Task.init(priority: operation:)
initializer์
๋๋ค. ํ์ฌ actor์์ ์์ฑํ์ง ์๊ณ ๋ค๋ฅธ actor๋ก ์์ฑํ๋ ๋ฐฉ๋ฒ์ Task.detached(priority:operation:)
ํด๋์ค ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ์
๋๋ค. (detatched task๋ผ๊ณ ์๋ ค์ ธ์์) ์ด ๋๊ฐ์ง ๋ฉ์๋๋ ๊ฐ๋ฐ์๊ฐ ์ํธ์์ฉ(๋น๋๊ธฐ ๋ฉ์๋ ๊ฒฐ๊ณผ ๊ธฐ๋ค๋ฆฌ๊ธฐ, ์ทจ์ํ๊ธฐ)ํ ์ ์๋ Task๋ฅผ ๋ฐํํฉ๋๋ค. (Actor๋ ๋ฐ์์!)
let newPhoto = // ... some photo data ...
let handle = Task {
return await add(newPhoto, toGalleryNamed: "Spring Adventures")
}
let result = await handle.value
Spring Adeventures๋ผ๋ ๊ฐค๋ฌ๋ฆฌ์ ์๋ก์ด ์ฌ์ง์ ์ถ๊ฐํ๋ Task๋ฅผ ์์ฑํ๋ ์์ ์ ๋๋ค. Task์ ๋ํด์ ๋ฌธ์๋ฅผ ๋ณด๋ฉด์ ๋ ์์ธํ ๊ณต๋ถํด์ผ๊ฒ ์ต๋๋ค.
Task Cancellation
Swift ๋์์ฑ์ ๊ณตํต์ cancellation ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค. ๊ฐ Task๋ ์ ์ ํ ์คํ์์ ์์ ์ทจ์๋์๋์ง ์ฒดํฌํ๊ณ ์ ์ ํ ๋ฐฉ์์ผ๋ก ์ทจ์์ ์๋ตํฉ๋๋ค. ์ฌ๊ธฐ์ ์ ์ ํ ์คํ์์ ์ด๋ ์๋์ ์ํฉ์ ๋๋ค.
CancellationError
์ ๊ฐ์ ์๋ฌ๋ฅผ ๋์ง ๋- nil์ด๋ ๋น collection์ ๋ฐํํ ๋
- ๋ถ๋ถ์ ์ผ๋ก ์๋ฃ๋ ์์ ์ ๋ฐํํ ๋
cancellation
์ ์ฒดํฌํ๊ธฐ ์ํด์๋ 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. Task๊ฐ ์ทจ์๋ ๋ CancellationError
๋ฅผ ๋์ง๋ Task.checkCancellation()
์ ํธ์ถํ๊ฑฐ๋ Task.isCancelled
์ ๊ฐ์ ์ฒดํฌํด์ ์ทจ์๋ ์ํฉ์ ํธ๋ค๋งํ๋ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด ๊ฐค๋ฌ๋ฆฌ์์ ์ฌ์ง์ ๋ค์ด๋ก๋ํ๋ Task์์๋ ๋ถ๋ถ์ ์ธ ๋ค์ด๋ก๋๋ฅผ ์ ๊ฑฐํ๊ณ ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ๋ซ๋ ์์
์ด ์์ ๊ฒ์
๋๋ค.
์ด์ ๊ฐ๋ฐ์๋ค์ ํ๋ก๊ทธ๋จ์ ๋์์ ์๋ํ ์ ์๋ Task ์กฐ๊ฐ์ผ๋ก ์ชผ๊ฐค ์ ์์ต๋๋ค. ์ด Task ์กฐ๊ฐ๋ค์ ๊ฐ๊ฐ ๋ ๋ฆฝ๋์ด ๋์์ ์๋ํ์ฌ ์๋ก๋ก๋ถํฐ ์์ ํ์ง๋ง, Task ์ฌ์ด์์ ๊ณต์ ๋๋ ์์๋ค์ ์์ ํ์ง ์์ต๋๋ค. Actor๋ ๋์์ฑ ์ฝ๋๋ก๋ถํฐ ๊ณต์ ์์์ ์์ ํ๊ฒ ๊ด๋ฆฌํด์ค๋๋ค.
Actor๋ ๋ ํผ๋ฐ์ค ํ์ ์ ๋๋ค. ํ์ง๋ง ํด๋์ค์ ๋ฌ๋ฆฌ, ํ๋ฒ์ ํ๋์ Task๋ง์ด State์ ์ ๊ทผํ์ฌ ๋ณ๊ฒฝํ ์ ์์ด ์ฌ๋ฌ๊ฐ์ Task๋ค๋ก๋ถํฐ ํ๋์ actor ์ธ์คํด์ค์ ์ ๊ทผํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ์๋ฅผ๋ค์ด, ๊ธฐ์จ์ ๊ธฐ๋กํ๋ actor๊ฐ ์๋ค๊ณ ํฉ์๋ค.
actor TemperatureLogger {
let label: String
var measurements: [Int]
private(set) var max: Int
init(label: String, measurement: Int) {
self.label = label
self.measurements = [measurement]
self.max = measurement
}
}
TemperatureLogger
actor๋ ์ธ๋ถ์์ ์ ๊ทผ ๊ฐ๋ฅํ ํ๋กํผํฐ label
๊ณผ measurements
๋ฅผ ๊ฐ์ง๊ณ ์๊ณ max
์ ๊ฐ์ด actor ๋ด๋ถ์์๋ง ์ ๊ทผํ์ฌ ์์ ๊ฐ๋ฅํ ํ๋กํผํฐ๊ฐ ์์ต๋๋ค.
์ด์ class์ structure๊ณผ ๊ฐ์ initializer๋ฅผ ์ด์ฉํด actor ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค. Actor์ ํ๋กํผํฐ์ ๋ฉ์๋์ ์ ๊ทผํ ๋, await
ํค์๋๋ฅผ ์ด์ฉํ์ฌ ์ ์งํ ํฌ์ธํธ๋ฅผ ํ์ํฉ๋๋ค.
let logger = TemperatureLogger(label: "Outdoors", measurement: 25)
print(await logger.max)
// Prints "25"
์์ ์์๋, logger.max
๋ถ๋ถ์ ์ ์งํ๋๋ก ํ์ต๋๋ค. ์๋ํ๋ฉด actor๋ ํ๋ฒ์ ํ๋์ Task๋ง์ด ์ด ๊ฐ์ ์ ๊ทผ๊ฐ๋ฅํ๋๋ก ํด์ผํ๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ง์ฝ ๋ค๋ฅธ Task๊ฐ ์ด๋ฏธ logger์ ์ํธ์์ฉํ๊ณ ์๋ค๋ฉด, ์ด ์ฝ๋๋ ํ๋กํผํฐ์ ์ ๊ทผ ๊ฐ๋ฅํ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
๋ฐ๋๋ก, Actor๋ด๋ถ์ ์ฝ๋๋ await
ํค์๋๋ฅผ ์ฌ์ฉํด์ Actor ํ๋กํผํฐ์ ์ ๊ทผํ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๊ธฐ์จ์ ์๋ก ์
๋ฐ์ดํธํ๋ ๋ฉ์๋๊ฐ ์๋ค๊ณ ํฉ์๋ค.
extension TemperatureLogger {
func update(with measurement: Int) {
measurements.append(measurement)
if measurement > max {
max = measurement
}
}
}
update(with:)
๋ฉ์๋๋ ์ด๋ฏธ actor์ ์๊ธฐ ๋๋ฌธ์, await
ํค์๋๋ฅผ ์ฌ์ฉํด max
ํ๋กํผํฐ์ ์์๋ ๋ฉ๋๋ค. ์ด ๋ฉ์๋๋ ์ Actor๊ฐ ํ๋ฒ์ ํ๋์ Task๋ง์ด ์ ๊ทผ๊ฐ๋ฅํ๊ฒ ํ๋ ์ง์ ๋ํด์๋ ์๋ ค์ค๋๋ค. 1๋ฒ Task๋ measurements
ํ๋กํผํฐ์ ์๋ก์ด ๊ธฐ์จ์ ์ ์ฅํ๊ณ ์ต๊ณ ๊ธฐ์จ์ ์
๋ฐ์ดํธํ๋ ์์
์
๋๋ค. 1๋ฒ Task๊ฐ ์คํํ๋ ๋์ค, measurements
ํ๋กํผํฐ๋ง ์๋ก ์
๋ฐ์ดํธ๊ฐ ๋์์ ๋, 2๋ฒ Task์์ max
ํ๋กํผํฐ์ ์ ๊ทผํด ์ฝ๋ ์ํฉ์ด ์๋ค๊ณ ํฉ์๋ค. ๊ทธ๋ฆฌ๊ณ 1๋ฒ Task๊ฐ ๋ง๋ฌด๋ฆฌ๋์ด, ์๋ก์ด max
ํ๋กํผํฐ๋ฅผ ๊ฐฑ์ ํ๋ค๋ฉด, 1๋ฒ Task์ 2๋ฒ Task๋ ๋ค๋ฅธ max
ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๊ฒ ๋ ์ํฉ์ด ์๊ธธ๋ฟ๋๋ฌ, 2๋ฒ Task๋ ์ ํจํ์ง ์์ ์ต๊ณ ๊ธฐ์จ๊ฐ์ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ์๋ฐฉํ๊ธฐ ์ํด actor๋ ํ๋ฒ์ ํ๋์ Task๋ฅผ ํ์ฉํด์ค๋๋ค. update(with:)
๋ฉ์๋๋ ๊ทธ ์ด๋ค ์ ์ง ํฌ์ธํธ(suspension point)๋ฅผ ๊ฐ์ง๊ณ ์์ง ์๊ธฐ ๋๋ฌธ์, ๊ทธ ์ด๋ค ์ฝ๋๋ ์
๋ฐ์ดํธ ๋์ค ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค. (๋ง์ผ await
๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด ์
๋ฐ์ดํธ๋ ์ค๊ฐ์ ๋ฉ์ถ ๊ฒ์ด๊ณ , actor๋ ๋ค๋ฅธ Taskํํ
์ด๋ฆฐ ์ํ๊ฐ ๋ ๊ฒ์
๋๋ค. - ์ถ์ธก)
๋ง์ฝ actor์ธ๋ถ์์ ์๋์ ๊ฐ์ด ํ๋กํผํฐ์ ์ ๊ทผํ๋ค๋ฉด, ์ปดํ์ผ ํ์ ์๋ฌ๊ฐ ๋ฉ๋๋ค.
print(logger.max) // Error โ ๏ธ
Swift๋ Actor๋ด๋ถ์ ์ฝ๋๋ง์ด Actor์ ์ง์ญ๋ณ์์ ๋ฐ๋ก ์ ๊ทผ์ ๋ณด์ฅํฉ๋๋ค. ์ด๊ฒ์ actor isolation์ด๋ผ๊ณ ๋ ํฉ๋๋ค. (์ฉ์ด๊ฐ ์ค์ํ๊ฐ?๋ผ๊ณ ํ ์ ์์ง๋ง ๋์ค์ ์ธ์ ๋์ฌ์ง ๋ชจ๋ฅด๋ ์์๋ ๋์. ๊น๋จน์ ์ ์์ผ๋ ์ข ์ข ์ฝ์ด๋ณด์)
actor isoliation: swift๊ฐ actor์ธ๋ถ์์ actor ๋ด๋ถ ์ง์ญ๋ณ์์ ๋ฐ๋ก ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ๊ณ ๋ด๋ถ์์๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํ ๊ฒ์ ๋ณด์ฅํ๋ ์ํฉ (์ธ๋ถ์์ ์ ๊ทผํ๊ธฐ ์ํด์ awaitํค์๋๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค.)
๋ผ๋ ๊ฒ๋ ์๋๋ฐ 2022-09-12 ๊ฐ์ฅ ์ต๊ทผ์ ๋ฌธ์์ ์ถ๊ฐ๋์์ต๋๋ค. ์ด๊ฒ์ ์ ํ๋กํผํฐ์ ๋ฉ์๋ค์ ๋ํด ๋ ๊ณต๋ถํด๋ณด๊ณ ๋ค์ ์ฝ์ด๋ณด๋ ค๊ณ ํฉ๋๋ค!