๋™์‹œ์„ฑ์€ ์ด์ œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋นผ๋†“์„ ์ˆ˜ ์—†๋Š” ์š”์†Œ๊ฐ€ ๋˜์—ˆ๋‹ค. ํ•ญ์ƒ ๋™์‹œ์„ฑ๊ณผ ๊ฐ™์ด ๋‚˜์˜ค๋Š” ๋ณ‘๋ ฌ์„ฑ์€ ๋ฌด์—‡์ด ๋‹ค๋ฅผ๊นŒ? ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ป๊ฒŒ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•  ์ˆ˜ ์žˆ์„๊นŒ? iOS ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๋•Œ๋Š” ์–ด๋–ค ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„๊นŒ? ๋‹ค์–‘ํ•œ ๊ฒƒ๋“ค์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ธฐ ์ด์ „์—, iOS์—์„œ์˜ Thread์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

ํ•ด๋‹น ๊ธ€์€ ์‚ฌ๋‚ด ๋ฐœํ‘œ์™€ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

Concurrency

๋™์‹œ์— ์ผ์–ด๋‚˜๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ผ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์—ฌ๋Ÿฌ๋ถ€๋ถ„์„ ๋™์‹œ์— ์‹คํ–‰ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•œ๋‹ค. ํ•˜์ง€๋งŒ! ์ด๋Š” ๋…ผ๋ฆฌ์ ์ธ ๊ฐœ๋…์ด๋‹ค. ์ฆ‰, ๋™์‹œ์— ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•œ๋‹ค๋Š” ๊ฒƒ. ๊ทธ๋Ÿผ ์ •๋ง ๋ณ‘๋ ฌ๋กœ ์ผ์–ด๋‚˜๋Š” ํ–‰์œ„๋ฅผ ๋ญ๋ผ๊ณ  ๋ถ€๋ฅผ๊นŒ? ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋‹ค. Parallelism ์ด๋ผ ํ•œ๋‹ค. ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ™˜๊ฒฝ์—์„œ๋Š” ์ •๋ง ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰๋  ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

์—ฌ๊ธฐ์„œ ํ•ต์‹ฌ์€ ๋ฉด์ ‘๊ด€ ์ˆ˜์— ๊ด€๊ณ„์—†์ด, ๋ฉด์ ‘์ž๋“ค์„ ์—ฌ๋Ÿฌ์ค„๋กœ ๋‚˜๋ˆ„์–ด์„œ ๋ฉด์ ‘์žฅ์— ๋“ค์—ฌ๋ณด๋ƒˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฉด์ ‘๊ด€์€ ์‹ค์ œ ๋ฌผ๋ฆฌ ์Šค๋ ˆ๋“œ๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๊ณ , ์ค„์„ ์„ธ์›Œ์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ๋™์‹œ์„ฑ์„ ๋งŒ์กฑํ•˜๋„๋ก ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ์‹์ด๋ผ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

Thread

  • ์ฝ”๋“œ์— ๋Œ€ํ•œ ๋ณ„๋„์˜ ์ž‘์—… ํ๋ฆ„
  • iOS ์ œ๊ณต Thread
    • Cocoa Thread
    • POSIX Thread

Thread Class ์‚ฌ์šฉํ•˜์—ฌ ๋งŒ๋“ค๊ธฐ

๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

let example = Thread { print("task is running on \(Thread.current)")}
example.start()

๋จผ์ €, ์ด๋ ‡๊ฒŒ closure๋กœ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ๊ตฌ๋ฌธ ์ž์ฒด๋ฅผ ๋„˜๊ฒจ์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

class ThreadExample {
    init() {}
 
    func start() {
        Thread.detachNewThreadSelector(#selector(executeTask), toTarget: self, with: nil)
    }
 
    @objc
    private func executeTask() {
        print("Task is running on \(Thread.current))
    }
}
 
let example = ThreadExample()
example.start()

๋‘๋ฒˆ์งธ๋กœ๋Š” Class๋ฅผ ๋งŒ๋“ค๊ณ , ์Šค๋ ˆ๋“œ ๋งŒ๋“œ๋Š” ์ฝ”๋“œ ์ž‘์„ฑํ›„, ๋™์ž‘ํ•˜๊ณ  ์‹ถ์€ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ์Šค๋ ˆ๋“œ์˜ ๋ฆฌ์†Œ์Šค๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜๋Š” ์‹œ์ ์— ์‹œ์Šคํ…œ์— ์˜ํ•ด ์ž๋™์œผ๋กœ ํšŒ์ˆ˜๋œ๋‹ค.

NSObject๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Thread ๋งŒ๋“ค๊ธฐ

class ThreadExample: NSObject {
    func start() {
        self.performSelector(inBackground: #selector(executeTask), with: nil)
        // ๋˜๋Š”..
        self.performSelector(onMainThread: #selector(executeTask), with: self, waitUntilDone: true)
    }
 
    @objc
    private func executeTask() {
        print("Task is running on \(Thread.current)")
    }
}
 
let example = ThreadExample()
example.start()

performSelector ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ง€์ •ํ•œ ๋ฉ”์„œ๋“œ๋Š” main thread ์œ„์—์„œ ์‹คํ–‰๋˜๊ฒŒ ๋œ๋‹ค.

Thread๋กœ๋ถ€ํ„ฐ ๋ฉ€์–ด์ง€์ž.

ํ•˜์ง€๋งŒ iOS์—์„œ๋Š” ์ด๋ ‡๊ฒŒ ์ง์ ‘ ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

  1. ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์Šค๋ ˆ๋“œ ์ˆ˜๋Š” ํ˜„์žฌ ์‹œ์Šคํ…œ ๋กœ๋“œ ๋ฐ ํ•˜๋“œ์›จ์–ด์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋‹ค.
  2. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ˆ˜ํ–‰๋˜๋Š” ์ž‘์—…๋Ÿ‰๋„, ๋ณ€ํ™”ํ•˜๋Š” ์‹œ์Šคํ…œ ์ƒํƒœ์— ๋งž๊ฒŒ ๋™์ ์œผ๋กœ ํ™•์žฅ๊ฐ€๋Šฅํ•ด์•ผ ํ•จ

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

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

์ด๋ฅผ ํ†ตํ•ด, ์Šค๋ ˆ๋“œ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ ๋„ ๋ชจ๋“  ์ž‘์—…์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ์ˆ ์„ ์ œ๊ณตํ•œ๋‹ค.

  • Grand Central Dispatch(GCD)
  • Operation Queue

์ •๋ฆฌ

  • concurrency์™€ parallelism์€ ๋‹ค๋ฅด๋‹ค. ๋…ผ๋ฆฌ์ , ๋ฌผ๋ฆฌ์  ๊ตฌ๋ถ„์ด ์žˆ๋‹ค.
  • Thread๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • Thread ๊ด€๋ฆฌ๊ฐ€ ์ƒ๋‹นํžˆ ๋ณต์žกํ•˜๊ณ  ๋ฌธ์ œ ์†Œ์ง€๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ. ๊ทธ๋ž˜์„œ Apple์ด ์ œ๊ณตํ•˜๋Š” GCD, Operation Queue๊ฐ€ ์žˆ๋‹ค.

๋‹ค์Œ ๊ธ€์—์„œ๋Š” GCD์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋„๋ก ํ•˜์ž.

Reference