Skip to content

ictechgy/ios-bank-manager

ย 
ย 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

75 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ’ท ์€ํ–‰์ฐฝ๊ตฌ ๋งค๋‹ˆ์ € ํ”„๋กœ์ ํŠธ

ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„: 2021๋…„ 7์›” 26์ผ ~ 8์›” 6์ผ

with Coden, Joey.
ย 

UML - ์ˆ˜์ • ์ „

UML Ver.1 ย 

UML - ์ˆ˜์ • ํ›„

UML Ver.2

ย ย 

STEP1 - LinkedList๋กœ Queue ํƒ€์ž… ๊ตฌํ˜„

๐Ÿ“– ์ฃผ์š” ํ•™์Šต ๊ฐœ๋…

LinkedList ์ž๋ฃŒ๊ตฌ์กฐ์˜ ์ดํ•ด ๋ฐ ๊ตฌํ˜„

LinkedList ์ฝ”๋“œ
class Node<T> {
    var data: T?
    var next: Node<T>?
    
    init(with data: T) {
        self.data = data
    }
    
    fileprivate init() {
        self.data = nil
    }
}

struct LinkedList<T> {
    private var head: Node<T>
    private var tail: Node<T>
    
    var peek: Node<T>? {
        return head.next
    }
    
    var isEmpty: Bool {
        return head === tail
    }
    
    init() {
        let dummyNode = Node<T>()
        head = dummyNode
        tail = dummyNode
    }
    
    func push(data: T) {
        let newNode = Node(with: data)
        newNode.next = head.next
        head.next = newNode
    }
    
    mutating func append(data: T) {
        let newNode = Node(with: data)
        tail.next = newNode
        tail = newNode
    }
    
    func contains(_ targetNode: Node<T>) -> Bool {
        var currentNode = head
        while let nextNode = currentNode.next, nextNode !== targetNode {
            currentNode = nextNode
        }
        return currentNode !== tail
    }
    
    mutating func insert(data: T, after targetNode: Node<T>) {
        guard self.contains(targetNode) else {
            return
        }
        let newNode = Node(with: data)
        newNode.next = targetNode.next
        targetNode.next = newNode
        if targetNode === tail {
            tail = newNode
        }
    }
    
    mutating func pop() -> Node<T>? {
        if self.isEmpty {
            return nil
        }
        let frontNode = head.next
        head.next = frontNode?.next
        if frontNode === tail {
            tail = head
        }
        return frontNode
    }
    
    mutating func removeLast() -> Node<T>? {
        if self.isEmpty {
            return nil
        }
        var currentNode = head
        while let nextNode = currentNode.next, nextNode !== tail {
            currentNode = nextNode
        }
        let rearNode = tail
        tail = currentNode
        return rearNode
    }
    
    mutating func remove(after targetNode: Node<T>) -> Node<T>? {
        guard self.contains(targetNode) else {
            return nil
        }
        let nodeToRemove = targetNode.next
        targetNode.next = nodeToRemove?.next
        if nodeToRemove === tail {
            tail = targetNode
        }
        return nodeToRemove
    }
    
    mutating func clear() {
        head.next = nil
        tail = head
    }
}

Dummy Node

  • Dummy Node์™€ tail์„ ํ™œ์šฉํ•ด ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๊นŒ์ง€ ํƒ์ƒ‰ํ•˜๋Š” ๊ณผ์ •์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค. (์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๋‚ฎ์ถค)
  • Dummy Node์˜ Data์— ๋“ค์–ด๊ฐˆ ๊ฐ’์„ ๊ณ ๋ฏผํ–ˆ๋Š”๋ฐ, data ํƒ€์ž…์„ ์˜ต์…”๋„๋กœ ๋งŒ๋“ฆ์œผ๋กœ์จ nil์ด ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.

ย 

Reference Counting

  • LinkedList๋ฅผ ํ•ด์ œํ•  ๋•Œ head.next = nil๋กœ ๋‹ค์Œ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ–ˆ๋‹ค. ์ด์ „ ๋…ธ๋“œ๊ฐ€ ์‚ฌ๋ผ์ง€๋ฉด ๋‹ค์Œ ๋…ธ๋“œ์˜ ์ฐธ์กฐ๊ฐ€ ์‚ฌ๋ผ์ ธ ์—ฐ์‡„์ ์œผ๋กœ ๋‹ค์Œ ๋…ธ๋“œ๋“ค์ด ํ•ด์ œ๋œ๋‹ค.
  • ๋‹จ, ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋Š” ์ถ”๊ฐ€์ ์œผ๋กœ tail์—์„œ์˜ ์ฐธ์กฐ๋„ ์ œ๊ฑฐํ•ด ํ•ด์ œํ–ˆ๋‹ค. ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋Š” ์ด์ „ ๋…ธ๋“œ์™€ tail์— ์˜ํ•ด ๋‘ ๋ฒˆ ์ฐธ์กฐ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. (ARC์— ๋Œ€ํ•œ ์ดํ•ด)

ย 

Generics

  • Generics ๊ฐœ๋…์„ ์ ์šฉํ•ด LinkedList์— ๋‹ค์–‘ํ•œ ํƒ€์ž…์„ ๋‹ด์„ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

ย 

Queue

  • ํ๋Š” ์„ ์ž…์„ ์ถœ(FIFO)์˜ ํŠน์ง•์„ ๊ฐ€์ง€๋Š” ADT์ด๋‹ค.
  • ์ผ์ƒ์ƒํ™œ์—์„œ์˜ ๋Œ€๊ธฐ์—ด์„ ์˜ˆ๋กœ ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • enqueue, dequeue๋Š” ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ด๋ฉฐ peek, isEmpty, clear๋“ฑ๋„ ์ถ”๊ฐ€์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ๋Š” ๋ฐฐ์—ด๋กœ๋„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๋กœ๋„ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

ย 

