개발하는 동글 :]

[TIL],[Swift],[DispatchQueue] 본문

카테고리 없음

[TIL],[Swift],[DispatchQueue]

동글하다 2023. 8. 29. 21:43

1. DispatchQueue?

공식문서의 내용을 살펴보면 DispatchQueue는 앱의 기본 스레드 또는 백그라운드 스레드에서 작업의 동기 또는 비동기 실행을 관리하는 Class이다. 이 것을 확인해 보기 위해 아래의 두 개의 메서드를 만들어서 확인해 보자.

func shortWork(_ num:Int){
    DispatchQueue.global().async {
        print("shortWork[\(num)]Start")
        print("1")
        print("2")
        print("3")
        print("4")
        print("5")
        print("shortWork[\(num)]End")
    }
}

func longWork(_ num:Int){
    DispatchQueue.global().async {
        print("longWork[\(num)]Start")
        sleep(1)
        print("longWork[\(num)]End")
    }
}

2. DispatchQueue의 동작 순서

2.1 DispatchQueue 내부의 동작 순서

override func viewDidLoad() {
	super.viewDidLoad()
	self.shortWork(1)
}

위의 코드를 실행하였을 때의 결과이다.
이것으로 알 수 있는 것은 DispatchQueue의 내부는 동기적으로 동작하는 것을 알 수 있다.

2.2 외부에서의 DispatchQueue의 동작 순서

override func viewDidLoad() {
	super.viewDidLoad()
	self.longWork(1)
	self.longWork(2)
	self.longWork(3)
	self.longWork(4)
	self.longWork(5)        
}

위의 코드를 실행해 보았을 때의 결과를 확인해 보면 DispatchQueue는 외부에서 동작순서는 보장받지 못한다는 것을 알 수 있다.

3. 직렬큐(Serial),동시큐(Concurrent)

3.1. 직렬큐(Serial)

그럼 비동기적으로 처리하면서 순서를 보장받고 싶다면 어떡해야 할까?
아래의 코드처럼 직렬큐를 만들어 사용하면 된다.

let serialQueue = DispatchQueue(label: "some") //직렬큐 생성

override func viewDidLoad() {
    super.viewDidLoad()
    serialQueue.async {
        self.shortWork(1)
    }
    serialQueue.async {
        self.shortWork(2)
    }
    serialQueue.async {
        self.shortWork(3)
    }
}

func shortWork(_ num:Int){
    print("shortWork[\(num)]Start")
    print("shortWork[\(num)]End")
}

결과를 위의 global과 비교를 해본다면 이처럼 직렬큐를 사용하였을 때 같은 직렬큐 내부에서는 동기적으로 처리가 되는 것을 확인할 수 있다.

3.2 동시큐(Concurrent)

그럼 이번에는 초반의 예시와 같이 global이란 큐를 사용하여 같은 코드를 비교해 보자

let concurrentQueue = DispatchQueue.global()

override func viewDidLoad() {
    super.viewDidLoad()
    concurrentQueue.async {
        self.shortWork(1)
    }
    concurrentQueue.async {
        self.shortWork(2)
    }
    concurrentQueue.async {
        self.shortWork(3)
    }
    
}

func shortWork(_ num:Int){
    print("shortWork[\(num)]Start")
    print("shortWork[\(num)]End")
}

그럼 이전과 동일하게 순서가 보장받지 않는 상태가 된다.
이러한 코드와 결과를 통해 직렬큐와 동시큐의 차이를 알 수 있다.
그렇다면 모두가 다른 직렬큐를 사용하여 실행하였을 때에는 어떻게 될까?

let serialQueue1 = DispatchQueue(label: "1")
let serialQueue2 = DispatchQueue(label: "2")
let serialQueue3 = DispatchQueue(label: "3")

override func viewDidLoad() {
    super.viewDidLoad()
    serialQueue1.async {
        self.shortWork(1)
    }
    serialQueue2.async {
        self.shortWork(2)
    }
    serialQueue3.async {
        self.shortWork(3)
    }
    
}

func shortWork(_ num:Int){
    print("shortWork[\(num)]Start")
    print("shortWork[\(num)]End")
}

확인해 본 결과 모두 다른 직렬큐를 사용하는 것은 동시큐를 사용한 것과 같이 순서가 보장되지 않는 형태의 결과가 나왔다
이것으로 동시큐는 임의의 직렬큐들을 사용하는 것이 아닐까 하는 추측할 수 있다.

4. 큐의 종류

4.1 메인큐

let mainQueue = DispatchQueue.main

메인쓰레드를 의미하고, 직렬큐이다.
실제 앱에서는 UI관련작업들이 DispatchQueue.main(메인큐)에서 동작해야 한다.

4.2 글로벌 큐

let userInteractiveQueue = DispatchQueue.global(qos: .userInteractive)
let userInitiatedQueue = DispatchQueue.global(qos: .userInitiated)
let defaultQueue = DispatchQueue.global()  // 디폴트 글로벌큐
let utilityQueue = DispatchQueue.global(qos: .utility)
let backgroundQueue = DispatchQueue.global(qos: .background)
let unspecifiedQueue = DispatchQueue.global(qos: .unspecified)

6개의 qos를 가지고 있는 전역 직렬큐이다.

4.3 커스텀 큐

let someQueue = DispatchQueue(label: "some")

label에 따라 분류되며 기본적으로 직렬큐이며 동시큐 설정도 가능하다.