[iOS Boostcourse] 동시성과 병렬성 그리고 비동기 프로그래밍
[iOS Boostcourse] 동시성과 병렬성 그리고 비동기 프로그래밍
이전에 운영체제 과목을 수강하면서 공부했던 내용입니다. 당시에도 굉장히 비중있게 공부했던 부분이라 이번 부스트코스를 통해 다시 공부를 하게 되어 이를 간단하게 요약하고 정리해보는 시간을 갖게 되었습니다.
iOS에서 동시성 프로그래밍에 대해 살펴보기 전 먼저 알아야할 개념들부터 정리해보도록 하겠습니다.
프로세스
하나의 프로그램이 메모리 상에서 실행되는 작업 단위입니다.
스레드
하나의 프로세스 내에서 실행되는 작업흐름의 단위로 프로세스가 시작하는 동시에 동작하는 스레드를 메인 스레드라하고 이외의 추가로 생성되는 스레드를 서브 스레드라 부릅니다. 보통 하나의 프로세스는 하나의 스레드를 갖지만 둘 이상의 스레드를 동시에 실행할 수도 있고 이를 우리는 멀티스레딩이라고 합니다.
그럼 이제 비동기, 동시성 그리고 병렬성에 대해 정리해보도록 하겠습니다.
비동기 프로그래밍
비동기 프로그래밍이란 프로그램의 주 실행 흐름에서 특정 작업을 위해 프로그램이 멈추고 해당 작업이 끝날 때까지 기다리는 것이 아니라 해당 작업은 별도의 공간에 맡겨둔 뒤 결과를 기다리지 않고 주 실행 흐름을 방해하지 않고 그대로 흐름을 이어가도록 가능케 하는 병렬처리 방식입니다.
동시성 프로그래밍
말 그대로 동시에 여러 프로그램을 돌리는 것이 아닌 그렇게 보이게끔 하는 기법으로 시간을 분할하여 스레드들에게 서로 번갈아가며 제공하여 실행되게끔 하는 방식입니다. 코어에 상관 없이 실행 가능한 기법으로 싱글 코어에서도 멀티스레딩을 가능케 합니다.
병렬성 프로그래밍
동시성 프로그래밍과 다르게 동시에 돌아가는 것처럼 보이는 것이 아닌 실제로 동시에 실행되는 것을 의미합니다! 멀티 코어에서 멀티 스레드를 동작시키는 방식으로 데이터 병렬성과 작업 병렬성으로 나뉘게 됩니다.
- 데이터 병렬성 - 처리해야 할 데이터를 나누어 나누어진 데이터들을 병렬 처리하여 작업을 빠르게 수행하는 기법
- 작업 병렬성 - 서로 다른 작업을 병렬 처리하는 기법
동시성과 병렬성 차이
동시성 프로그래밍과 병렬성 프로그래밍 모두 비동기적으로 구현할 수 있습니다. 하지만 둘은 다음과 같은 차이가 존재합니다.
동시성 | 병렬성 | |
---|---|---|
개념 | 논리적 | 물리적 |
동작 가능 환경 | 싱글코어, 멀티 코어 | 멀티 코어 |
병렬성 프로그래밍은 멀티 코어 환경에서만 동작 가능합니다.
이젠 iOS에서 동시성 프로그래밍을 어떻게 지원하는지에 대해 알아보도록 하겠습니다.
OperationQueue? DispatchQueue ?
저는 사실 iOS 공부를 하면서 Concurrency한 작업을 진행할 때 DispatchQueue
만을 사용해왔습니다. 사실 어떠한 이유가 있어서 이것을 사용했다기보단 제가 독학을 하면서 보고 공부한 유투버들이나 예제에서 모두 DispatchQueue
를 사용했었기 때문입니다.
하지만 이번에 부스트코스를 통해 학습을 진행하면서 OperationQueue
에 대해 알게 되었고 이 둘에 어떠한 차이점이 있는지 궁금하였습니다.
그래서 이 둘의 차이점에 대해 공부를 해보았고 이 둘의 차이점에 대해 보다 확실히 이해하게 되었습니다.
이 둘의 차이점에 대해 쉽게 설명된 글이 있어 해당 글을 인용해 둘의 차이점을 간략하게 소개하겠습니다.
Operation
과 OperationQueue
는 NSOperation
과 NSOperationQueue
로 iOS2에서 처음으로 소개되었고, Grand Central Dispatch 줄여서 GCD는 iOS4에서 처음으로 소개되었습니다. 이 둘은 동시성을 지원하기 위해 작업 단위를 캡슐화하여 실행에 넘기는 동작을 하도록 설계되었습니다. 이렇게 두 api의 목적이 같기 때문에 개발자들은 종종 어느 것을 사용해야 하는지 헷갈려 하기도 합니다.
언제 어떤 api를 사용해야 하는지 설명하기 전에 이 둘의 주요 차이점에 대해 먼저 이야기 해보도록 하겠습니다.
What Sets Them Apart
애플은 Operation
이 GCD 위에서 동작하게끔 설계하였습니다. 그러므로 Operation
은 GCD를 상위 수준으로 추상화한 api라고 할 수 있습니다. 즉 Operation
을 사용하는 것은 은연중에 GCD를 사용하는 것과 같습니다.
GCD는 시스템의 유닉스 레벨의 수준에서 직접적으로 상호작용하는 저수준의 C api입니다. 반면 Operation
은 Objective-C api입니다. 그렇기 때문에 Operation
은 보다 저수준에서 동작하는 GCD보다 상대적으로 느릴 수 밖에 없습니다.
Benefits of Operation
Operation
이 GCD 위에서 만들어졌다는 사실에 Operation
만이 제공하는 것이 무엇이 있는지 궁금하실 겁니다. 이러한 몇 가지 차이점으로 인한 이점은 Opertation
을 선택하도록 하는 요소가 되기도 합니다.
Dependencies
Operation
은 의존성을 제공합니다. 의존성을 제공한다는 것은 개발자가 일련의 작업에 순서를 정할수 있다는 것을 의미하고 하나의 작업이 다른 작업에 의존성을 갖고 있다면 이 작업은 해당 작업들이 모두 끝난 후에 작업을 시작할 수 있습니다.
Observable
Operation
과 OperationQueue
클래스는 KVO를 통해 관찰될 수 있는 프로퍼티를 제공합니다. 이러한 사실로 우리는 작업들의 상태를 모니터링할 수 있습니다.
Pause, Cancel, Resume
Operation
들은 정지,취소 그리고 재시작될 수 있습니다. GCD에 작업을 할당한다면 해당 작업에 대한 어떠한 통제권도 갖지 못합니다. 이러한 관점에서 Operation
이 보다 작업의 Life cycle에 대한 유연함을 제공한다는 것을 알 수 있습니다.
단 작업을 대기열에 추가한 것 자체는 되돌릴 수 없습니다.
Control
OperationQueue
역시 DispatchQueue
에 비해 몇 가지 이점을 갖고 있는데요. 그 예로는 대기열에 들어갈 수 있는 작업의 숫자를 지정함으로써 동시에 수행될 수 있는 작업의 수를 지정할 수 있습니다. 이를 통해 동시에 실행되는 작업의 갯수와 이들의 순서를 조작할 수 있습니다.
When to Use Which
일반적으로 애플은 개발자들에게 보다 고수준의 추상화된 api를 사용할 것을 권장합니다. 즉 Operation
을 보다 권장하는 것이죠.
그렇다면 애플은 왜 보다 고수준의 api를 사용할 것을 권장하는 것일까요? 애플은 새로운 iOS 버전의 출시마다 운영체제의 효율을 증가시키기 위해 프레임워크와 라이브러리를 최적화하는 작업을 수행합니다. 이러한 작업은 보통 저수준의 api의 영향을 주곤 합니다. 심지어 이러한 저수준의 api 위에 존재하는 고수준의 api도 이러한 작업에 영향을 받곤 합니다.
그렇다면 GCD의 사용을 지양햐야 하는 것일까요? 이는 개발자의 선택에 따릅니다. 많은 개발자들이 GCD를 사용하기도 하고 Operation
과 GCD를 같이 사용하기도 합니다.
When to Use Operation
위에서 언급한 의존성을 이용한 작업의 순서를 결정할 수 있는 점이 GCD에게는 없는 강력한 이점 중 하나입니다. 즉 어떠한 작업들의 순서를 지정해줄 필요가 있다면 Operation
을 사용하는 것이 바람직합니다. 하지만 짧은 시간안에 수십개의 작업을 생성하야할 경우에는 Operation
의 내재된 오버헤드로 인한 성능 문제로 이어질 수 있습니다.
When to Use GCD
GCD는 Operation
을 사용하여 일련의 작업들을 수행하기 위한 코드에 비해 적은 양의 코드로도 같은 행위를 할 수 있습니다. GCD가 순서가 아예 없는 것은 아닙니다. 기본적으로 GCD는 FIFO 형태의 하나의 작업 대기열을 갖고 있기 때문에 들어온 순서대로 작업을 처리할 수 있습니다. 또한 이들을 들어온 순서에 상관없이 Concurrent하게 작업을 진행할 수도 있습니다. 이렇게 특정 작업의 순서를 지정해주는 것처럼 Operation
이 갖고 있는 이점을 사용하는 것이 아니라면 GCD를 사용해도 무방합니다.
마무리
오늘은 이렇게 iOS에서 동시성 프로그래밍을 지원하는 api에 대해 살펴보았고 그들의 차이점도 같이 살펴보았습니다. 오늘은 간략하게 다른 블로그의 글을 번역하고 이를 요약한 것이어서 내용을 가볍게 훑어보기에는 좋았습니다. 하지만 가볍게 이해하는 것은 잘못된 지식으로 이어질 수 있기 때문에 다음에는 Concurrency Programming Guide 문서를 정독해보고 이를 통해 보다 개념을 확실히 하고 학습한 내용을 정리해보는 시간을 갖도록 하겠습니다. 감사합니다.
참고자료