๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
iOS ๐ŸŽ/iOS

Concurrency1 : GCD, Operation

by yongmin.Lee 2023. 1. 27.

Concurrency Programming, ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

  • ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋™์‹œ์— ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์‹ฑ๊ธ€ ์ฝ”์–ด์—์„œ๋„ ๊ฐ€๋Šฅํ•œ ๋…ผ๋ฆฌ์ ์ธ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. 
  • Swift๋กœ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” completion handler, GCD, Operation, Structed Concurrency๊ฐ€ ์žˆ๋‹ค

 

Parallel Programming, ๋ณ‘๋ ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

  • ๋ณ‘๋ ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ CPU(์ฝ”์–ด)๊ฐ€ ํ•˜๋‚˜์˜ ์ž‘์—…(Task)์„ ๋ถ„๋‹ดํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ
  • ๋ฌผ๋ฆฌ์ ์ธ ๊ฐœ๋…์œผ๋กœ CPU(์ฝ”์–ด)๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์„ ๋•Œ์— ๊ฐ€๋Šฅ
  • ๋ณ‘๋ ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋‹ค์ค‘ ์ฝ”์–ด๋ฅผ, ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ ์ด ๋‘˜์€ ๋™์‹œ์— ์ผ์–ด๋‚  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Serial Programming, ์ง๋ ฌ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

  • ์ง๋ ฌ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋‹จ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ์—์„œ๋งŒ ์ž‘์—…์„ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ๋™์‹œ์— ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๊ณ , ์ˆœ์„œ๋Œ€๋กœ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

Synchronous, ๋™๊ธฐ

  • ๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ž‘์—…์ด ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • A๋ผ๋Š” ์ฝ”๋“œ ๋ธ”๋ก์„ ๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ–ˆ๋‹ค๋ฉด A๋ผ๋Š” ์ฝ”๋“œ์˜ ์‹คํ–‰์ด ์™„์ „ํžˆ ๋์ด๋‚˜์•ผ ๋‹ค์Œ ์ฝ”๋“œ๋กœ ๋„˜์–ด๊ฐ„๋‹ค.

 

Asynchronous, ๋น„๋™๊ธฐ

  • ๋ฐ˜๋Œ€๋กœ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ž‘์—…์ด ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ , ๋‹ค์Œ ์ฝ”๋“œ ๋ธ”๋ก์„ ๋ฐ”๋กœ ์‹คํ–‰์‹œํ‚ค๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. 
  • A, B๋ผ๋Š” ์ž‘์—…์ด ๋‚˜์—ด๋˜์–ด ์žˆ๊ณ  A๋ฅผ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌํ•ด์ฃผ์—ˆ์„ ๋•Œ A๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋ฐ”๋กœ B ์ž‘์—…์„ ์‹œ์ž‘ํ•œ๋‹ค.
  • ๋™๊ธฐ์™€ ๋น„๋™๊ธฐ๋Š” ์‹คํ–‰ ์ข…๋ฃŒ ์‹œ์ ์„ ์•Œ ์ˆ˜ ์žˆ๋Š”๊ฐ€์— ๋Œ€ํ•œ ์ฐจ์ด๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.
  • ๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ์ž‘์—…์€ ๋ฌด์กฐ๊ฑด ์ž‘์—…์ด ์ข…๋ฃŒ๋˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋˜๋‹ˆ ์ž‘์—…์ด ์ข…๋ฃŒ๋œ ํ›„์— ํ•  ์ผ์„ ์ •ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋น„๋™๊ธฐ์˜ ๊ฒฝ์šฐ์—๋Š” ์–ธ์ œ ์ž‘์—…์ด ์ข…๋ฃŒ๋˜๋Š”์ง€๋ฅผ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 

