일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
Tags
- WWDC
- rxswift
- ios #swift #uialertcontroller #메서드 스위즐링
- Opensource
- Swift
- 부트캠프
- 코코아 인터널스
- 알고리즘
- World
- 단위 테스트
- boostcamp
- Cocoa Internals
- OS
- SwiftUI
- Algorithm
- notion
- 부스트캠프
- 디자인패턴
- 커스텀 뷰
- 네이버 부캠
- development
- Hello
- IOS
- Design Pattern
- 개발
- 후기
- Tistory
Archives
- Today
- Total
꿈돌이랜드
Swift Concurrency를 공부하며 느낀점 본문
반응형
Swift Concurrency
- 사내에서 Swift Concurrency 스터디를 진행했습니다.
- Swift Concurrency는 Swift5.5 버전 부터 도입된 Swift 언어 차원의 비동기 처리 방식입니다
- Documentation
- 이 글에서는 개인적으로 Swift Concurrency를 공부하면서 중요하게 깨달은 내용에 대해 서술합니다.
1. 어떤 actor에 해당 변수, 함수가 “선언”되어있는지가 중요하다.
- GCD의 경우 선언이 중요한게 아니라 런타임에 어떤 dispatchqueue에 해당 작업이 들어가서 실행되는지가 중요했습니다.
- Swift Concurrency의 경우는 해당 변수와 함수가 “선언된 위치”가 곧 어떤 스레드(엄밀히 말하면 actor)에서 동작할지를 결정합니다.
- 이를 흔히 다양한 교육자료에서 격리(isolated)라고 표현이 되는데, 직역으로는 당연히 맞는 말이지만, 처음 공부하는 입장에서는 어렵게 느껴지는 요인이었습니다.
class GCDExample {
private let queue = DispatchQueue(label: "com.example.gcd", attributes: .concurrent)
private var counter = 0
func increment() {
queue.async {
self.counter += 1
print("GCD Counter: \(self.counter)")
}
}
}
let gcdExample = GCDExample()
gcdExample.increment()
// Swift Concurrency
actor CounterActor {
private var counter = 0
func increment() {
counter += 1
print("Actor Counter: \(counter)")
}
}
let counterActor = CounterActor()
Task {
await counterActor.increment()
}
2. 어떤 스레드에서 실행되는지 보다는 어떤 “actor”에서 실행되는지를 생각하자
- Swift Concurrency는 미리 스레드를 대략 CPU 코어 수 만큼 여럿 만들어 놓고(협력적 스레드풀, Cooperative Thread pool) 이 중 쉬고 있는 스레드를 골라서 실행되게 하는 방법입니다.
- actor는 내부에 unownedExecutor라는 큐를 통해 본인의 변수나 함수에 접근하는 task를 순차적으로 실행되게 하여 data race를 방지합니다.
- await 키워드는 액터를 전환하면서, 해당 액터로부터의 작업을 기다리는 키워드로 이해하면 되겠습니다.
- 실행되는 스레드는 시스템이 알아서 지정해줍니다.
- 단 MainActor는 반드시 메인 스레드에서 작동함을 보장합니다.
3. 암시적인(숨겨진) 주변 문맥을 숙지해야한다.
- UIKit, SwiftUI 에서 제공하는 다양한 클래스들은 MainActor로 마킹되어 있어, 메인스레드에서 실행되는 것을 보장합니다.
- UIViewController 공식문서 선언부
- @MainActor class UIViewController
- SwiftUI View 프로토콜역시 MainActor로 마킹되어있습니다.
- 따라서 UI LifeCycle 메서드내에 선언된 Task 들은 MainActor에서 실행되는 Task입니다.
- Task는 주변 actor 컨텍스트를 상속받습니다.
- 단, Task.detached로 이를 끊을 수 있습니다.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 이 Task는 MainActor를 상속받음 (메인 스레드에서 실행됨)
Task {
print("Executing on Main Thread: \\(Thread.isMainThread)") // true
}
// Task.detached를 사용하면 MainActor 컨텍스트에서 벗어남 (백그라운드에서 실행될 수 있음)
Task.detached {
print("Executing on Background Thread: \\(Thread.isMainThread)") // false (일반적으로)
}
}
}
- 만약 아무런 컨텍스트없는 Task의 경우 명시적으로 @MainActor를 지정하지 않는 한 백그라운드에서 실행될 수 있습니다.
- 어떤 actor에도 속하지 않는 글로벌 컨텍스트에서 실행됩니다.
반응형
'Programming > Swift' 카테고리의 다른 글
[Swift] Result 타입 (0) | 2023.10.20 |
---|---|
[Swift] Array의 shuffle() 메서드 (Fisher-Yates 알고리즘) (0) | 2023.08.31 |
[Swift] Swift5.7 이후의 Regex (0) | 2023.08.30 |
[Swift] 클래스와 구조체중 어느 것을 선택해야 할까 (0) | 2023.08.12 |
[Swift] Target-Action 의 동작 원리를 알아보기 (0) | 2023.07.23 |