Unit Test

  • ํ…Œ์ŠคํŠธํ•  ํƒ€์ž…์„ setUp() ์—์„œ ์ดˆ๊ธฐํ™” ํ•ด์คฌ๋‹ค.

  • ํ•˜์ง€๋งŒ ๋‹ค์Œ ํ…Œ์ŠคํŠธ์ฒ˜๋Ÿผ ํƒ€์ž…์„ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜ ๋‚ด์˜ given์—์„œ ํ•œ ๋ฒˆ ๋” ์ƒ์„ฑ์„ ํ•ด์ฃผ์—ˆ๋‹ค. ํ˜น์‹œ setUp() ์—์„œ sut์— ๋‹ค๋ฅธ ์กฐ์ž‘์ด ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•ด ํ•œ ๋ฒˆ ๋” ์ดˆ๊ธฐํ™”๋ฅผ ํ•จ์œผ๋กœ์จ ์–ด๋– ํ•œ ๊ฐ’๋„ ๋‹ด๊ธฐ์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์žฅ&๋ช…์‹œํ–ˆ๋‹ค.

    func test_ํ๋ฅผ์ƒˆ๋กœ์ƒ์„ฑํ•˜๊ณ _isEmptyํ•ด๋ณด๋ฉด_true์ด๋‹ค() {
        //given
        sut = Queue()
        //when
        let outputValue = sut.isEmpty
        //then
        XCTAssertTrue(outputValue)
    }

ย 

STEP2 - Queue ํ™œ์šฉ๊ณผ ๋™์‹œ์„ฑ ๊ธฐ์ดˆ

๐Ÿ“– ์ฃผ์š” ํ•™์Šต ๊ฐœ๋…

Serial VS. Concurrent

Serial

  • ํ•œ๋ฒˆ์— ํ•˜๋‚˜๋งŒ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ๊ฐœ๋…
  • Serial DispatchQueue์— ๋งŽ์€ Task๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ์ด๋Š” ํ•˜๋‚˜์˜ ์“ฐ๋ ˆ๋“œ์—์„œ ์ˆœ์ฐจ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๊ฒŒ ๋จ
  • Thread Pool์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ์“ฐ๋ ˆ๋“œ๋Š” ํ•˜๋‚˜๋ฟ์ด์ง€๋งŒ ๋งค Task๋งˆ๋‹ค ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์ฒ˜๋ฆฌ์‹œํ‚ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

Concurrent

  • ํ•œ๋ฒˆ์— ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ๊ฐœ๋…
  • Concurrent DispatchQueue์— ๋งŽ์€ Task๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ด๋Š” ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ์—์„œ ๋™์‹œ์— ์ˆ˜ํ–‰๋˜๊ฒŒ ๋จ
  • Thread Pool์—์„œ ๋ช‡๊ฐœ์˜ ์“ฐ๋ ˆ๋“œ๋ฅผ ๊ฐ€์ ธ์˜ฌ์ง€๋Š” ์•Œ ์ˆ˜ ์—†๋‹ค.(๋‹ค๋งŒ iOS ํ™˜๊ฒฝ์—์„œ ๋ชจ๋“  DispatchQueue๊ฐ€ ๊ฐ€์ ธ๋‹ค๊ฐ€ ์“ฐ๋Š” ์“ฐ๋ ˆ๋“œ ์ด ํ•ฉ์€ 64๊ฐœ๋ฅผ ๋„˜์ง€ ๋ชปํ•œ๋‹ค.)

ย 

Sync VS. Async - ์ž‘์—… ์™„๋ฃŒ์—ฌ๋ถ€๋ฅผ ๋ˆ„๊ฐ€ ์‹ ๊ฒฝ์“ฐ๋Š”๊ฐ€

Sync

  • ๋™๊ธฐ์ ์œผ๋กœ ์ˆ˜ํ–‰์‹œํ‚จ๋‹ค.
  • ์ž‘์—… ์™„๋ฃŒ์—ฌ๋ถ€๋Š” ํ˜ธ์ถœํ•œ ์ชฝ์—์„œ ์‹ ๊ฒฝ์“ด๋‹ค.
  • ์ž‘์—…์„ ๋ณด๋‚ธ ์ชฝ์—์„œ ์ž‘์—…์ด ๋๋‚˜๊ธฐ๋ฅผ(return) ๊ธฐ๋‹ค๋ฆฌ๋Š” ํ˜•ํƒœ โ†’ Block๊ณผ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ™์ด ์“ฐ์ž„
  • Non-Block์ธ ๊ฒฝ์šฐ ํ˜ธ์ถœํ•œ ์ชฝ์—์„œ ๋ถ€ํƒํ•œ ์ผ์ด ๋๋‚ฌ๋Š”์ง€๋ฅผ ๊ณ„์† ๋ฌผ์–ด๋ณด๊ฒŒ ๋จ

Async

  • ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ˆ˜ํ–‰์‹œํ‚จ๋‹ค
  • ์ž‘์—… ์™„๋ฃŒ์—ฌ๋ถ€๋Š” ์ฝœ๋ฐฑ์ด ์‹ ๊ฒฝ์“ด๋‹ค.
  • ์ž‘์—…์„ ๋ณด๋‚ธ ์ชฝ์—์„œ๋Š” ์ž‘์—…์ด ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๋Š” ํ˜•ํƒœ โ†’ Non-Block๊ณผ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ™์ด ์“ฐ์ž„
  • Block์ธ ๊ฒฝ์šฐ ์ž‘์—…์„ ๋ถ€ํƒํ•˜๊ณ  ๋Œ์•„์™€๋„ ์•„๋ฌด๊ฒƒ๋„ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณดํ†ต ๊ฐ™์ด ์“ฐ์ด์ง€๋Š” ์•Š๋Š”๋‹ค.
  • ์ž‘์—…์ด ๋๋‚œ ๋’ค ์ฒ˜๋ฆฌํ•  ์ฝ”๋“œ๋ฅผ ์ฝœ๋ฐฑ์— ๋„ฃ์–ด๋‘๊ณ  ๋™์ž‘ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.

ย 

Block VS. Non-Block - ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๋กœ ๋ฆฌํ„ดํ•˜๋Š”๊ฐ€

