티스토리 뷰

반응형

안녕하세요 Ick입니다!

오늘은 iOS에서 앱을 개발할 때 여러 개의 작업을 동시에 수행할 수 있도록 해주는 동시성 프로그래밍에 대해 알아보려고 합니다.

동시성 프로그램의 이론적인 내용은 여기를 참고해주세요!

이번 글에서는 동시성 프로그래밍을 직접 구현해보는 것만 해보려고 합니다!

 

iOS에서 동시성 프로그래밍을 구현하기 위해서 Apple에서는 GCD라는 것을 만들어뒀습니다.

이는 직접 스레드를 만들어서 작업을 수행하는 것이 어렵고 문제를 발생할 수 도 있기 때문에, 시스템에서 자동으로 수행해주도록 해 준 것이라고 볼 수 있습니다!

저희는 이렇게 만들어진 GCD를 사용해서 동시성 프로그래밍을 할 수 있습니다!

그럼 사용해보기 전에 반드시 알아야 할 용어들만 간단하게 짚고 넘어가도록 하겠습니다.

 

동기(Synchronous)

동기식 작업으로 설계하면 어떤 작업이 끝날 때까지 다른 작업을 수행할 수 없습니다.

예를 들어 치킨집에서 하는 일이 치킨 튀기기, 주문받기, 치킨 배달이라는 3가지만 존재할 때

동기로 작업을 처리하면 주문을 받는 동안에는 다른 일을 할 수 없는 것입니다.

작업들이 순차적으로 진행되기 때문에 순서가 있는 작업에는 좋을 수 있습니다.

비동기(Asynchronous)

비동기 작업으로 설계하면 여러 개의 작업이 동시에 수행될 수 있습니다.

예를 들어 치킨집에서 하는 일이 치킨 튀기기, 주문받기, 치킨 배달이라는 3가지만 존재할 때

비동기로 작업을 처리하면 주문을 받는 동안에도 치킨을 튀기거나 치킨을 배달할 수 있는 것입니다.

하지만 어떤 작업이 먼저 끝날지 모르기 때문에 순서가 있는 작업에는 우선순위나 종속성을 적용해 줘야 할 수 도 있습니다.

종속성(Dependency)

종속성은 A 작업이 끝나면 B 작업을 수행하겠다고 하는 관계를 나타냅니다.

예를 들어 치킨집에서 하는 일이 치킨 튀기기, 주문 받기, 치킨 배달이라는 3가지만 존재할 때

주문을 받은 뒤에 치킨을 튀겨야 하는 것처럼 작업에 순서가 있을 때 종속성을 추가하여 순서를 제어할 수 있습니다.

이번 글에서는 DispatchQueue를 사용해볼 거라서 종속성에 대한 구현은 OperationQueue를 다루는 글에서 해보려고 합니다.

쓰게 되면 링크를... 링크!!

우선순위(Priority)

직렬 큐(Serial Queue)

동시 큐(Concurrent Queue)

 

 


 

DispatchQueue

우선 DispatchQueue는 3가지 종류가 있습니다. 

이중 main, global은 시스템에서 기본적으로 제공하는 큐이고 custom으로 개발자가 직접 큐를 만들 수 있습니다.

 

main : 메인 스레드에서 동작하는 큐. UI, 사용자 인터렉션을 담당하는데 Serial queue이기 때문에 한 번에 하나의 작업만 수행합니다.

 

global : Concurrent queue이기 때문에 여러 작업을 한 번에 수행할 수 있습니다.

 

custom : 개발자가 직접 만든 큐.

 

자 그럼 각각의 큐를 사용하는 방법을 보겠습니다~

DispatchQueue.main.async {
    
}
DispatchQueue.global().async {
    
}

let customQueue = DispatchQueue(label: "Ick")
customQueue.async {
    
}

 

 

 

 

 

 

위와 같이 main 큐는 직렬 큐이기 때문에 비동기로 만들어줘도 순차적으로 진행되는 것을 볼 수 있었습니다.

그럼 global 큐는 어떨까요?

위와 같이 순서가 지 맘대로 인 것을 볼 수 있죠.

😆 얘를 출력하라는 작업이 늦게 들어갔음에도 불구하고 먼저 시작되고 먼저 끝나버립니다.

이렇게 단순하게 비동기만 사용해서 실행하면 실행 순서를 예측할 수 없습니다.

 

이번엔 큐에 우선순위를 다르게 해서 작업을 실행시켜 보겠습니다!

하다 보니... 10개 출력된 사진이 블로그에서 보기에 너무 못생겨서 5개로 줄였습니다 ㅎㅎ

위와 같이 😆를 출력하는 작업은 우선순위가 높은 큐에 넣었고 ❤️를 출력하는 작업은 우선순위가 낮은 큐에 넣었습니다.

실제 결과를 봐도 우선순위가 높은 큐에 넣은 작업이 먼저 완료되는 것을 볼 수 있었습니다!!

몇 번을 해도 완료되는 순서는 동일했습니다.

 

그럼 이번에는 비동기 방식이 아닌 동기식 방법으로 구현해보겠습니다.

들어온 순서대로 착착 진행되는 것을 볼 수 있습니다.

하나의 작업이 끝나기 전에 다른 작업이 실행되지도 않는 것도요!

그럼 만약에 동기식 방법에 우선순위를 주면 어떻게 될까요?

짠! 이렇게 우선순위보다도 먼저 들어온 작업부터 처리하는 것을 볼 수 있습니다.

 

그럼 이번엔 DispatchQueue를 직접 만들어서 구현해보겠습니다!

직접 만들기 위해서는 아래와 같이 코드를 작성하면 됩니다.

let customQueue = DispatchQueue(label: <#T##String#>, qos: <#T##DispatchQoS#>, attributes: <#T##DispatchQueue.Attributes#>, autoreleaseFrequency: <#T##DispatchQueue.AutoreleaseFrequency#>, target: <#T##DispatchQueue?#>)

큐를 직접 만들 때 몇 가지 매개변수를 선택해줘야 하는데 우선 설명은 다음과 같습니다

간단하게 보면 label은 큐의 이름이라고 보면 되고 qos는 큐의 우선순위 attribute는 직렬 큐, 동시 큐를 선택해주는 옵션 같아요

autoreleaseFrequency는 큐에 예약하는 블록에 의해 생성되는 객체를 자동 해제하는 빈도,

target은 블록을 실행할 큐를 선택해주는 옵션이라고 합니다.

 

우선 지금은 label, qos, attribute에 중점을 두고 생성해보겠습니다.

동시 큐로 만들었기 때문에 비동기로 작업을 수행하면 끝나는 순서를 알 수 없습니다.

그럼 한 번 직렬로 만들어서 비동기로 수행해보겠습니다

 

어떤가요? 예상된 순서로 진행되셨나요?

그럼 이번에는 2개의 직렬 큐로 만들어서 비동기로 실행해보겠습니다.

이렇게 하더라도 비동기적으로 수행되는 것을 볼 수 있습니다.

즉 서로 다른 직렬 큐에 작업들이 들어가 있고 비동기로 실행하면 직렬 큐라고 해도 순서를 예측할 수 없다는 것입니다.

 

마지막으로 DispatchWorkItem를 살펴보겠습니다.

얘는 그냥 단순하게 작업을 캡슐화하는 것입니다.

위와 같이 지금까지는 작업을 바로 집어넣었는데 DispatchWorkItem을 사용하면 하나의 객체처럼 작업을 사용할 수 있습니다!

 

감사합니다!!

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함