동시성 과 앱디자인


이번 포스팅에서는 동시성 프로그래밍의 기본적인 개념과 iOS에서는 어떤식으로 적용시킬 수 있는지에 대해 이론적인 설명을 해보겠습니다.

참고문서 : Concurrency Programming Guide


초창기에는 컴퓨터의 단위시간당 최대 일처리능력은 CPU의 Clock속도에 의해 결정되었습니다.

기술력이 증진되고 기기가 소형화됨에 따라 발열에 다른 물리적 제약들로 인해 더이상 Clock의 속도를 향상시키기 힘들었습니다.

따라서 CPU칩들의 성능을 향상시키기 위해서 다른 방법을 찾았고 해결책은 각 CPU의 프로세스 코어의 개수를 늘리는 것이었습니다.

CPU당 코어 갯수가 증가하며 강제적으로 CPU의 속도를 증가시킬 필요도 없었고 칩의 사이즈 그리고 열처리방식을 따로 고안할 필요가 없었습니다.

단 한가지 문제점이 있다면 여러개의 코어를 어떻게 효율적으로 사용하냐는 문제였습니다.


이제 코어 수가 늘어남에 따라 컴퓨터는 하드웨어뿐만 아니라 여러개의 작업을 동시에 수행할 수 있는 스프트웨어가 필요했습니다.

오늘날 OS XIOS와 같은 멀티태스킹 운영체제에서는 수백개 혹은 그이상의 프로그램을 주어진 시간에 실행할 수 있습니다. 따라서 프로그램들을 각각 다른 코어에 스케줄링 할 수 있게되었습니다.

하지만 이들 중 대부분은 소요시간이 짧은 자동실행 프로그램이거나 백그라운드 애플리케이션이었습니다.

정말 필요한것은 이런단순한 애플리케이션이 아닌 여분의 코어의 성능까지 모두 사용할만큼 무거운 어플에 적용하는 방식이었습니다.


여러개의 코어를 사용하는 전통적인 방식은 여러개의 스레드를 사용하는 것이었지만 코어의 개수가 점차 늘어나며 문제 들이 발생했습니다.

그 중 가장 큰 문제는 멀티스레드에서 사용되는 코드가 코어의 개수가 변하면 환경에 맞춰 최적화되지 않는 문제였습니다.

우리는 코어의 개수만큼 쓰레드를 생성할 수 없으며 프로그램이 잘 실행될 것이라고 기대할 수도 없습니다.

우리가 알아야할 것은 몇개의 코어를 사용해야 효과적일지에 대한 문제이고 이는 애플리케이션 스스로가 알아낼 수 없는 문제입니다.

몇 개의 코어를 사용할지에 대한 문제를 해결하더라도 여전히 많은 스레드들을 효과적이고 충돌없이 사용하는법에 대한 문제가 남아있었습니다.


문제점들을 요약해보자면

  • 애플리케이션이 여러개의 코어를 활용하는 것에 이점이 있도록 활용되는 방법을 찾아야합니다.

  • 하나의 어플리케이션에서 처리되는 작업들은 다양한 시스템환경에서 최적화될 수 있어야합니다.

다행히도 Apple의 운영체제에서는 이런 모든 문제의 해결책을 모두 제공합니다. 또한 이번 포스팅에서는 해결책을 구성하는 기술에 대하여 알아보고 직접 코드에 적용시키는법에 대하여 알아보겠습니다.



스레드 의존성 낮추기


비록 스레드가 계속 사용되어 왔지만 여전히 여러개의 작업을 환경의 변화에 따라 유동적으로 사용하는 법에 대해서는 해결하지 못하였습니다.

이 문제에 대한 해결책을 마련하는 것은 우리 개발자들의 몫입니다.

우리는 몇개의 스레드를 만들지 결정해야하고 시스템환경이 변경될 때마다 각 환경에 맞게 스레드의 개수를 최적화될 수 있게 해줘야합니다.

또 하나의 문제점은 어플리케이션이 스레드를 유지보수하는데에 큰 비용을 부담하게됩니다.


이렇게 스레드에 의존하는 대신 동시성 문제를 해결하기 위해 OS X와 iOS에서는 asynchronous design을 고안했습니다.

Asynchronous function은 이미 수년동안 운영체제 내에서 사용되어왔고 종종 디스크로부터 데이터를 읽어오는것과 같은 시간이 오래걸리는 작업을 수행하는데 사용되었습니다.

Asynchronous function이라 하면 작업수행을 시작하기위해 작업과정의 일부를 보이지 않는 영역에서 진행합니다.

전형적으로 이 과정에서는 주어진 작업을 따로 처리할 백그라운드 스레드를 탐색하고 작업이 끝나면 call back함수를 통하여 caller에게 notification을 전달합니다.

과거에는 Asynchronous function이 하는 역할을 직접 구현해야했지만 현재는 OS X와 iOS에서 직접적으로 스레드를 관리하지 않고 비동기적인 작업을 수행할 수 있는 기능을 제공한다.


비동기 방식으로 작업을 수행을 하기위한 하나의 기술은 GCD(Grand Central Dispatch)입니다. 이 기술은 우리가 애플리케이션에 쓴 코드 내에서 스레드를 관리해주며 코드를 더 낮은 단계의 시스템 레벨로 이동시켜줍니다.

이 단계에서 우리는 스레드를 통해 작업할 작업을 정의해주고 dispatch queue에 추가해주면 됩니다. GCD는 이처럼 우리에게 필요한 스레드를 생성해주고 해당 스레드에서 실행될 작업을 스케줄링해줍니다.

오늘날 스레드 관리는 시스템의 일부가되었습니다. GCD는 작업관리와 실행에 걸친 전반적인 부분에 걸쳐 역할을 수행하기에 전통적인 의미의 스레드보다 더 효율적인 기능을 제공합니다.

Operation queue는 Objective-C의 오브젝트로써 dispatch queue와 매우 흡사한 기능을 합니다.

원하는 작업을 정의하고 해당 작업을 Operation queue에 추가해줍니다. Operation queue또한 dispatch queue와 마찬가지로 속도와 효율을 보장하며 스레드 관리에 대한 모든것을 관리합니다.



다음 포스팅에서는 dispatch queue와 operation queue을 직접 앱에 활용할 수 있는 방법에 대해 다뤄보겠습니다!