Block

  • ํ˜ธ์ถœ๋œ ์ชฝ์˜ ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๋กœ return ๋˜์ง€ ์•Š์œผ๋ฉฐ ํ˜ธ์ถœํ•œ ์ชฝ์ด ์ผ์„ ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰์Œ

Non-Block

  • ํ˜ธ์ถœ๋œ ์ชฝ์˜ ํ•จ์ˆ˜๋Š” ๋ฐ”๋กœ return๋˜๋ฉฐ ํ˜ธ์ถœํ•œ ์ชฝ์€ ๋‹ค์Œ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์Œ

https://user-images.githubusercontent.com/39452092/128502366-542445ef-5618-42a3-bf4a-d9d867f71571.png

์•จ๋Ÿฐ์˜ Blocking Non-Blocking ์„ค๋ช… - Inflearn

ย 

Concurrency VS. Parrellel

Concurrency

  • ๋…ผ๋ฆฌ์ ์ธ ๊ฐœ๋…
  • ํ•˜๋‚˜์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ์˜ ์ผ์„ ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉด์„œ ์ˆ˜ํ–‰ํ•˜๋ฉด ์ด๋Š” ๋™์‹œ์— ์ˆ˜ํ–‰๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž„

Parrellel

  • ๋ฌผ๋ฆฌ์ ์ธ ๊ฐœ๋…
  • ์‹ค์ œ CPU์— ๋ฌผ๋ฆฌ์ ์ธ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ ์žˆ์–ด, ์—ฌ๋Ÿฌ ์ผ์„ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ณ‘๋ ฌ์„ฑ์€ ๋™์‹œ์„ฑ์„ ํฌํ•จํ•œ๋‹ค.

ย 

Thread

์†Œํ”„ํŠธ์›จ์–ด ์Šค๋ ˆ๋“œ

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

๋ฌผ๋ฆฌ์  ์Šค๋ ˆ๋“œ

  • ์‹ค์ œ๋กœ CPU๊ฐ€ ๊ฐ€์ง„ ๊ฒƒ๋“ค์€ ๋ฌผ๋ฆฌ์ ์ธ ์“ฐ๋ ˆ๋“œ
  • ๋ฌผ๋ฆฌ์ ์ธ ์“ฐ๋ ˆ๋“œ ํ•˜๋‚˜๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ ์†Œํ”„ํŠธ์›จ์–ด ์“ฐ๋ ˆ๋“œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • iOS์—์„œ๋Š” Thread Pool์ด๋ผ๋Š” ๊ฒƒ์ด ์žˆ์–ด DispatchQueue๋Š” ์ด๊ณณ์—์„œ ์“ฐ๋ ˆ๋“œ๋ฅผ ๊ฐ€์ ธ๋‹ค๊ฐ€ ์“ด๋‹ค.(์†Œํ”„ํŠธ์›จ์–ด ์“ฐ๋ ˆ๋“œ)

ย 

Thread.sleep(forTimeInterval:)

  • sleep(UInt) ๋ฅผ ํ˜ธ์ถœํ•ด Thread๋ฅผ ์ž ์‹œ ์ค‘์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Double ํƒ€์ž…์˜ ์‹œ๊ฐ„๋™์•ˆ Thread๋ฅผ ์ค‘์ง€ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ Thread.sleep(forTimeInterval:) ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋œ๋‹ค

ย 

Class vs Struct

  • Class๋ฅผ ์ฐธ์กฐํ•˜๋Š” Struct ์™€ Class๋ฅผ ์ฐธ์กฐํ•˜๋Š” Class ๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ๊ฒฝ์šฐ Class๋ฅผ ์ฐธ์กฐํ•˜๋Š” Struct ์˜ reference counting ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฌด์ฒ™ ํฌ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์œ„ ํƒ€์ž…์„ Struct๋ณด๋‹ค๋Š” Class๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๋Š” ๊ฒƒ์„ ๋ฐฐ์› ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ ํƒ€์ž…๋“ค์„ ๋ณต์‚ฌํ•  ์ผ์€ ์—†๊ธฐ ๋•Œ๋ฌธ์— Node๋ฅผ ์ œ์™ธํ•œ ํƒ€์ž…๋“ค์€ Struct๋กœ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ–ˆ๋‹ค.

ย 

Mutableํ•œ self๋Š” share(capture) ํ•  ์ˆ˜ ์—†๋‹ค.

  • DispatchQueue๋กœ ๋ณด๋‚ด๋Š” closure์—์„œ Struct์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ mutating self๋ฅผ captureํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ํƒ€์ž…์˜ ๊ฒฝ์šฐ class๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.
struct Camper {
    var name: String
		
    mutating func changeName(to newName: String) {
	name = "๋ญ˜๋กœ ๋ฐ”๊พธ์ฃ ?" //๊ฐ€๋Šฅํ•œ ๋ฌธ์žฅ
	DispatchQueue.global().async {
	    self.name = "์กฐ์ด!" //๋ถˆ๊ฐ€๋Šฅ. ํด๋กœ์ €๊ฐ€ mutableํ•œ self๋ฅผ ์บก์ณํ•ด์„œ ๊ฐ€์ง€๊ณ  ๋‚˜๊ฐ€๋ ค ํ•˜๊ธฐ ๋•Œ๋ฌธ
	}
    }
}

ย 

STEP3 - DispatchQueue๋ฅผ ํ†ตํ•œ ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ

๐Ÿ“– ์ฃผ์š” ํ•™์Šต ๊ฐœ๋…

DispatchQueue

