[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

🍎 Apple/SwiftUI

[SwiftUI] 관찰 중인 데이터를 변경하는 작업을 MainActor 환경에서 해야하는 이유

inu 2023. 10. 28. 15:02
반응형

이미지 소스 및 정보 출처 : WWDC21 Discover concurrency in SwiftUI


Run loop

SwiftUI에서 View는 위와 같은 방식으로 업데이트된다. 이 때 이를 실현시켜주는 것이 Run Loop이다. Rup Loop는 MainActor에서만 동작한다.

  • MainActor : Main Thread에서의 동작을 보장하는 Actor

Example

이러면 Main Thread를 기반으로 작업을 처리하는 MainActor가 fetchPhotos 메서드로 인해 아무런 일도 수행하지 못한다. 그럼 update 함수를 async로 감싸면 괜찮지 않을까?

하지만 이렇게해도 문제가 발생한다.

  • 이전 코드에서는 비록 fetchPhotos 메서드가 Main Thread를 점유하고 있기는 했지만 모든 것이 하나의 Thread 안에서 동작했다. 따라서 [ObejctWillChange 호출 → Items에 item 할당(상태변화) → Run loop tick 동작(UI반영)] 이 순서가 보장되었다.
  • 하지만 위 코드에서 fetchPhotos 메서드 작업과 ObjectWillChange, items 목록의 실질적 변화는 Main Thread가 아닌 다른 Thread에서 동작한다. 그렇지만 Run loop tick은 여전히 Main Thread(Main Actor)에서 동작한다.
  • 그래서 [ObejctWillChange 호출 → Run loop tick 동작(UI반영) → Items에 item 할당(상태변화)] 순서로 동작할수도 있는 위험이 생기는 것이다.

(ObjectWillChange에서 변화전 snapshot을 찍고 이를 기반으로 runloop때 snapshot 대비 변화를 비교해서 UI에 반영해야하는데 그렇게 하지 못하는 것)

그래서 async/await를 활용해서 다른 스레드로는 fecthPhotos 작업만 동작하도록한다. 이렇게하면 데이터 변경작업 자체는 MainActor에서 실행되면서 [ObejctWillChange 호출 → Items에 item 할당(상태변화) → Run loop tick 동작(UI반영)] 이 순서가 보장된다.

반응형