아래는 작업을 하는데 시간이 오래 걸리는 예시이다.
func fetchData() {
var data: [String] = []
for num in 0..<10000 {
data.append("\(num)")
}
}
이 함수를 View Model에 연결해 보면 다음과 같다.
class ThreadViewModel: ObservableObject {
@Published var dataArray: [String] = []
func fetchData() {
var data: [String] = []
for num in 0..<10000 {
data.append("\(num)")
}
dataArray = data
}
}
View Model에서 fetchData()
라는 함수를 실행하면 0부터 9999까지 루프를 돌면서 배열을 만들고 그 배열을 Observable Data에 집어넣게 되므로, 작업에서 꽤 많은 시간이 소요된다.
속도를 체감하기 위해서 간단하게 View에 연결하면 다음과 같다.
struct ThreadView: View {
@StateObject var viewModel: ThreadViewModel = .init()
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack {
Button(action: {
viewModel.fetchData()
}) {
Text("Load Data")
}
ForEach(viewModel.dataArray, id: \.self) { data in
Text(data)
}
}
}
}
}
Simulator에서 실행해보면 Load Data 버튼을 누르고 약 5초 뒤에나 화면에 나타나게 된다.
실제로 Xcode Debug Navigator에서 CPU 사용량을 확인해보면 다음과 같다.
오랜 시간이 걸리는 작업을 메인 스레드인 Thread 1에서 다 부담하니까 사진처럼 CPU 사용량이 한 번에 84%까지 치솟는 것을 볼 수 있다.
그러나 여러 스레드에서 동시에 실행하도록 설정을 해주면 이 문제를 조금이나마 해결할 수 있다.
func fetchData() {
DispatchQueue.global().async {
var data: [String] = []
for num in 0..<10000 {
data.append("\(num)")
}
DispatchQueue.main.async { // UI 수정은 항상 Main Thread에서 진행
self.dataArray = data
}
}
}
위와 같이 DispatchQueue.global().async 클로져를 이용해서 함수 내용을 감싸주고 CPU 사용량을 확인해보면 다음 사진처럼 확연히 사용량이 줄어든 것을 볼 수 있다.
이처럼 시간이 오래 걸리는 작업은 메인 스레드에서 담당하는 것이 아니라 여러 스레드에서 분산하여 실행하는 것이 효과적이다.