DispatchQueue๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ queue์— closure ํ˜•ํƒœ์˜ ์ž‘์—…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” class๋‹ค. ์ž‘์—…์ด queue์— ์ถ”๊ฐ€๋˜๋ฉด GCD๋Š” ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์•Œ์•„์„œ Thread๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ž‘์—…์„ ๋ณ„๋„์˜ thread์— ๋ถ„๋ฐฐํ•ด ์ฒ˜๋ฆฌํ•œ๋‹ค.

  • ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ NSThread๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ณต์žกํ•˜๊ฒŒ ๋™์‹œ์„ฑ์„ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก, ์• ํ”Œ์—์„œ ์ถ”์ƒํ™”๋œ ํด๋ž˜์Šค๋กœ์จ ์ œ๊ณต
  • ์ฃผ์˜ํ•ด์•ผ ํ•  ๊ฒƒ์€ DispatchQueue์™€ Thread๋Š” ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์ด๋‹ค!

by vivi ๐Ÿฆœ

Task - ์‹คํ–‰๋  ์ž‘์—… Thread - ์ž‘์—…์ด ์‹คํ–‰๋˜๋Š” ํ๋ฆ„ Queue - ์ž‘์—… ์‹คํ–‰์ด ์˜ˆ์•ฝ๋œ ๋Œ€๊ธฐ์—ด (์š”์ฆ˜ ํ”Œ์ ์—์„œ ์ž์ฃผ ๋ณด๋Š” ํ FIFO ๋ฐฉ์‹์˜ ๐Ÿ˜‹)

concurrent / serial - queue๊ฐ€ ์ž‘์—…์„ thread์— ํ• ๋‹นํ•˜๋Š” ๋ฐฉ์‹์„ ๋‚˜ํƒ€๋ƒ„

sync / async - queue์— ์ž‘์—…์„ ํ• ๋‹น์‹œํ‚ค๋Š” ๋ฐฉ์‹

์š”๋ ‡๊ฒŒ ์ •๋ฆฌํ•ด๋ณด๋ฉด ์–ด๋–จ๊นŒ์šฉ

ย 

Main

์ฝ”๋“œ๊ฐ€ default๋กœ ๋Œ์•„๊ฐ€๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋กœ ์œ ์ผํ•œ ์Šค๋ ˆ๋“œ๋ฉฐ serial๋กœ ๋™์ž‘ํ•œ๋‹ค. UI์™€ ๊ด€๋ จ๋œ ์ž‘์—…๋“ค์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋„คํŠธ์›Œํฌ ์ž‘์—…๊ณผ ๊ฐ™์€ ๋งŽ์€ ์‹œ๊ฐ„์ด ์†Œ์š”๋˜๋Š” ์ž‘์—…์€ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰ํ•ด ์ตœ์ƒ์˜ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

  • ๋งŒ์•ฝ ๋„คํŠธ์›Œํฌ ์ž‘์—…๊ณผ ๊ฐ™์€ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ผ์„ ๋ฉ”์ธ์“ฐ๋ ˆ๋“œ์—์„œ ์ˆ˜ํ–‰์‹œํ‚ค๊ฒŒ ํ•œ๋‹ค๋ฉด ํ™”๋ฉด์ด ๋ฒ„๋ฒ…์ผ ์ˆ˜ ์žˆ๋‹ค. โ†’ Update Cycle์ด ์ง€์—ฐ๋˜๊ธฐ ๋•Œ๋ฌธ

    https://user-images.githubusercontent.com/39452092/128512637-e6d6478e-a1c9-43fa-91a0-cdc45029aae9.png

    ์•จ๋Ÿฐ์˜ Concurrency, GCD, Operation ๊ฐ•์˜

Global

  • ๋น„๋™๊ธฐ๋กœ ์ž‘์—…์ด ์ฒ˜๋ฆฌ๋˜๋Š” queue. ์„œ๋น„์Šค ํ’ˆ์งˆ(quality of service)์— ๋”ฐ๋ผ 6๊ฐ€์ง€๋กœ ๋ถ„๋ฅ˜๊ฐ€ ๋˜์–ด ์žˆ์œผ๋ฉฐ ๊ฐ queue๋Š” ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์„ ์ˆ˜๋ก ๋” ๋งŽ์€ Thread๋ฅผ ๋ฐฐ์น˜ํ•˜๊ณ  ๋ฐฐํ„ฐ๋ฆฌ๋ฅผ ๋” ์ง‘์ค‘ํ•ด์„œ ์ž‘์—…์„ ๋” ๋นจ๋ฆฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค. (qos๋ณ„๋กœ ํ๊ฐ€ ์“ธ ์ˆ˜ ์žˆ๋Š” ์“ฐ๋ ˆ๋“œ์˜ ๊ฐœ์ˆ˜์ œํ•œ์€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋‹ค๋งŒ ์“ฐ๋ ˆ๋“œํ’€๋กœ๋ถ€ํ„ฐ ๊ฐ€์ ธ์˜จ ์†Œํ”„ํŠธ์›จ์–ด ์“ฐ๋ ˆ๋“œ๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋ฌผ๋ฆฌ์ ์ธ ์“ฐ๋ ˆ๋“œ(๋˜๋Š” CPU)์— ๋” ๋นˆ๋ฒˆํžˆ ๋ฐฐ์น˜๋˜๋Š”์ง€๋Š” ๋‹ฌ๋ผ์ง„๋‹ค.)
  • .userInteractive, .userInitiated, .default, .utility, .background, .unspecified ๊ฐ€ ์žˆ์œผ๋ฉฐ default๋Š” DispatchQueue.global() ์ด๋ผ๊ณ ๋งŒ ๋ช…์‹œํ•ด์ค˜๋„ ๋œ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ default๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • qos์— ๋”ฐ๋ผ ํ ์ธ์Šคํ„ด์Šค๋Š” ๋ณ„๋„๋กœ ์ƒ์„ฑ๋œ๋‹ค.

Custom

  • ๊ธฐ๋ณธ์€ ์ง๋ ฌ๋กœ ๋™์ž‘ํ•˜๋Š” custom queue
  • Concurrentํ•˜๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋™์‹œ์„ฑ queue๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ณดํ†ต Global queue๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ์‹œ label์„ ์ง€์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ณ ์œ  identifier๋กœ์จ์˜ ๊ธฐ๋Šฅ์€ ์ˆ˜ํ–‰ํ•˜์ง€ ๋ชปํ•œ๋‹ค. (๊ฐ™์€ ๋ ˆ์ด๋ธ”๊ฐ’์„ ์ฃผ์–ด ์ƒ์„ฑํ•ด์ค˜๋„ ์„œ๋กœ ๋‹ค๋ฅธ ํ๋กœ ๋งŒ๋“ค์–ด์ง)