๋™์‹œ์„ฑ vs ๋น„๋™๊ธฐ

  • ๋™์‹œ์„ฑ ๋น„๋™๊ธฐ๋Š” ์™„์ „ํžˆ ๋‹ค๋ฅธ ๊ฐœ๋…
  • ๋™์‹œ์„ฑ: Serial์ด๋ƒ, Concurrent์ธ๊ฐ€๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹จ์ผ ์Šค๋ ˆ๋“œ์ธ๊ฐ€, ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ์ธ๊ฐ€์˜ ๊ตฌ๋ถ„
  • ๋™๊ธฐ/๋น„๋™๊ธฐ: ์Šค๋ ˆ๋“œ์˜ ์ˆ˜์™€๋Š” ๋ฌด๊ด€ํ•˜๊ฒŒ ์ž‘์—…์ด ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ƒ, ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๋Š๋ƒ์˜ ๊ตฌ๋ถ„
  • Serial ํ™˜๊ฒฝ์—์„œ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ  Concurrent ํ™˜๊ฒฝ์—์„œ ๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , ๋น„๋™๊ธฐ๋กœ๋„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค

 


Grand Central Dispatch (GCD) = Dispatch Framework

Grand Central Dispatch

  • Dispatch (=GCD) ๋Š” ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ•˜๋“œ์›จ์–ด์—์„œ ๋™์‹œ์„ฑ ์ฝ”๋“œ ์‹คํ–‰์„ ์œ„ํ•œ ์–ธ์–ด ๊ธฐ๋Šฅ, ๋Ÿฐํƒ€์ž„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, ์‹œ์Šคํ…œ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋œ ํ”„๋ ˆ์ž„์›Œํฌ์ด๋‹ค.
  • Dispatch ํ”„๋ ˆ์ž„์›Œํฌ์—๋Š” DispatchQueue, DispatchWorkItem, DispatchGroup, DispatchQoS, DispatchSource, DispatchSemaphore ๋“ฑ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ž‘์—… ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ํƒ€์ž…๋“ค์ด ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค. 

 

DispatchQueue

  • ํ…Œ์Šคํฌ๋ฅผ ๋‹จ์ผ ๋˜๋Š” ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ์—์„œ ์ง๋ ฌ ๋˜๋Š” ๋™์‹œ ์‹คํ–‰ํ• ์ง€ ๊ด€๋ฆฌํ•˜๋Š” FIFO ํ
  • DispatchQueue์— ์ž‘์—…์„ ๋„˜๊ธธ ๋•Œ 2๊ฐ€์ง€๋ฅผ ์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค
    • ๋‹จ์ผ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ๊ฐ€, ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ๊ฐ€(Serial/Concurrent)
    • ๋™๊ธฐ๋กœ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ธ๊ฐ€, ๋น„๋™๊ธฐ๋กœ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ธ๊ฐ€(sync/async)
  • DispatchQueue.main๊ณผ DispatchQueue.global()์€ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ ธ์žˆ๋Š” ํ๋กœ ๊ฐ๊ฐ Serial, Concurrent ํ
// ๋‹จ์ผ์Šค๋ ˆ๋“œ, ๋™๊ธฐ
DispatchQueue.main.sync {}
DispatchQueue(label: "Serial").sync {}

// ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ, ๋™๊ธฐ
DispatchQueue.global().sync {}
DispatchQueue(label: "Concurrent", attributes: .concurrent).sync {}

// ๋‹จ์ผ์Šค๋ ˆ๋“œ ๋น„๋™๊ธฐ
DispatchQueue.main.async {}
DispatchQueue(label: "Serial").async {}

// ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ ๋น„๋™๊ธฐ
DispatchQueue.global().async {}
DispatchQueue(label: "Concurrent", attributes: .concurrent).async {}

 

