[Swift๐Ÿฆฉ] #18 ๋™์‹œ์„ฑ

21003 ๋‹จ์–ด swiftiOSiOS

์šฉ์–ด ์ •๋ฆฌ

  • 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

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