๐Ÿ’ก

Global ํ์ด๋“  Custom ํ์ด๋“  ์ด ์“ฐ๋ ˆ๋“œ ๊ฐœ์ˆ˜ ์ œํ•œ์€ 64๊ฐœ์ด๋‹ค.(iOS ๊ธฐ์ค€) ๋งŒ์•ฝ Global์—์„œ ์ด๋ฏธ 64๊ฐœ๋ฅผ ์“ฐ๊ณ  ์žˆ๋‹ค๋ฉด ํ๋ฅผ ์•„๋ฌด๋ฆฌ ๋” ๋งŒ๋“ค์–ด๋ดค์ž ํ•ด๋‹น ํ๋“ค์€ ์“ฐ๋ ˆ๋“œ๋ฅผ ์“ธ ์ˆ˜ ์—†๋‹ค. ๋‹ค๋งŒ ๊ฐ ํ๋งˆ๋‹ค ์“ฐ๋ ˆ๋“œ ์ œํ•œ์€ ๊ฑธ๋ ค์žˆ์ง€ ์•Š๋‹ค. (Operation Queue๋Š” ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ํ•œ๋‹ค.) ์ฐธ๊ณ 

ย 

ํด๋กœ์ €์™€ ARC (Capture list์— ๋Œ€ํ•œ ๊ณ ๋ฏผ)

  • DispatchQueue์— ๋„˜๊ฒจ์ฃผ๋Š” Task๋„ ํด๋กœ์ €์ด๊ธฐ ๋•Œ๋ฌธ์— Strong Reference Cycle์„ ์—ผ๋‘ํ•ด์•ผ ํ•œ๋‹ค.
  • ์ผ๋ฐ˜์ ์œผ๋กœ ํด๋กœ์ € ๋‚ด์—์„œ self๋ฅผ ์บก์ฒ˜ํ•œ๋‹ค๊ณ  ํ•ด๋„, ์ธ์Šคํ„ด์Šค๊ฐ€ DispatchQueue์— ๋ณด๋‚ด๋Š” Taskํด๋กœ์ €๋ฅผ ์ฐธ์กฐํ•˜์ง€๋Š” ์•Š๊ธฐ ๋•Œ๋ฌธ์— Strong Reference Cycle์€ ์ƒ๊ธฐ์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜๋„ ์œ ๋…ํ•˜๋„๋ก ํ•˜์ž.

ย 

Semaphore

  • ๊ฐ ์€ํ–‰์›์€ ๊ณ ๊ฐ์˜ ์—…๋ฌด๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๋งŒ์•ฝ ๊ฐ™์€ ์—…๋ฌด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์€ํ–‰์›์ด ๋‘˜์ด ์žˆ๋‹ค๋ฉด? ๋น„๋™๊ธฐ์ ์ธ ์ด ์ž‘์—…์˜ ๊ฐœ์ˆ˜๋ฅผ ์ œํ•œํ•˜๋Š” ๋ฐฉ์‹์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด semaphore ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.
  • Semaphore๋Š” ์ž„๊ณ„๊ตฌ์—ญ ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ๋ฐฉ์•ˆ ์ค‘ ํ•˜๋‚˜๋กœ ๋™์ผํ•œ ์ž์›์— ๋™์‹œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐœ์ˆ˜๋ฅผ ์˜๋ฏธํ•˜๋Š” ์ •์ˆ˜ ๋ณ€์ˆ˜๋‹ค. Semaphore๋Š” wait() (p์—ฐ์‚ฐ)๊ณผ signal() (v์—ฐ์‚ฐ) ์œผ๋กœ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ semaphore๊ฐ€ 0์ด๋ฉด ์ ‘๊ทผ์„ ์‹œ๋„ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋‚˜ ์Šค๋ ˆ๋“œ๋Š” ๋Œ€๊ธฐ๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค.
  • semaphore๊ฐ€ 0์ด๋ฉด ํ”„๋กœ์„ธ์Šค๋‚˜ ์Šค๋ ˆ๋“œ๋Š” wait() ์—์„œ ๋Œ€๊ธฐ๋ฅผ ํ•˜๋‹ค๊ฐ€ ์ ‘๊ทผ์ด ํ—ˆ์šฉ๋˜๋ฉด semaphore๋ฅผ 1 ๊ฐ์†Œ์‹œํ‚ค๊ณ  ์ ‘๊ทผํ•œ๋‹ค. ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ์ด ๋๋‚˜๋ฉด signal() ๋กœ semaphore๋ฅผ 1 ์ฆ๊ฐ€์‹œ์ผœ ์‚ฌ์šฉ์ด ๋๋‚ฌ์Œ์„ ์•Œ๋ฆฐ๋‹ค.
  • ๊ฐ™์€ ์—…๋ฌด๋ฅผ ํ•˜๋Š” ์€ํ–‰์›์˜ ์ˆ˜๊ฐ€ 2๋ผ๋ฉด DispatchSemaphore(value: 2) ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์จ DispatchQueue์— ๋™์‹œ์— ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” Task์˜ ์ตœ๋Œ€ ๊ฐœ์ˆ˜๋ฅผ ์ œํ•œํ–ˆ๋‹ค.

ย 

Thread safety of DispatchSemaphore

