Swift에서 동시성 프로그래밍하면 크게 GCD(Grand Central Dispatch)와 OperationQueue 두 가지로 나눌 수 있다.
두 가지 모두 가볍게..(낱낱이 파헤쳐볼라 그랬는데 그건 양이 너무 많아서 각각 따로 정리해야할듯..ㅎ) 파헤쳐보자.
GCD(Grand Central Dispatch)
GCD는 스레드 프로그래밍을 위해 Apple에서 제공하는 하위 레벨 C-based API이다. iOS 프로그래밍을 하면서 동시성을 처리하기 위해 가장 널리 사용된다.
GCD는 기본적으로 작업들(tasks)을 Queue에 배치하고 이를 비동기적으로 실행시킨다.
GCD의 Queue 크게 Main Queue와 Global Queue, Custom Queue 세 개로 나뉜다.
Main Queue
- 메인 스레드에서 처리하는 작업을 의미한다.
- Serial한 특성을 가지고 있다.
- 오직 한 개만 존재한다. (당연함.. 메인 스레드는 언제나 하나이기 때문.. Only One..)
- DispatchQueue에 대한 명시 없이 작성되는 코드들은 기본적으로 다 DispatchQueue.main 에서 실행된다.
DispatchQueue.main.async { ... }
위와 같은 코드로 사용 가능하다.
Global Queue
- Concurrent한 특성을 가지고 있다.
- QoS(Quality of Service)에 따라 작업의 중요도를 결정할 수 있으며, 6가지로 나뉜다.
→ userInteractive, userInitiated, default, utility, background, unspecified로 나뉨(뒤로 갈수록 후순위)
Custom Queue
- 아래와 같은 코드로 커스텀으로 만들어 사용한다.
DispatchQueue(label: "CustomQueue")
- 기본적으로 Serial 특성을 가졌지만 Concurrent로 설정 가능하다.
DispatchQueue(label: "CustomConcurrentQueue", attributes: .concurrent)
- Global Queue와 동일하게 QoS 설정 가능하다.
OperationQueue
OpertionQueue는 GCD위에 구축된 더 높은 레벨의 추상화이다. 즉, OperationQueue도 내부적으로 GCD를 사용해서 동작한다는 뜻이다 ! 그럼 OperationQueue는 왜 사용할까?
바로.. GCD보다 한 단계 업그레이드 된 놈이라 GCD가 할 수 없는 더 복잡한 일을 처리할 수 있기 때문에 사용된다. 예를 들면 task의 실행, 정지, 대기와 같은 실행 상태를 알 수 있고, 이를 사용하여 Operation들의 취소, 순서 지정 등 작업들의 복잡한 처리가 가능해진다.
Operation State
Operation에는 자신의 상태를 나타내는 상태값들이 존재한다. 이를 통해 현재 특정 Operation의 상태를 읽고 처리할 수 있게된다.
- Pending: Queue에 Operation이 추가된 상태
- Ready: Pending에서 모든 조건 만족 시 Ready로 변경
- Executing: start() 메서드를 호출하여 작업이 시작된 상태
- Finished: 작업이 완료된 상태로 Queue에서 Operation이 제거된다.
- Cancelled: Pending, Ready, Executing 3개의 상태에서만 변경 가능하여, Cancelled 상태가 되면 곧바로 Finished로 상태가 변하게 된다.
Operation 사용법
Operation은 클래스이다. 따라서 Operation를 subclassing하여 사용하면 된다.
class CustomOperation: Operation {
override func main() {
// setup() 함수처럼 사용
// 오버라이딩해서 사용한다.
}
}
main() 메서드 말고도 start(), isAsynchronous, isExecuting, isFinished 를 오버라이딩 하여 사용할 수 있다.
비동기 작업의 경우 보통 main()만 오버라이딩하여 사용하고 동기작업일 경우 나머지 메서드들과 프로퍼티들(start(), isAsynchronous, isExecuting, isFinished)을 오버라이딩해야한다.
BlockOperation 사용
간단한 작업의 경우 BlockOperation을 사용해서 Operation을 생성할 수 있다.
let blockOperaion = BlockOperation {
// 실행할 작업 코드
}
let queue = OperationQueue()
queue.addOperation(blockOperaion)
Serial vs Concurrent
GCD와 다르게 OperationQueue는 큐가 한 가지만 존재한다. 그럼 직렬과 동시는 어떻게 구현해..? 할 것이다.
OperationQueue에는 maxConcurrentOperationCount라는 프로퍼티가 있다. (아따 이름 길다 ~)
maxConcurrentOperationCount는 동시에 진행할 작업의 수를 나타낸다.
이 값은 default 값이 -1인데, 아래와 같이 이를 1로 설정해주면 직렬처럼 사용할 수 있게 된다. (동시에 하나의 작업만 실행하겠다는 의미이므로 Serial과 동일하다고 볼 수 있다.)
let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 1
QoS
OperationQueue도 QoS를 지정할 수 있다 !
OperationQueue를 생성하면 기본값은 .background로 되어있다. .qualityOfService 프로퍼티를 사용해서 설정해줄 수 있다.
let operationQueue = OperationQueue()
operationQueue.qualityOfService = .userInteractive
큐 뿐만 아니라 작업에 해당하는 Operation 자체에도 QoS를 지정해줄 수 있다. Operation의 경우 기본값은 .default 이다.
말고도 OperationQueue의 기능은 무궁무진한데 .. 이는 공식문서를 읽어보고 추후 더 자세히 정리해보도록 하자…🫠
동시성 프로그래밍의 문제점
동시성 프로그래밍을 하게되면 여러 작업을 한 번에 효율적으로 처리할 수 있게 되는 이점도 있지만, 아래와 같이 멀티 스레딩에서 일어날 수 있는 여러 문제점들이 발생할 수 있다.
- Race Condition (경쟁 상태)
- 공용 자원에 대해 여러 개의 스레드에서 접근할 때 그 순서에 따라 결과가 항상 같지 않고 달라지는 상황
- Deadlock (교착 상태)
- 두 개 이상의 스레드가 서로의 작업이 끝날 때까지 무한정 기다리는 상태
- Priority Inversion (우선 순위의 뒤바뀜)
- 낮은 우선순위의 작업이 높은 우선순위의 작업보다 먼저 실행되는 경우
너무 많은 양을 한 번에 정리하려다보니… 이래됨… GCD, OperationQueue, Race Condition, DeadLock 모두.. 나중에 각각 따로 한 번씩 더 정리해야겠다..
이번 글은 그냥 동시성 프로그래밍이 이런게 있구나 ~ 문제점은 저런게 있구나 ~ 정도의 글로…남겨두기..
- 참고자료
DispatchQueue | Apple Developer Documentation
An object that manages the execution of tasks serially or concurrently on your app's main thread or on a background thread.
developer.apple.com
Understanding Concurrency in iOS: GCD vs Operation Queue
Concurrency is a fundamental concept in iOS app development that allows you to perform multiple tasks simultaneously. This is crucial for…
medium.com
[GCD] 동기/비동기/Serial/Concurrent 에 대해 알아보자
동시성을 위해 iOS 에서 지원하는 기술인 GCD 와 Operation 의 간단한 개념과 특징을 알아보고
80000coding.oopy.io
[iOS] 차근차근 시작하는 GCD — 6
GCD 사용시 주의 사항에 대해 알아봅시다
sujinnaljin.medium.com
[iOS - swift] DispatchQueue.main.sync와 DispatchQueue.main.async 이해하기, sync를 사용해야하는 상황 (#mainSyncSafe
DispatchQueue의 sync와 async 동작 main queue와 thread 구분하기 main thread는 single thread이며, 해당 작업을 처리하는곳이 queue async와 sync로 각각 queue에 작업 담기가 가능 DispatchQueue.main.async { // main queue에 async
ios-development.tistory.com
동시성 프로그래밍(7) Operation
안녕하세요. 지난 시간까지는 GCD를 이용한 동시성 프로그래밍에 대해서 배웠습니다. 이제부터는 동시성 프로그래밍을 위한 또 다른 방법, Operation에 대해서 알아보겠습니다. 1. GCD와의 차이 GCD를
h4njun.tistory.com
동시성 프로그래밍(8) OperationQueue
안녕하세요. 오늘은 OperationQueue에 대해서 알아보도록 하겠습니다. 1. OperationQueue https://developer.apple.com/documentation/foundation/operationqueue Apple Developer Documentation developer.apple.com 지난 시간까지 Operation에
h4njun.tistory.com
Operation | Apple Developer Documentation
An abstract class that represents the code and data associated with a single task.
developer.apple.com
[iOS - swift] Operation, OperationQueue, 동시성
Operation single task에 관한 데이터와 코드를 나타내는 추상 클래스 해당 클래스를 서브클래싱하여 사용하면 안정적으로 task를 실행시킬 수 있는 효과 존재 OperationQueue Operation 객체들을 priority에 의
ios-development.tistory.com
동시성 프로그래밍(5) Concurrency Problems(동시성과 관련된 문제들)
안녕하세요. 오늘은 동시성 프로그래밍을 하면서 발생할 수 있는 문제들에 대해서 알아보겠습니다. Thread-Safety https://en.wikipedia.org/wiki/Thread_safety Thread safety - Wikipedia Thread safety is a computer programming
h4njun.tistory.com
'CS' 카테고리의 다른 글
[CS - iOS] Coordinator Pattern (5) | 2024.10.12 |
---|---|
[CS] 동시성 프로그래밍 vs 비동기 프로그래밍 (0) | 2024.08.03 |
[CS - iOS] 프로세스와 스레드 관리 (0) | 2024.05.02 |