main Thread

  • ์•ฑ์ด ์‹คํ–‰๋˜๋Š” ๋™์•ˆ์—๋Š” ๋Š˜ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ผ์™€์žˆ๋Š” ๊ธฐ๋ณธ ์Šค๋ ˆ๋“œ๋กœ ์ „์—ญ์ ์œผ๋กœ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋™์ž‘ํ•˜๋Š” Run Loop๋ฅผ Main Run Loop๋ผ๊ณ  ํ•œ๋‹ค.
  • UIKit์˜ ๋Œ€๋ถ€๋ถ„์˜ ์š”์†Œ๋“ค์€ Thread Unsafe ํ•˜๋ฏ€๋กœ Race Condition์ด ๋ฐœ์ƒํ• ์ˆ˜ ์žˆ๋‹ค.
    ๋”ฐ๋ผ์„œ, ๋ชจ๋“  UI ์ž‘์—…๋“ค์€ Serial Queue์ธ Main Thread๋กœ ๊ฐ€์ ธ์™€ Main RunLoop์— ๋”ฐ๋ผ UI๋ฅผ ๊ทธ๋ฆฌ๋„๋ก ํ•จ/
    ์ด๋Ÿฌํ•œ ์ฃผ๊ธฐ๋ฅผ View Drawing Cycle ์ด๋ผ๊ณ ํ•œ๋‹ค.
  • main ์Šค๋ ˆ๋“œ์—์„œ main.sync๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
    main ์Šค๋ ˆ๋“œ๋Š” Serial Queue์ด๋ฏ€๋กœ main ์Šค๋ ˆ๋“œ๋Š” main.sync๊ฐ€ ๋๋‚˜๊ธฐ๋ฅผ, main.sync๋Š” main ์Šค๋ ˆ๋“œ์˜ Block-wait์ด ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” deadlock(๊ต์ฐฉ์ƒํƒœ) ์ƒํƒœ๊ฐ€ ๋˜์–ด๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ.
  • main ์Šค๋ ˆ๋“œ์— ๋น„๋™๊ธฐ(async) ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋Š”๊ฒฝ์šฐ, ๋‹จ์ผ ์Šค๋ ˆ๋“œ์—์„œ๋งŒ ์ž‘์—…์ด ์ด๋ฃจ์–ด์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋น„๋™๊ธฐ ์ž‘์—…์ด๋”๋ผ๋„ ๋™์‹œ์— ์ž‘์—…์ด ์ฒ˜๋ฆฌ๋˜์ง€๋Š” ๋ชปํ•˜๊ณ  ์ˆœ์„œ๋Œ€๋กœ ์ž‘์—…์ด ์ฒ˜๋ฆฌ

 

DispatchWorkItem

DispatchQueue์—์„œ ์ฝ”๋“œ ๋ธ”๋ก์„ ํ˜ธ์ถœํ•˜๋Š”๋ฐ์— ์žˆ์–ด์„œ DispatchWorkItem์„ ํ™œ์šฉํ•˜์—ฌ ์ฝ”๋“œ ๋ธ”๋ก์„ ์บก์Šํ™”๊ฐ€๋Šฅ

์ •์˜๋œ DispatchWorkItem๋Š” sync์™€ async ๋ฉ”์„œ๋“œ์˜ execute ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ

let yellow = DispatchWorkItem {
    for _ in 1...5 {
        print("yellow")
        sleep(1)
    }
}

let blue = DispatchWorkItem {
    for _ in 1...5 {
        print("blue")
        sleep(1)
    }
}

DispatchQueue.main.async(execute: yellow)
DispatchQueue.global().sync(excute: blue)

 

QoS, Quality of Service

  • ๋ฌด์—‡์— ๋” ๋งŽ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ• ์ง€์— ๋Œ€ํ•œ ์šฐ์„ ์ˆœ์œ„ (๋ฌด์—‡์„ ๋จผ์ € ์ฒ˜๋ฆฌํ• ์ง€ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ์•„๋‹ˆ๋‹ค)
  • ์‹œ์Šคํ…œ์€ QoS ์ •๋ณด๋ฅผ ํ†ตํ•ด ์Šค์ผ€์ฅด๋ง, CPU ๋ฐ I/O ์ฒ˜๋ฆฌ๋Ÿ‰, ํƒ€์ด๋จธ ๋Œ€๊ธฐ ์‹œ๊ฐ„ ๋“ฑ์˜ ์šฐ์„  ์ˆœ์œ„๋ฅผ ์กฐ์ •
  • ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋†’์„ ์ˆ˜๋ก ๋” ๋งŽ์€ ์ „๋ ฅ์„ ์†Œ๋ชจ

 

