class AsyncAwaitBootcampViewModel: ObservableObject {
@Published var dataArray: [String] = []
func addTitle1() {
self.dataArray.append("Title1: \(Thread.current)")
}
}
struct AsyncAwaitBootcamp: View {
@StateObject private var viewModel = AsyncAwaitBootcampViewModel()
var body: some View {
List {
ForEach(viewModel.dataArray, id: \.self) { data in
Text(data)
}
}
.onAppear {
viewModel.addTitle1()
}
}
}
요런 뷰랑 뷰모델이 있다고 해봅시다
Thread.current로 append되는 로직이 어디서 실행되는지 살펴보면 메인스레드에서 진행되는 걸 알 수 있음
2초 정도 딜레이 준다고 해도 여전히 메인 스레드에서 동작함!
func addTitle2() {
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
let title = "Title2 : \(Thread.current)"
DispatchQueue.main.async {
self.dataArray.append(title)
}
}
}
요런 두번째 메소드를 만들어봤다고 해봅시다.
global 스레드로 해줬음!
![]() | ![]() |
---|
첫번째메소드는 메인스레드
두번째메소드는 백그라운드 스레드로 넘어간 걸 볼 수 있음
![]() | ![]() |
---|
이렇게 main 큐안에 또 어펜드하는 로직이 있으면 이건 다시 메인으로 가는걸 볼 수 있구요
async 메소드를 하나 만들어줍시다
![]() | ![]() |
---|
어라랏
여전히 메인스레드네?!
async 키워드가 붙는다고 항상 백그라운드 스레드에서 동작되는 게 아님을 알 수 있음
(하지만 지금 버전의 엑코에선 시뮬레이터에서 아예 안나옴 async에서 Thread.current 클래스를 쓸 수 없다고하네용)
DispatchQueue.main.asyncAfter 같은 것처럼 delay를 주는 게
Task에선 .sleep임!
![]() | ![]() |
---|
author2가 백그라운드 스레드로 바꼈네?!
따로 스레드를 바꾸겠다고 명시하지 않았는데 알아서 백그라운드 스레드로 넘어갔음
![]() | ![]() |
---|
MainActor를 붙이게되면 다시 메인스레드로 넘어갑니다~!
그러면 메소드를 한번 바꿔볼까요?
![]() | ![]() |
---|
이건 또 메인 스레드에서 다 실행이되네!
await은 백그라운드 스레드에서 실행될 수도 있고 아닐 수도 있는데
결과를 기다린다는 느낌인 것 같다.
이 과정이 백그라운드 스레드에서 동작하게 되면서 UI업뎃을 하면 안되니까 Actor라는 애를 사용해서 Main 스레드로 옮겨주는 거고.
이걸 addAuthor1메소드 마지막에 추가해줘보자
플로우를 이해해야합니다!
async 로직이지만 평소에 작성하던 코드들처럼 순서대로 실행이 되는 걸 볼 수 있죠?!
이게 async await의 힘인가?!!
await의 결과값이 도착하기 전까지 fianlText 추가하는 로직은 실행되지 않습니다!!!
요렇게 순서대로 작성해줘도 됨
(위에꺼랑 다른 점은 addAuthor1에 await로직 넣어주느냐 아니면 Task 에서 따로따로 await 해서 작성해주느냐)
근데 이러면 두번기다리는거라 더 효율적인 방법이 있는데 추후에 알아보도록 합시다
(백에서 같이 돌아가게하고 순서대로 하는 방법이 있나봄)