[Swift๐ฆฉ] #18 ๋์์ฑ
์ฉ์ด ์ ๋ฆฌ
- blocking : ํจ์ ํธ์ถ ์, ๊ธฐ๋๋๋ ํ์๋ฅผ ๋ชจ๋ ๋๋ง์น ๋ ๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ฆฌํด๋๋ฉด, '๋ธ๋กํน๋์๋ค'.
- non-blocking : ๋ฐ๋๋ก, ๊ธฐ๋๋๋ ํ์๋ฅผ ์์ฒญ๋ง ํ๊ณ ๋ฐ๋ก ๋ฆฌํด๋๋ฉด '๋ ผ๋ธ๋กํน๋์๋ค'.
- ๋๊ธฐ : ์์ฐจ์ ์ผ๋ก ์๋.
- ๋น๋๊ธฐ : ์์ฐจ์ ์ด์ง ์๋ค. ๋์์ ์คํ๋๊ณ ์๋ค.
Concurrency
- Swift๋ ๋น๋๊ธฐ / ๋ณ๋ ฌ ์ฝ๋ ์์ฑ์ ์ง์ํ๋ค.
- ๋น๋๊ธฐ(asynchronous) ์ฝ๋ : ์ผ์์ ์ผ๋ก ์ค๋จ๋ ์ ์๊ณ , ํ๋ฒ์ ํ๋ก๊ทธ๋จ์ ํ ๋ถ๋ถ๋ง ์คํ
- ๋ณ๋ ฌ(parallel) ์ฝ๋ : ๋์์ ์ฝ๋์ ์ฌ๋ฌ ๋ถ๋ถ์ด ์คํ๋จ.
๋์์ฑ = ๋น๋๊ธฐ + ๋ณ๋ ฌ
๋น๋๊ธฐ ํจ์ ํธ์ถ ํ๋ก์ธ์ค
1. await ๋ก ํจ์๋ฅผ ํธ์ถํ๋ฉด, ํจ์๋ ํด๋น ์ค๋ ๋์ ์ ์ด๊ถ์ ํฌ๊ธฐํ๊ฒ ๋๋ค. 2. async ์์ & ๊ฐ์ ๋ธ๋ก ํ๋จ์ ์ฝ๋๋ค์ ์ค๋ ๋๋ฅผ ์ก์์ ๋ฐ๋ก ์คํํ ์ ์๊ฒ ๋จ. 3. ์ค๋ ๋ ์ ์ด๊ถ์? ์์คํ ์๊ฒ! ๊ทธ๋ฌ๋ฏ๋ก await ๋ async ์์ ๋ ์ค์ผ์ฅด ํ๋ผ๊ณ ์์คํ ์๊ฒ ๋ถํ. 4. ์์คํ : ์ฐ์ ์์์ ๋ฐ๋ผ async ๋ง๊ณ ๋ค๋ฅธ ์์ ์ ๋จผ์ ์งํํ ์ ์์. (ํด๋น ์ค๋ ๋์์) 5. async ์์ ์ ์์๊ฐ ์ค๋ฉด, ์์คํ ์ await ํ๊ณ ์๋ ์์ ์ ์ฌ๊ฐํ๊ฒ ํ๊ณ , ์ด๋ค ํน์ ํ ์ค๋ ๋ ์ ์ด๊ถ์ ์ฃผ๋ฉด์ ๋ฏธ๋ค์ง async ์์ ์ด ์คํ๋๋ค. (์คํ๋๋ ์ค๋ ๋๋ ๊ธฐ๋ค๋ฆฌ๊ธฐ ์ ์ ์ค๋ ๋์ ๋ค๋ฅผ ์ ์์) / ์ถ์ฒ - https://sujinnaljin.medium.com/swift-async-await-concurrency-bd7bcf34e26f
๋์์ฑ ์ฝ๋ ์์ด๋ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์์ง๋ง, ์ค์ฒฉ ํด๋ก์ ๋ฅผ ์ฌ์ฉํด์ผ ํด์ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง๊ณ ์๋ฌ ์ํฉ์ ๋์ํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ์์๊ธฐ ๋๋ฌธ์, ์๋ก ๋์์ฑ ๊ฐ๋ ์ ๋์ !
listPhotos(inGallery: "Summer Vacation") { photoNames in
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
downloadPhoto(named: name) { photo in
show(photo)
}
}
1. ๋น๋๊ธฐ ํจ์ ์ ์์ ํธ์ถ
- ๋น๋๊ธฐ ํจ์(๋ฉ์๋) ๋ ์คํ ๋์ค์ ์ผ์์ ์ผ๋ก ์ค๋จ๋ ์ ์๋ ํน์ํ ํจ์
- ํจ์๊ฐ ๋ฐํ๋ ๋ ๊น์ง ์์
์ ์ ์ ๋ฉ์ถ ์ ์๋ค. (block)
- ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ ์ ๋ค์ด๊ฐ๋ฉด์ ์ ์ ๋ฉ์ถฐ๋๊ณ , ๊ฐ์ ํ๋ก๊ทธ๋จ ๋ด์ ๋ค๋ฅธ ๊ฒ์ด ๋์ํ ์ ์๊ฒ ํจ.
- <-> ์ผ๋ฐ์ ์ธ ๋๊ธฐ ํจ์
- ์๋ฃ๋ ๋๊น์ง ์คํ๋๊ฑฐ๋
- ์ค๊ฐ์ ์ค๋ฅ ๋ฐ์
- ๋น๋๊ธฐ ํจ์์์ ๋ํ๋ด๊ธฐ ์ํด
async
ํค์๋ ์ฌ์ฉ. - ๋ง์ฝ async ํจ์๊ฐ throw ๋ ํ๋ฉด
async throws
์์๋ก ์์ฑ. - ์ค์ ๋ก ํจ์๋ฅผ ํธ์ถํ๋ ๋ถ๋ถ์์๋
try await
๋ฅผ ์ฌ์ฉ.
func listPhotos(inGallery name: String) async -> [String] {
let result = // ... some asynchronous networking code ...
return result
}
๋น๋๊ธฐ ํจ์ ์คํ ํ๋ฆ
- ๋น๋๊ธฐ ๋ฉ์๋ ๋ด์์ ์คํ ํ๋ฆ์, ๋ค๋ฅธ ๋น๋๊ธฐ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋๋ง ์ผ์ ์ค๋จ๋๋ค.
- ์ค๋จ์ ์์์ ์ผ๋ก ์ด๋ฃจ์ด์ง์ง ์์ผ๋ฏ๋ก, ๋ฌด์กฐ๊ฑด
await
ํค์๋๋ก ์์๋๋ก ์คํํ๋ค๊ณ ํ์ํด์ผ ํ๋ค.- async ํจ์๊ฐ return ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉด์ ํ์ฌ ์ฝ๋ ๋ถ๋ถ์ด ์คํ์ ์ผ์ ์ค๋จ ํ ์ ์๋ค.
- ํด๋น ์ฐ๋ ๋๋ฅผ ๋ค๋ฅธ ์ฝ๋์ ๋๊ฒจ์ฃผ๊ธฐ ๋๋ฌธ์, ์ฐ๋ ๋ ์๋ณด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
let photoNames = await listPhotos(inGallery: "Summer Vacation")
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
let photo = await downloadPhoto(named: name)
show(photo)
- await ํจ์๋ ์คํ์ ์ผ์ ์ค๋จํ ์ ์์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ํ๋ก๊ทธ๋จ์ ํน์ ์์น์์๋ง ํธ์ถํ ์ ์๋ค.
- ๋น๋๊ธฐ ํจ์, ๋ฉ์๋ ๋๋ ํ๋กํผํฐ์ ๋ฐ๋์ ์๋ ์ฝ๋
- @main ์ผ๋ก ํ์๋ ๊ตฌ์กฐ์ฒด, ํด๋์ค, ์ด๊ฑฐํ์ static ๋ฉ์๋์ ์๋ ์ฝ๋
- ๊ตฌ์กฐํ๋์ง ์์ ํ์ ์์ ์ฝ๋
2. ๋น๋๊ธฐ ์ํ์ค
- listPhotos ์ ๊ฒฝ์ฐ, ์ฌ์ง ๋ฐฐ์ด ์ ์ฒด๊ฐ ์ค๋น๋ ๋ค์์ ์ ์ฒด ๋ฐฐ์ด์ ํ๋ฒ์ ๋ฐํ๋์ง๋ง,
func listPhotos(inGallery name: String) async -> [String] {
let result = // ... some asynchronous networking code ...
return result
}
for await in
๊ตฌ๋ฌธ์ผ๋ก ๋ฐฐ์ด ์์ดํ ํ๋ํ๋๋ฅผ ๋น๋๊ธฐ๋ก ๋ถ๋ฌ์ฌ ์๋ ์๋ค.
import Foundation
let handle = FileHandle.standardInput
for try await line in handle.bytes.lines {
print(line)
}
3. ๋น๋๊ธฐ ํจ์ ๋ณ๋ ฌ๋ก ํธ์ถ
await
๋ก ํจ์๋ฅผ ํธ์ถํ๋ฉด, ์ฝ๋์ ํ ๋ถ๋ถ๋ง ์คํ๋จ.- ๊ทธ๋์ ๋ค์ ๋ผ์ธ์ ์คํํ๊ธฐ ์ํด ๊ธฐ๋ค๋ ค์ผ ํจ.
await ํค์๋๊ฐ ๋ถ์ด์์ด์
- download firstPhoto
- download secondPhoto
- download thirdPhoto
- ๋ฅผ ์ ๋ถ ํด์ผ๋ง let photos = ~~
// a
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
ํ๋ค๋ฉด?
- ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ๊ณ ์ฃผ๋ณ์ ์ฝ๋์ ๋ณ๋ ฌ์ ์ผ๋ก ์คํํ ์ ์๋ค.
// async ํค์๋๋ฅผ ๋ถ์ฌ์ ๋ณ์์ ํ ๋นํ๋ฉด, ๋์์ 3์ฅ ๋ฐ์์ฌ ์ ์์.
// ์ด์ ํธ์ถ์ด ์๋ฃ๋๊ธธ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์์ํจ.
async let firstPhoto = downloadPhoto(named: photoNames[0])
async let secondPhoto = downloadPhoto(named: photoNames[1])
async let thirdPhoto = downloadPhoto(named: photoNames[2])
// ๋์ ์ด ๋ฌธ์ฅ์ ์ฌ์ง 3์ฅ์ ์ ๋ถ ๋ฐ์ ๋ ๊น์ง ๊ธฐ๋ค๋ ธ๋ค ์คํํด์ผํ๊ธฐ ๋๋ฌธ์ await ๋ฅผ ๋ถ์ฌ์ผ ํจ.
let photos = await [firstPhoto, secondPhoto, thirdPhoto]
show(photos)
- ์์ฐจ์ ์ผ๋ก ์คํํด์ผ ํ๋ ์์ (์ด์ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ๊ฐ๋ค ์ด๋ค๋์ง) -> await ํค์๋๋ฅผ ๋ฃ์ด์ ํธ์ถ
- ๋ฑํ ๋์ค์ ๊ฒฐ๊ณผ๊ฐ ํ์ํ์ง ์์ -> async let
4. ์์ ๊ณผ ์์ ๊ทธ๋ฃน Task
Task : ์ฝ๋๋ฅผ ๋ณ๋ ฌ๋ก ์คํํ๋ ๊ธฐ๋ณธ ๋ฉ์ปค๋์ฆ
- Task : ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ ์ ์๋ ์์ ๋จ์
- ๋น๋๊ธฐ ์ฝ๋๋ ์ด๋ค ์์ ์ ์ผ๋ถ๋ก ์คํ๋๋ค.
- ์๋ฅผ ๋ค์ด, ์์
async - let
๊ตฌ๋ฌธ์ ๊ฒฝ์ฐ ์์ 3๊ฐ๋ก ์ด๋ฃจ์ด์ ธ ์๋ค. - Task Group ์ ๋ง๋ค์ด์ ํ์ ์์ ์ ์ถ๊ฐํ๋ ํ์์ผ๋ก, ์ฐ์ ์์/์ทจ์ ์ ์ด, ๋์ ์ผ๋ก ์์ ์์ฑ ๊ฐ๋ฅ.
- ์์ ๊ทธ๋ฃน ๋ด์ ์์ ์๋ ๋์ผํ ์์ ์์ ์ด ์์ผ๋ฉฐ, ํ์ ์์ ์ ์์ ์๋ ์์ ์๋ ์๋ค.
- ์์ ๊ณผ ์์ ๊ทธ๋ฃน ๊ฐ์ ๋ช ์์ ์ธ ๊ด๊ณ๊ฐ ์์ด์ ๊ตฌ์กฐ์ ๋์์ฑ(Structured Concurrency) ์ ๊ทผ ๋ฐฉ์์ด๋ผ๊ณ ๋ถ๋ฆผ.
- ์ ํ์ฑ์ ๋ํ ์ผ๋ถ ์ฑ ์์ ์ง๊ณ ์์ด์, ๋ถ๋ชจ-์์ ๊ด๊ณ๋ฅผ ํตํด ์ทจ์ ์ ํ ๊ฐ์ ์ผ๋ถ ๋์๊ณผ, ์ปดํ์ผ ํ๋ ๋์์ ์ผ๋ถ ์ค๋ฅ๋ฅผ ๊ฐ์งํ ์ ์๋ค.
Unstructured Concurrency
- TaskGroup ๊ฐ์ ๊ตฌ์กฐํ ๋ ์ ๊ทผ ๋ฐฉ์ ์ด์ธ์๋ ๋์์ฑ์ ๋ํ ์ ๊ทผ ๋ฐฉ์์ด ์๋ค.
- ์์ ์์ ์ด ์์ด์ ์์ ํ ์ ์ฐ์ฑ์ ๊ฐ์ง์ง๋ง, ์ ํ์ฑ์ ๋ํ ์ฑ ์์ด ์ฌ์ฉ์์๊ฒ ์๋ค.
Task.init(priority: operation:)
๊ตฌ๋ฌธ์ ์ฌ์ฉํด์ ํ์ฌ ํ์์์์ ์คํ๋๋ ๊ตฌ์กฐํ ๋์ง ์์ ์์ ์ ์์ฑํ ์ ์๋ค.Task.detached(priority: operation:)
๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ฉด, ํ์ฌ ํ์์์ ์ผ๋ถ๊ฐ ์๋ ๊ตฌ์กฐํ๋์ง ์์ ์์ ์ ์์ฑํ ์ ์๋ค.- ์์ ๊ณผ ์ํธ์์ฉํ ์ ์๋ ํธ๋ค๋ฌ๋ฅผ ๋ฐํํ๋ค.
let newPhoto = // ... some photo data ...
let handle = Task {
return await add(newPhoto, toGalleryNamed: "Spring Adventures")
}
let result = await handle.value
์์ ์ทจ์
- Cooperative Cancellation Model ํ๋ ์ทจ์ ๋ชจ๋ธ์ ํตํด,
- ์์ ์ด ์คํ์ด ์ ์ ํ ์์ ์์ ์ทจ์๋์๋์ง ํ์ธํ๊ณ , ์ทจ์์ ์๋ตํ๋ค.
- ์์
์ทจ์์ ์ข
๋ฅ
CancellationError
์ ๊ฐ์ ์๋ฌ ๋ฐ์nil
๋๋ ๋น ์ฝ๋ ์ ๋ฐํ- ๋ถ๋ถ์ ์ผ๋ก ์๋ฃ๋ ์์ ๋ฐํ
Task.checkCancellation()
์ ํตํดCancellationError
๊ฐ ๋ฐ์ํ ์๊ฐ์ ์ก์์ ์ฒ๋ฆฌํ ์ ์์.Task.isCancelled
์ ๊ฐ์ ํ์ธํ๊ณ ์ฝ๋ ๋ด์์ ์ฒ๋ฆฌํ ์ ์์.- ์๋์ผ๋ก ์ทจ์ํ๋ ค๋ฉด
Task.cancel()
ํธ์ถ.
5. ํ์์ Actors
- ํ์์๋ ์ฐธ์กฐ ํ์
- ํด๋์ค์์ ์ฐจ์ด์
- ํ ๋ฒ์ ํ๋์ ์์ ๋ง ํ์์ ๋ด์ ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค.
- ์ฌ๋ฌ ์์ ์ฝ๋๊ฐ ๊ฐ์ ํ์์ ์ธ์คํด์ค์ ์ํธ์์ฉํด๋ ์์ ํ๋ค.
- mutable state ์ ์์ ํ๊ฒ ์ ๊ทผํ ์ ์๋ค.
์์.
- ํด๋์ค, ๊ตฌ์กฐ์ฒด ๋ฌธ๋ฒ๊ณผ ๊ฑฐ์ ์ ์ฌํ์ง๋ง,
- actor ๋ฐ๊นฅ์์ actor ์์ ํ๋กํผํฐ๋ ๋ฉ์๋์ ์ ๊ทผํ ๋,
- ํ๋์ task ๋ง ํด๋น ์ฝ๋์ ์ ๊ทผํ ์ ์์ผ๋ฏ๋ก,
- ๋ค๋ฅธ task ๊ฐ ์ ๊ทผํ์ ๋ ๋ฉ์ถฐ๋์ผํจ.
await
ํค์๋๋ฅผ ๋ถ์ฌ์ ํธ์ถํ๋ค.
- ํ์์ ์์์๋ ํ๋กํผํฐ๋ ๋ฉ์๋์ ์ ๊ทผํ ๋,
await
๋ฅผ ์์ฑํ์ง ์๋๋ค. (actor isolation)
// 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
}
}
extension TemperatureLogger {
// ํ์์ ์์์ ์คํํ๋ ํจ์์ด๋ฏ๋ก, await ๋ฅผ ์ฐ์ง ์๋๋ค.
// ์ฌ๋ฌ ์์
์์ ๋์์ ์ด ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒฝ์ฐ,
// ํ์์ ๋ด ํ๋กํผํฐ์ ๋ถ๋ณ์ฑ์ด ๊นจ์ง๋ฏ๋ก
// ํ ๋ฒ์ ํ๋์ ์์
๋ง ์ฒ๋ฆฌํ ์ ์๊ฒ ๋ง๋๋ ํ์์๋ฅผ ์ฌ์ฉํ๋ค.
func update(with measurement: Int) {
measurements.append(measurement)
if measurement > max {
max = measurement
}
}
}
let logger = TemperatureLogger(label: "Outdoors", measurement: 25)
print(await logger.max)
// ๋ค๋ฅธ ์์
์ ์ฝ๋๊ฐ ์ด๋ฏธ ์ํธ์์ฉํ๊ณ ์์ผ๋ฉด ์ ๊ทผ์ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ์ผ์์ ์ง.
// await ๋ฅผ ์์ฑํ์ง ์์ผ๋ฉด ์๋ฌ๋ฅผ ๋ฟ๋๋ค.
// Prints "25"
์ ๋ฆฌ
async await
- async ํค์๋๋ฅผ ํตํด ์๋ non-blocking ์ธ Swift ์ ํจ์๋ฅผ blocking ์ผ๋ก ๋ง๋ค์ด ์ฃผ๋ ๊ฒ.
- await ํค์๋๋ฅผ ํตํด blocking ํจ์๊ฐ ๋๋ ๋ ๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ (๋๊ธฐ)
- escaping closure ๋ฅผ ์ฌ์ฉํด์ non-block / ๋น๋๊ธฐ ๋ก ์ฌ์ฉํ๋ ๊ฒ์ block / ๋๊ธฐ์ธ ๊ฒ์ฒ๋ผ ์ฌ์ฉ.
- async ํจ์, await ํค์๋๋ก ํธ์ถ -> ์ค๋ ๋ ์ ์ด๊ถ ์์คํ ์ ๊ฐ๋ฉด์ ๋๊ธฐ -> ์์คํ ์ด ์ฐ์ ์์์ ๋ฐ๋ผ ์์ -> ์ฐจ๋ก๊ฐ ๋์์์ ์์คํ ์ด ํด๋น ์์ ์ ์ด๋ค ์ค๋ ๋๋ฅผ ์ฃผ๋ฉด ๊ฑฐ๊ธฐ์์ ์คํ.
/- Task : ๋น๋๊ธฐ ์์ ์ ๋จ์. ์ฐ์ ์์๋ ์ทจ์๋ฅผ ์ ์ดํ๊ณ ๋์ ์์ฑ ๊ฐ๋ฅ.
- Actor : ํ๋์ task ๋ง mutable state์ ์ ๊ทผํ ์ ์๊ฒ ํ์ฌ, ์์ ์ฑ ํ๋ณด.
์ถ์ฒ
https://bbiguduk.gitbook.io/swift/language-guide-1/concurrency
https://okky.kr/article/442803
https://sujinnaljin.medium.com/swift-async-await-concurrency-bd7bcf34e26f
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ([Swift๐ฆฉ] #18 ๋์์ฑ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@ddosang/Swift-18-๋์์ฑ์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค