시스템에 의해 관리되는 Dispatch Queue들에 작업을 보내어 멀티코어 하드웨어 위에서 동시에 코드를 실행하는 Dispatch Framework에 대해 알아보도록 하겠습니다.
Dispatch는 GCD(Grand Central Dispatch)로도 잘 알려져 있습니다. macOS, iOS, watchOS, tvOS의 멀티코어 하드웨어에서 동시에 코드를 실행하는 것에 대해 종합적이고 시스템적인 개선과 런타임 라이브러리들을 포함하고 있습니다.
BSD subsystem, Core Foundation, Cocoa API는 모두 이러한 향상된 기능(enhancements)들을 이용하여 시스템과 어플리케이션을 더 빠르고, 더 효율적으로 실행하고, 응답성을 향상시키기 위해 확장되었습니다. 컴퓨팅하는 코어 수가 서로 다른 컴퓨터들이 있는 환경이나 여러 어플리케이션이 코어를 점유하기 위해 경쟁하는 환경에서 단일 어플리케이션이 여러 코어를 효율적으로 사용하게 하는 것은 정말 어렵겠죠.
시스템 레벨에서 동작하는 GCD는 실행되는 모든 어플리케이션의 요구사항을 보다 더 효율적으로 받아들이고, 사용가능한 시스템 리소스들을 균형있게 잘 매칭시켜 줍니다.
Dispatch Queue
Dispatch Queue는 앱의 메인 스레드 혹은 백그라운드 스레드, 직렬적(serial) 또는 동시적(concurrent) 으로 실행될 작업들을 관리하는 객체 입니다. Dispatch Object를 상속받는 클래스로 선언되어 있습니다.
class DispatchQueue: DispatchObject
Dispatch Queue는 어플리케이션이 블록 객체 형식으로 작업을 전달할 수 있는 FIFO(선입선출) 큐입니다. Dispatch Queue는 작업들을 직렬적(serial) 또는 동시적(concurrent) 으로 처리합니다. Dispatch Queue에 전달된 작업은 시스템에 의해 관리되는 Thread pool에서 실행됩니다. 앱의 메인 스레드를 대표하는 Dispatch Queue를 제외하고는 어떤 작업이 어떤 스레드에서 실행될지는 시스템에서 보장해주지 않습니다.
작업을 동기(synchronously) 혹은 비동기(asynchronously)로 스케쥴할 수도 있습니다. 동기적으로 작업을 스케쥴할 경우, 코드는 해당 작업이 끝날 때까지 대기합니다. 반면에 비동기적으로 작업을 스케쥴할 경우, 작업 항목이 다른 어떤 곳에서 실행되는 동안 코드는 계속해서 실행되게 됩니다.
주의: 메인 큐에서 작업을 동기적으로 실행하도록 시도할 경우 교착상태(Deadlock)에 빠질 수 있습니다.
과도하게 스레드를 생성하는 것은 피해야 합니다. 동시적으로 실행되는 작업을 설계할 때, 현재 실행되고 있는 스레드를 차단하는 메소드를 호출하면 안됩니다. Concurrent Dispatch Queue에 의해 스케쥴된 작업이 스레드를 차단하면, 시스템은 대기 중인 concurrent 작업들을 실행할 추가적인 스레드를 생성합니다. 너무 많은 작업들이 차단되면, 해당 앱을 위한 스레드가 시스템에 부족해 질 수 있습니다.
어플리케이션에서 너무 많은 스레드를 사용하는 또 다른 경우는 직접 만든(private) Concurrent Dispatch Queue들을 많이 생성하는 것입니다. 각각의 Dispatch Queue는 스레드 리소스를 사용하기 때문에, 추가적인 Concurrent Dispatch Queue를 생성하는 것은 스레드 사용 문제를 악화시킵니다. 직접 Concurrent Queue들을 만들기 보다는, Global한 Concurrent Dispatch Queue들 중 하나에 작업을 전달해야 합니다.
직렬(serial)로 처리되는 작업의 경우에는, Serial Queue의 대상을 Global한 Concurrent Queue들 중 하나에 설정하면 됩니다. 이렇게 하면, 스레드를 생성하는 개별 Queue의 수를 최소화하면서 Queue의 직렬화(serial)된 동작을 유지할 수 있습니다.
Dispatch WorkItem
class DispatchWorkItem
Dispatch WorkItem은 완료 핸들러 또는 실행 의존성을 첨부할 수 있는 방식으로 작업을 실행하고 캡슐화할 때 사용되어 집니다. Dispatch Queue 혹은 Dispatch Group에서 실행되게 할 작업들을 캡슐화 할 수 있습니다. 또한 Dispatch Source 이벤트, 등록 또는 취소 핸들러로 사용할 수도 있습니다.
Dispatch Group
Dispatch Group은 단일 유닛으로 관리(monitor)하고자 하는 작업의 모음입니다.
class DispatchGroup: DispatchObject
그룹을 사용하면 일련의 작업을 집계하고 그룹의 동작을 동기화할 수 있습니다. 여러 작업 항목을 그룹에 연결하고 동일 큐 혹은 다른 큐들에서 비동기로 실행되는 작업들을 스케쥴할 수 있습니다. 모든 작업 실행이 완료되면, 그룹의 완료 핸들러가 실행됩니다. 또한 그룹의 모든 작업의 실행이 완료될 때까지 동기적으로 기다릴 수도 있습니다.
정리
- Dispatch 프레임워크에 대한 기본적인 개념을 알아보았습니다.
- Concurrent한 작업을 효율적으로 설계하기 위한 클래스들을 알아보았습니다.
더 나아가기
'iOS' 카테고리의 다른 글
[iOS] 강한 참조 사이클 (순환 참조) 해결하기 2편 (0) | 2019.12.15 |
---|---|
[iOS] 강한 참조 사이클 (순환 참조) 해결하기 1편 (0) | 2019.12.15 |
[iOS] ARC 란? (Automatic Reference Counting) (0) | 2019.12.15 |
[iOS] GCD 활용하기 2편 (DispatchGroup, DispatchSemaphore) (0) | 2019.12.15 |
[iOS] GCD 활용하기 1편 (DispatchQueue) (0) | 2019.12.15 |