func serveCustomers() {
    let tellerGroup = DispatchGroup()
    while let currentCustomer = customerQueue.dequeue() {
        semaphore.wait()
        tellerGroup.enter()
        DispatchQueue.global().async {
            self.serve(customer: currentCustomer)
            self.semaphore.signal()
            tellerGroup.leave()
        }
    }
    tellerGroup.wait()
    departmentGroup.leave()
}
  • DispatchQueue๋กœ ๋น„๋™๊ธฐ ์ž‘์—…์„ ๋ณด๋‚ผ ๋•Œ semaphore.signal()๊ณผ tellerGroup.leave() ๋Š” ๊ณผ์—ฐ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๋™์‹œ์— ํ˜ธ์ถœ๋์„ ๋•Œ thread safeํ•œ์ง€ ์˜๋ฌธ์ด ๋“ค์—ˆ๋‹ค. Thread์™€ Semaphore์— ๊ด€ํ•œ ์Šคํƒ ํฌ๋“œ ๋Œ€ํ•™ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•ด๋ณด๋‹ˆ semaphore์˜ ์—ฐ์‚ฐ๋“ค์€ atomic ํ•˜๋‹ค๊ณ  ํ•œ๋‹ค. ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด ์–ด๋–ค ์ž‘์—…์ด atomic ํ•˜๋‹ค๋Š” ๊ฒƒ์€ ๊ฐ™์€ ์ž‘์—…์„ ์‹œ๋„ํ•˜๋Š” ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์— ์˜ํ•ด ๋ฐฉํ•ด๋ฐ›์„ ์ผ์ด ์—†๋‹ค. ์ฆ‰, semaphore์˜ ์—ฐ์‚ฐ๋“ค์€ thread safeํ•˜๋‹ค.
  • DispatchSemaphore์˜ ๊ณต์‹๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด "efficient implementation of a traditional counting semaphore" ๋ผ๊ณ  ์„ค๋ช…ํ•˜๊ณ  ์žˆ์œผ๋‹ˆ DispatchSemaphore ์—ญ์‹œ ์—ฐ์‚ฐ๋“ค์ด atomicํ•  ๊ฒƒ์ด๋ผ๊ณ  ์˜ˆ์ƒํ–ˆ๋‹ค. (thread safeํ•œ ์ž‘์—…์ด๋ผ๊ณ  ๋ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.)
  • DispatchGroup์— ๋Œ€ํ•ด์„œ๋Š” ์ฐพ์ง€ ๋ชปํ–ˆ์ง€๋งŒ thread safe ํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.
  • DispatchQueue๋Š” ์ž์ฒด์ ์œผ๋กœ thread safeํ•˜๋‹ค๊ณ  ํ•œ๋‹ค.

ย 

DispatchGroup

func serveCustomers() {
    departments.forEach { _, bankingDepartment in
        departmentGroup.enter()
        DispatchQueue.global().async {
            // ์ž‘์—…
            // departmentGroup.leave()
        }
    }
    departmentGroup.wait()
}
  • ๋น„๋™๊ธฐ์ ์ธ ์ž‘์—…๋“ค์ด ๋ชจ๋‘ ๋๋‚œ ์‹œ์ ์„ ์•Œ๊ณ  ์‹ถ์–ด DispatchGroup์„ ํ™œ์šฉํ–ˆ๋‹ค. ๋น„๋™๊ธฐ ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „ group.enter() , ๋น„๋™๊ธฐ ์ž‘์—…์ด ๋๋‚œ ํ›„ group.leave() ๋ฅผ ํ•˜๋„๋ก ํ•ด ์ž‘์—…์˜ ๊ฐœ์ˆ˜๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ group.wait() ๋กœ group์— ๋“ค์–ด๊ฐ„ ์ž‘์—…๋“ค์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋„๋ก ๊ตฌํ˜„ํ•ด ์ตœ์ข… ์™„๋ฃŒ ์‹œ์ ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

ย 

Mutual Exclusion

  • ์ƒํ˜ธ ๋ฐฐ์ œ๋ผ๊ณ  ํ•˜๋ฉฐ ๊ณต์œ ์ž์›์— ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ ‘๊ทผํ•˜๋ ค ํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

    ์ƒํ˜ธ ๋ฐฐ์ œ - ์œ„ํ‚ค๋ฐฑ๊ณผ

  • ์ƒํ˜ธ ๋ฐฐ์ œ ๊ธฐ๋ฒ•์—๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

    1. ๋ฐ์ปค ์•Œ๊ณ ๋ฆฌ์ฆ˜(์ตœ์ดˆ)
    2. ํ”ผํ„ฐ์Šจ ์•Œ๊ณ ๋ฆฌ์ฆ˜
    3. Lamport ๋นต์ง‘ ๐Ÿž ์•Œ๊ณ ๋ฆฌ์ฆ˜
    4. ๋ฎคํ…์Šค
    5. ์„ธ๋งˆํฌ์–ด
    6. ๋ชจ๋‹ˆํ„ฐ

    ย 

ํ™•์žฅ์„ฑ

  • BankingCategory๋Š” ์€ํ–‰์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์—…๋ฌด์˜ ์ข…๋ฅ˜, BankingDepartment๋Š” ํ•ด๋‹น ์—…๋ฌด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ถ€์„œ๋ฅผ ์ง€์นญํ•œ๋‹ค.
  • ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—๋Š” loan๊ณผ deposit ๋‘ ๊ฐ€์ง€ ์—…๋ฌด๋ฐ–์— ์—†๊ธฐ ๋•Œ๋ฌธ์— Bank์—์„œ ๊ฐ ๋ถ€์„œ๋ฅผ ํ”„๋กœํผํ‹ฐ๋กœ ๊ฐ–๊ณ  ์žˆ์–ด๋„ ๋˜์ง€๋งŒ ํ™•์žฅ์„ฑ์„ ๊ณ ๋ คํ•ด [BankingCategory:BankingDepartment] ํ˜•ํƒœ์˜ ๋”•์…”๋„ˆ๋ฆฌ๋กœ departments(๋ถ€์„œ)๋ฅผ ๊ด€๋ฆฌํ•˜๋„๋ก ํ–ˆ๋‹ค.
  • ์ด๋ฅผ ์œ„ํ•ด ์ƒ์„ฑ์ž์—์„œ departments์— ํ•„์š”ํ•œ ๊ฐ’๋“ค์„ ๊ฐ€๋ณ€์ธ์ž๋กœ ๋ฐ›๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.
