[iOS-Swift] GCD 종류와 특성, 사용 시 주의사항
GCD 톺아보기
iOS Concurrency에 대해 앞선 글에서 언급하면서,
GCD와 Operation Queue의 설명을 덧붙였었는데요.
GCD는 iOS에서 멀티스레드 프로그래밍을 도와주는 프레임워크로,
작업을 대기행렬 (Queue)로 보내고, 시스템이 알아서 스레드를 관리해 처리해주는 것이 핵심이었습니다.
이번 글에서는 GCD의 종류와 특성, QoS,
그리고 GCD 사용 시 주의해야 할 사항들을 다루어보려 합니다.
GCD의 Queue 종류
GCD에서 작업을 처리하는 대기행렬(Queue)는 크게 두 종류로 나뉘는데요,
Queue의 종류
1. Dispatch Queue
2. Operation Queue
그 중 Dispatch Queue는 다시
Dispatch Queue
1. Global Queue
2. Main Queue
3. Private Queue
Global, Main, Private Queue 세 가지로 구분됩니다.
어떤 작업들이 있을 때, 작업의 성격에 따라서
사용해야 할 Queue가 정해지게 되는데요.
우선, Main Queue는 메인 스레드를 의미하며, 한 개의 직렬 큐로 동작합니다.
중요한 작업, 특히 UI 업데이트는 반드시 이 메인 큐에서 실행해주어야 합니다.
DispatchQueue.main.async { }
Global Queue는 동시 큐로서,
병렬적으로 처리하기 때문에 주로 순서가 중요하지 않은 작업들이 들어갑니다.
DispatchQueue.global().async { }
마지막으로 Private Queue는 사용자가 커스텀하는 큐로,
필요에 의해 직렬이나 동시 큐로 설정을 할 수 있습니다.
QoS(Quality of Service)와 글로벌 큐
QoS란, 작업의 우선 순위를 결정하는 요소입니다.
OS 내에서 작업에 따라서 시스템 자원을 어떻게 효율적으로 배분해줄지 결정하는 역할을 합니다.
이때, iOS는 작업의 특성에 따라서 6가지의 레벨로 나누어주고 있습니다.
QoS (작업 순위 오름차순 정리)
- .userInteractive: 즉시 반응해야 하는 UI 관련 작업 (애니메이션, 버튼 클릭 등)
- .userInitiated: 사용자가 즉시 결과를 기대하는 비동기 작업 (파일 열기 등)
- .default: 기본 우선순위
- .utility: 몇 초에서 몇 분 정도 걸리는 작업 (네트워킹, I/O 등)
- .background: 시간에 덜 민감한 작업 (데이터베이스 유지 등)
- .unspecified: QoS가 명시되지 않은 작업
작업의 중요도에 따라서 QoS를 지정해주면,
iOS가 해당되는 작업을 우선적으로 처리하거나 배터리 효율 등을 고려해서
최적화된 방식으로 실행해줍니다.
프라이빗 큐
커스텀이 가능한 프라이빗 큐는 기본적으로 직렬로 동작하지만,
동시 동작도 가능하며 QoS 설정 또한 가능합니다.
let queue = DispatchQueue(label: "com.example.privateQueue", attributes: .concurrent, qos: .utility)
queue.async { }
GCD 사용 시 주의사항
GCD를 사용할 때에는 지켜야 할 주의사항들이 몇 가지 있는데요,
1. UI 관련 작업은 메인 큐에서 처리
UI 업데이트가 필요한 경우, 항상 메인 큐에서 처리해주어야 합니다. (간섭 방지)
2. Sync 메서드 사용 시 주의사항
메인 큐에서는 비동기적으로 작업을 처리해야 합니다. UI와 관련되지 않는, 오래 걸리는 작업들을 다른 쓰레드에서 실행할 수 있도록 비동기로 보내주어야 UI가 멈추는 불상사를 피할 수 있습니다.
3. 강한 참조 주의
GCD에서 작업을 보내는 일은 클로저를 보내는 것이기 때문에, 객체에 대한 캡처 현상이 발생합니다. 때문에, 메모리 누수 방지를 위한 weak 참조를 사용해주어야 합니다.
4. Completion Handler
비동기 작업을 처리할 때, 작업이 완료되면 그 시점을 알리기 위한 Completion Handler가 사용됩니다. 이를 통해서, 작업이 완료된 후의 후속 작업을 처리할 수 있게 됩니다.