다음의 PR을 참고하면 좋아요.
https://github.com/DeveloperAcademy-POSTECH/MC3-Team9-BALANCEIAGA/pull/77
비동기 해보기.
다음 두 개를 사용해 볼거에요.
- DispatchQueue.global()
- DispatchGroup()
공식문서 https://developer.apple.com/documentation/dispatch/dispatchqueue
기본 대기열에서 작업 항목을 동기식으로 실행하려고 하면 데드락이 발생해요
어떻게 해결해야 할까요?
import Foundation
let queue1 = DispatchQueue(label: "example.queue1")
let queue2 = DispatchQueue(label: "example.queue2")
func task1() {
queue2.sync {
print("Task 1: Waiting for queue2")
queue1.sync {
print("Task 1: Executing on queue1")
}
}
}
func task2() {
queue1.sync {
print("Task 2: Waiting for queue1")
queue2.sync {
print("Task 2: Executing on queue2")
}
}
}
queue1.async {
task1()
}
queue2.async {
task2()
}
두 개의 큐 queue1과 queue2를 생성하고, task1, task2 함수가 각각 다른 큐에 실행되도록 만들었어요.
queue1과 queue2에 각각의 작업을 비동기로 추가하여 실행하고 있어요.
이 코드에서 task1은 queue2에서 동기적으로 queue1로 접근하려고 하고, task2는 queue1에서 동기적으로 queue2로 접근하려고 합니다. 이렇게 서로 다른 큐에서 블록된 상태에서 서로의 큐를 대기하게 되면 데드락이 발생할 수 있습니다.
데드락을 해결하자
let serialQueue = DispatchQueue(label: "com.example.serialQueue")
func task1() {
serialQueue.sync {
print("Task 1: Executing on serialQueue")
}
}
func task2() {
serialQueue.sync {
print("Task 2: Executing on serialQueue")
}
}
serialQueue.async {
task1()
}
serialQueue.async {
task2()
}
queue1.async {
task1()
queue2.async {
task2()
}
}
공식문서 https://developer.apple.com/documentation/dispatch/dispatchgroup
하나의 유닛으로서 우리가 관리하는 태스크들의 그룹이에요.
여러 작업 항목을 그룹에 연결하고 동일한 대기열 또는 다른 대기열에서 비동기식으로 실행하도록 예약할 수 있어요.
모든 작업이 완료되면 DispatchGroup은 핸들러를 통해 완료되었다는 것을 알릴 수 있어요.
import SwiftUI
struct ContentView: View {
@State private var isLoading = true
var body: some View {
VStack {
if isLoading {
Text("Loading...")
} else {
Text("Data Loaded!")
}
}
.onAppear {
let dispatchGroup = DispatchGroup()
// 비동기 작업 1
dispatchGroup.enter()
DispatchQueue.main.async {
self.fetchDataFromAPI1 {
dispatchGroup.leave()
}
}
// 비동기 작업 2
dispatchGroup.enter()
DispatchQueue.main.async {
self.fetchDataFromAPI2 {
dispatchGroup.leave()
}
}
// DispatchGroup의 모든 작업이 완료될 때까지 기다려요
dispatchGroup.notify(queue: .main) {
// 여기에 DispatchGroup의 모든 작업이 완료되었을 때 실행할 로직 추가해요
self.isLoading = false
self.anotherFunction()
}
}
}
// 예시를 위한 가상의 비동기 API 요청 함수 1
func fetchDataFromAPI1(completion: @escaping () -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
// 비동기 작업 시뮬레이션을 위해 3초 대기해요
completion()
}
}
// 예시를 위한 가상의 비동기 API 요청 함수 2
func fetchDataFromAPI2(completion: @escaping () -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + 5) {
// 비동기 작업 시뮬레이션을 위해 5초 대기해요
completion()
}
}
// 기타 다른 함수
func anotherFunction() {
// DispatchGroup의 모든 작업이 완료된 후에 실행되는 함수에요.
print("All async tasks completed. Running anotherFunction()")
// 이곳에 원하는 로직을 추가해요.
}
}
좋은 글 감사합니다. 자주 올게요 :)