struct Bank {
    private var departments = [BankingCategory:BankingDepartment]()
    
    init(departmentInformation: [(departmentCategory: BankingCategory, numberOfDepartmentTellers: Int)]) {
        departmentInformation.forEach { category, numberOfTellers in
            self.departments[category] = BankingDepartment(duty: category, numberOfBankTellers: numberOfTellers, departmentGroup: self.departmentGroup)
        }
    }
    // ...
}

ย 

Variadic Parameter

  • ๊ฐ€๋ณ€์ธ์ž๋ผ๊ณ  ํ•˜๋ฉฐ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ชฝ์—์„œ๋Š” argument๋ฅผ ์•ˆ ์ค„์ˆ˜๋„, ์—ฌ๋Ÿฌ๊ฐœ ์ค„ ์ˆ˜๋„ ์žˆ๋‹ค
func someVariadic(numbers: Int...) {
    numbers.forEach {
	//...
    }
}

someVariadic()
someVariadic(1)
someVariadic(1, 2, 3)
  • ์ฃผ์˜ํ•ด์•ผ ํ•  ์ 

    • ๋„˜๊ฒจ์ค„ ๋•Œ ๋ฐฐ์—ด๋กœ ๋„˜๊ฒจ์ฃผ์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ
    • ๋ฐ›์€ ์ชฝ์—์„œ๋Š” ๋ฐฐ์—ด์ด ๋œ๋‹ค๋Š” ๊ฒƒ(์œ„์˜ ๊ฒฝ์šฐ numbers์˜ ํƒ€์ž…์€ [Int]์ด๋‹ค.)

    ย 

UInt์— ๋Œ€ํ•˜์—ฌ

The Basics - The Swift Programming Language (Swift 5.5)

๐Ÿ’ก

Use UInt only when you specifically need an unsigned integer type with the same size as the platformโ€™s native word size. If this isnโ€™t the case, Int is preferred, even when the values to be stored are known to be nonnegative. A consistent use of Int for integer values aids code interoperability, avoids the need to convert between different number types, and matches integer type inference, as described in Type Safety and Type Inference.

UInt๋Š” ํ”Œ๋žซํผ์˜ ๊ณ ์œ  word size์™€ ๋™์ผํ•œ ํฌ๊ธฐ์˜ unsigned integer ํƒ€์ž…์ด ํ•„์š”ํ•  ๋•Œ์—๋งŒ ์‚ฌ์šฉํ•ด๋ผ. ๋งŒ์•ฝ ์ด ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, Int๋ฅผ ์ถ”์ฒœํ•œ๋‹ค. (์–‘์˜ ์ •์ˆ˜๊ฐ’๋งŒ์„ ์ €์žฅํ•œ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„) ์ •์ˆ˜๊ฐ’์— ๋Œ€ํ•ด Int ํƒ€์ž…์„ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์ฝ”๋“œ ์ƒํ˜ธ์šด์šฉ์„ฑ์„ ์ฆ๋Œ€์‹œํ‚ฌ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. (๋‹ค๋ฅธ ์ˆซ์ž ํƒ€์ž…๊ฐ„์— ๋ณ€ํ™˜๊ณผ์ •์ด ํ•„์š”์—†๊ฒŒ ๋˜๋ฉฐ, ์ •์ˆ˜ ํƒ€์ž…์˜ ํƒ€์ž…์ถ”๋ก ๊ณผ๋„ ์ผ์น˜ํ•˜๊ฒŒ ๋œ๋‹ค.)

  • ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ, word size๋ผ๋Š” ๊ฒƒ์€ ์ปดํ“จํ„ฐ์˜ 32-bit, 64-bit ์•„ํ‚คํ…์ณ๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ, ํ•ด๋‹น bit์™€ ๋™์ผํ•œ ์‚ฌ์ด์ฆˆ๋ฅผ ๊ฐ€์ง€๋Š” unsigned int๊ฐ€ ํ•„์š”ํ• ๋•Œ๋งŒ ์“ฐ๋ผ๋Š” ๊ฒƒ ๊ฐ™๋‹ค. (์ด๊ฑด ๋˜ ๋ฌด์Šจ ๋ง์ด์ง€)
  • Joey ๋‡Œํ”ผ์…œ - Int ์™€ UInt ๋ชจ๋‘ word size๋ฅผ ๊ฐ–๋Š”๋ฐ ์ด๋•Œ UInt๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ์–‘์ˆ˜ ๋ฒ”์œ„๊ฐ€ Int๋ณด๋‹ค ํ›จ์”ฌ ํฝ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Int๋กœ ํ‘œํ˜„ํ•˜์ง€ ๋ชปํ•˜๋Š” ํฌ๊ธฐ์˜ ์–‘์ˆ˜๋ฅผ ์„ ์–ธํ•ด์•ผํ•  ๋•Œ UInt๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ทธ ์™ธ์—๋Š” Int๋ฅผ ์‚ฌ์šฉํ•˜๋ผ๋Š” ์˜๋ฏธ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • UInt ๊ณต์‹๋ฌธ์„œ
  • ์–ด๋””์— ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•ด ๋ณผ ์ˆ˜ ์žˆ์„๊นŒ?

ย 

Namespace Pollution

  • ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ’์˜ ๋ณ€๊ฒฝ์ด ์ถ”์ ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ „์—ญ๋ณ€์ˆ˜๋Š” ์“ฐ์ง€ ๋ง๋ผ๊ณ  ํ•œ๋‹ค.
  • ๊ทธ๋ ‡๋‹ค๋ฉด ์ „์—ญ์ƒ์ˆ˜๋Š”? โ†’ Namespace Pollution์„ ๋ง‰๊ธฐ ์œ„ํ•ด struct, class, enum์— ๋„ฃ๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์ง ํ•  ์ˆ˜ ์žˆ๋‹ค.