DispatchGroup

  • DispatchGroup์€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ์ž‘์—…๋“ค์„ ๊ทธ๋ฃน์œผ๋กœ ๋ฌถ์–ด, ๊ทธ๋ฃน ๋‹จ์œ„๋กœ ์ž‘์—… ์ƒํƒœ๋ฅผ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ
// ์‚ฌ์šฉ๋ฐฉ๋ฒ•1 : enter, leave๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ
let group1 = DispatchGroup()
group1.enter()
DispatchQueue.main.async {
	// ๋น„๋™๊ธฐ์ž‘์—…
}
DispatchQueue.global().async {
	// ๋น„๋™๊ธฐ์ž‘์—…
}
group1.leave()

// ์‚ฌ์šฉ๋ฐฉ๋ฒ•2 : enter, leave๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ
let group2 = DispatchGroup()
DispatchQueue.main.async(group: group2) {
	// ๋น„๋™๊ธฐ์ž‘์—…
}
DispatchQueue.global().async(group: group2) {
	// ๋น„๋™๊ธฐ์ž‘์—…
}
  • notify() : notify ๋ฉ”์„œ๋“œ์— ์˜ํ•ด group์˜ ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ์ฝ”๋“œ ๋ธ”๋ก์„ ์‹คํ–‰, ์ด๋•Œ notify์˜ ํŒŒ๋ผ๋ฏธํ„ฐ queue๋Š” ์ฝ”๋“œ๋ธ”๋ก์„ ์‹คํ–‰์‹œํ‚ฌ queue๋ฅผ ์ง€์ •
  • wait() : wait๋Š” DispatchGroup์˜ ์ˆ˜ํ–‰์ด ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ๋งŒ ํ•˜๋Š” ๋ฉ”์„œ๋“œ. notify์™€ ๋‹ฌ๋ฆฌ ๋ณ„๋„์˜ ์ฝ”๋“œ ๋ธ”๋ก์„ ์‹คํ–‰ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ฝ”๋“œ ๋ธ”๋ก์„ ์‹คํ–‰์‹œํ‚ฌ queue๋ฅผ ์ง€์ •ํ•  ํ•„์š”๋„ ์—†๋‹ค.
// notify()
let group = DispatchGroup()
DispatchQueue.global().async(group: group, execute: blue)
DispatchQueue.global().async(group: group, execute: red)
group.notify(queue: .main) {
    print("๋ชจ๋“  ์ž‘์—…์ด ๋๋‚ฌ์Šต๋‹ˆ๋‹ค.")
}

// wait()
let group = DispatchGroup()
DispatchQueue.global().async(group: group, execute: blue)
DispatchQueue.global().async(group: group, execute: red)
group.wait()
print("๋ชจ๋“  ์ž‘์—…์ด ๋๋‚ฌ์Šต๋‹ˆ๋‹ค.")

 

DispatchSemaphore

  • ์Šค๋ ˆ๋“œ์— ์ ‘๊ทผ๊ฐ€๋Šฅํ•œ ์Šค๋ ˆ๋“œ ์ˆ˜๋ฅผ ์„ค์ • Race Condition์„ ๋ฐฉ์ง€
  • wait()๊ณผ signal()์„ ํ˜ธ์ถœํ•˜์—ฌ ์ ‘๊ทผ๊ถŒํ™˜ ์š”์ฒญ๋ฐ ๋ฐ˜ํ™˜

Operation

Operation

  • ์‹คํ–‰ํ•  ์ฝ”๋“œ ๋ธ”๋ก์„ ๊ฐ์ฑ„ํ™”ํ•ด๋‘” ๊ฒƒ. (GCD์˜ DispatchWorkItem์™€ ์œ ์‚ฌ)
  • Operation์€ ์ถ”์ƒํด๋ž˜์Šค์ด๋ฏ€๋กœ ํ•˜์œ„ ํด๋ž˜์Šค๋Š” ์ปค์Šคํ…€ ํด๋ž˜์Šค๋กœ ์ง์ ‘ ๋งŒ๋“ค์–ด์ฃผ๊ฑฐ๋‚˜ BlockOperation์ด๋ผ๋Š” ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉ
  • Opertion์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ 2๊ฐ€์ง€
    • ์ง์ ‘ ์‹คํ–‰
    • OperationQueue์— ๋„ฃ๋Š” ๋ฐฉ๋ฒ•