enum SomeEnum {
    static let someGlobalConst = 100
}
  • ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ค‘์—์„œ๋„ enum์— ๋„ฃ๋Š” ์ด์œ ๋Š” case-less enum์ธ ๊ฒฝ์šฐ accidently ํ•˜๊ฒŒ instance๋ฅผ initiating ํ•  ์ผ์ด ์—†์œผ๋ฏ€๋กœ!

ํ—ท๊ฐˆ๋ฆด๋งŒํ•œ ๊ฒƒ๋“ค

DispatchQueue์— sync๋กœ Task๋ฅผ ๋„˜๊ธฐ๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•˜์—ฌ

๐Ÿถ DispatchQueue๋„ ์‚ฌ์‹ค ๋‘๊ฐœ์˜ ํ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—…์„ ๋ฐ›์•„๋“ค์ด๋Š” ํ์™€ ์ž‘์—…์„ ์“ฐ๋ ˆ๋“œ๋กœ(?) ๋‚ด๋ณด๋‚ด๋Š” ํ ์ด ๋‘ ๊ฐœ๋กœ์š”. ํŠน์ • ์“ฐ๋ ˆ๋“œ(์ด๋ฅผํ…Œ๋ฉด ๋ฉ”์ธ์“ฐ๋ ˆ๋“œ)์—์„œ ๋™์ž‘ํ•˜๋„๋ก ์ž‘์„ฑํ•œ ์ฝ”๋“œ์—์„œ DispatchQueue์— sync๋กœ Task๋ฅผ ๋ณด๋‚ด๋ฉด (์ด๋Š” ์ž‘์—…์„ ๋ฐ›์•„๋“ค์ด๋Š” ํ๋กœ ๋“ค์–ด๊ฐˆ ๊ฒƒ) ๋‹น์—ฐํžˆ ์ž‘์—…์„ ๋ณด๋‚ธ ํ•ด๋‹น ์“ฐ๋ ˆ๋“œ๋Š” block๋˜๋ฉด์„œ ํ์— ๋ณด๋‚ธ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ๊ฒ ์ฃ ? (์ด Task๋ฅผ ์•ž์œผ๋กœ A Task๋ผ๊ณ  ์นญํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.)

์ด ๋•Œ sync๋ฅผ ํ†ตํ•ด A Task๋ฅผ ๋ฐ›์€ DispatchQueu๋Š” ์ž‘์—…์„ ์“ฐ๋ ˆ๋“œ๋กœ ๋‚ด๋ณด๋‚ด๋Š” ํ ์˜ ๋‚ด๋ณด๋‚ด๋Š” ์ผ๋“ค(?)์„ ๋™๊ธฐ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค๊ณ  ํ•ด์š”. A Task ์ดํ›„์— ๋ฐ›์€ ์ž‘์—…๋“ค์€ 'A Task๊ฐ€ ์“ฐ๋ ˆ๋“œํ’€์—์„œ ๊ฐ€์ ธ์˜จ ์“ฐ๋ ˆ๋“œ์— ์˜ํ•ด ์‹คํ–‰์ด ์™„๋ฃŒ'๋˜์–ด์•ผ ์‹คํ–‰์ด ๋  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ์š”. (ํ ์ž์ฒด๊ฐ€ Concurrent๋ผ๊ณ  ํ•˜๋”๋ผ๋„ ์ด์™€๊ฐ™์ด ์ˆ˜ํ–‰๋จ) (A Task๋ฅผ ๋ฐ›์•˜์–ด๋„ ์ž‘์—…์„ ๋ฐ›์•„๋“ค์ด๋Š” ํ ๋Š” ๊ทธ๋Œ€๋กœ ๋‘๋ฏ€๋กœ ํ•ด๋‹น DispatchQueue๋Š” ๊ณ„์† ์ž‘์—…์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ)

๊ทธ๋Ÿฌ๋ฉด A Task๋ฅผ ๋ฐ›๊ธฐ ์ด์ „์— ํ์— ์กด์žฌํ–ˆ๋˜ Task๋“ค์€ ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? A Task๋ฅผ ๋ฐ›๊ธฐ ์ด์ „์— ๋จผ์ € ๋ฐ›์•˜๋˜ ์ž‘์—…๋“ค์€ ์ด๋ฏธ ์“ฐ๋ ˆ๋“œ ํ’€์—์„œ ๊ฐ€์ ธ์˜จ ์“ฐ๋ ˆ๋“œ์—์„œ ์‹คํ–‰์ค‘์ด๊ฑฐ๋‚˜ / ๊ฐ€๊นŒ์šด ๋ฏธ๋ž˜์— ์“ฐ๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. A Task์™€๋Š” ์ƒ๊ด€์—†์ด์š”. -> ์ œ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋งํฌ

ย 

์•„๋ž˜์˜ ์ธ์Šคํ„ด์Šค๋“ค์€ Thread-safeํ• ๊นŒ?

  1. DispatchQueue๋Š” ์ž์ฒด์ ์œผ๋กœ thread-safeํ•œ๊ฐ€?
  2. DispatchSemaphore๋Š” ์ž์ฒด์ ์œผ๋กœ thread-safeํ•œ๊ฐ€?
  3. DispatchGroup์€ ์ž์ฒด์ ์œผ๋กœ thread-safeํ•œ๊ฐ€?

โ†’ Step3์˜ thread-safe์— ํ•ด๋‹นํ•˜๋Š” ๋‚ด์šฉ๋“ค๊ณผ ๋™์ผํ•œ ๋‚ด์šฉ์ด๋‹ค. ์šฐ์„  ํ”„๋กœ์ ํŠธ์˜ ์ฝ”๋“œ ์ง„ํ–‰ ๊ฒฐ๊ณผ๋กœ ๋ดค์„ ๋•Œ์—๋Š” Thread-safeํ•œ ๊ฒƒ์œผ๋กœ ๋ณด์˜€๋‹ค.

DispatchQueue๋Š” Thread-Safeํ•˜๋‹ค.

์• ํ”Œ์˜ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฌธ์„œ

ย ย 

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Swift 100.0%