let operation = BlockOperation {
    // A. some code
}

// BlockOperation์˜ ๋ฉ”์„œ๋“œ
operation.addExecutionBlock {
    // B.Operation์˜ ๋™์ž‘์ด ๋๋‚˜๊ณ  ๋‚œ ํ›„์— ์›ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ A->B
}

// Operation์˜ ํ”„๋กœํผํ‹ฐ
operation.completionBlock = {
    // C. Operation๊ณผ ๊ทธ์™€ ์—ฐ๊ด€๋œ executionBlock๋“ค์ด ๋ชจ๋‘ ์‹คํ–‰๋œ ๋‹ค์Œ์— ์‹คํ–‰ A->B->C
}

// OperationQueue์—๋Š” Operation์„ ๋„ฃ์–ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฐ”๋กœ ์‹คํ–‰๋œ๋‹ค
let operationQueue = OperationQueue()
operationQueue.addOperation(operation)

 

OperationQueue

  • OperationQueue๋Š” Operation ๊ฐ์ฒด๋“ค์„ ์‹คํ–‰ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋Œ€๊ธฐ์—ด
  • Operation๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์ข€ ๋” ๊ฐ์ฒด์ง€ํ–ฅ์ ์œผ๋กœ ์„ค๊ณ„๋˜์–ด sync/async์— ๋Œ€ํ•œ ์ •๋ณด๋Š” Operation์ด ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์Šค๋ ˆ๋“œ ๊ด€๋ฆฌ๋Š” OperationQueue๊ฐ€ ํ•œ๋‹ค
  • operation์„ ํ์— ์ถ”๊ฐ€ํ•˜๋ฉด ์‹คํ–‰๋  ๋•Œ๊นŒ์ง€ operation์€ ํ์— ๋‚จ์•„์žˆ๊ณ  ์ถ”๊ฐ€๋œ operation์„ ์ง์ ‘ ์‚ญ์ œํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.
  • ๋ชจ๋“  operation์ด ๋๋‚  ๋•Œ๊นŒ์ง€ Queue๋Š” ์œ ์ง€

 

GCD vs Operation

  • Operation์—๋Š” ํ•ด๋‹น Operation์˜ ์ƒํƒœ๋ฅผ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์กด์žฌ
    • isConcurrent: Bool   => Operation ๋™์‹œ์„ฑ ์—ฌ๋ถ€
    • isAsynchronous: Bool  =>  Operation ๋น„๋™๊ธฐ ์—ฌ๋ถ€
    • isReady:  Bool  =>  Operation์ด ์‹คํ–‰ํ•  ์ค€๋น„๋ฅผ ๋งˆ์น˜๋ฉด isReady ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. 
    • isExecuting:  Bool  =>  Start๊ฐ€ ํ˜ธ์ถœ๋œ ํ›„(ํ˜น์€ OperationQueue์— ์˜ํ•ด ์‹คํ–‰๋œ ํ›„) isExecuting ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. 
    • isCancel:  Bool  =>  Operation์„ cancelํ•˜๊ฒŒ ๋˜๋ฉด isCancel ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. 
    • isFinished:  Bool  =>  cancelํ•˜์ง€ ์•Š๊ณ  ๋™์ž‘์„ ๋ชจ๋‘ ๋งˆ์ณค๋‹ค๋ฉด isFinished ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

 

 

 
 
์ฐธ๊ณ 

 

https://medium.com/hcleedev/swift-structed-concurrency%EB%9E%80-32f9a5c7ac58

https://velog.io/@ldh0320/WWDC21-Meet-asyncawait-in-Swift#a-normal-function-call

https://developer.apple.com/documentation/dispatch
https://developer.apple.com/documentation/foundation/operation

https://developer.apple.com/documentation/foundation/operationqueue