iOS에서 DispatchQueue 에 대해 알아보기

sonny·2024년 10월 7일
4

TIL

목록 보기
12/48

내가 바로 전에 쓴 글을 보다가 DispatchQueue 를 뭘 알고 적었는지 모르겠더라 ...

구글에 검색했을 당시에는 타이머가 시작한 후 픽셀이 떨어질 때 픽셀들이 쌓여 바닥부터 차오르는 애니메이션을 구현하기 위해서 코드를 보고 작성한 걸로 기억이 난다.

그런데, 정작 이게 뭔지도 모르고 그냥 써놓았고.... 심지어 DispatchQueue 는 이제 갓 Swift를 배운 사람들에게는 다소 난이도가 있는 코드였다는 걸 알게 됐다.

(대충 전 블로그에서 아무것도 모르면서 DispatchQueue를 사용해 본 나를 박제)

그래서 오늘은 조금이라도 이해하고자 DispatchQueue 에 대해 알아보려고 했는데 알고보니 Grand Central Dispatch의 일부이더라.

Grand Central Dispatch 는 줄여서 GCD 라고 한다.


Grand Central Dispatch (GCD) 와 DispatchQueue의 차이?

DispatchQueue와 아예 다른건가? 싶었는데 GCD의 일부였고, DispatchQueueGCD 를 통해서 비동기 작업을 처리하기 위한 도구라고 한다.

GCD 라는 시스템을 통해서 비동기작업이나 동시성 관리, 스레드 관리 등의 복잡한 작업을 쉽게 처리할 수 있는데, 그 기능을 개발자가 더 쉽게 사용할 수 있도록 해주는 것이 DispatchQueue 라고 한다는 것.

  • Grand Central Dispatch(GCD)
    비동기 작업, 동시성 관리, 스레드 관리 등을 위한 저수준 시스템 레벨의 API . 개발자가 비동기 작업이나 스레드 관리를 직접 하지 않고도 이를 쉽게 처리할 수 있도록 시스템이 작업을 최적화하고 관리해 준다.

  • DispatchQueue
    GCD의 기능을 이용하여 작업을 큐에 넣고 관리하는 고수준의 도구다. 이 큐를 사용해 작업을 직렬(순차적으로) 혹은 병렬(동시에)로 실행할 수 있다.

예를 들어 설명하면 GCD 는 일종의 거대한 시스템으로 우리가 많은 작업을 동시에 처리할 수 있게 해주는 엔진이라고 볼 수 있고, DispatchQueue 는 그 엔진을 조작하는 조작판처럼 우리가 작업을 넣어서 그 엔진이 알아서 일을 처리하게끔 하는 도구라고 한다.

이해가 되는가.. 아니요 전혀요..


그러면 내가 어떠한 이유로 저 코드를 사용하게 된 건지 한번 봐야겠다.

이 코드를 보면 나는 픽셀이 바닥에 닿을 때 부터 바닥이 픽셀과 같은 색상으로 차오르는 애니메이션을 바랬다.

적용해서 쌓이는건 되는데 현재 일시정지 했다가 다시 시작 누르면 오류 발생함.....

DispatchQueue.main.asyncAfter 은 타이머 시작 후 3초 후에 startFillingAnimation 을 실행하기 위해 사용되었다.

타이머가 시작되자마자 픽셀을 떨어뜨리는 애니메이션을 시작하지만, 화면을 채우는 애니메이션은 3초 후에 시작하도록 하려는 목적으로 해당 코드를 작성했던 것이다.

이처럼 지연 작업을 구현할 땐 DispatchQueue.main.asyncAfter가 적합하다고 한다.

그리고 이 부분에서 25분(fillDuration = 1500초) 후에 타이머와 애니메이션을 종료하기 위해 사용되었는데, DispatchQueue.main.asyncAfter 를 통해서 특정 시간이 지난 후 특정 작업을 수행하도록 만들 수 있기 때문에 사용했던 것이다.

정리하자면 나는 타이머가 시작된 후 3초 동안 대기 후 화면 채우기 애니메이션 시작하기 위함과, 타이머와 화면 채우기 애니메이션을 25분 후에 종료하도록 하기 위해 사용했다는 것.


Grand Central Dispatch(GCD) 에 대해 최대한 쉽게 이해해보려한다.

Grand Central Dispatch(GCD)는 iOS와 macOS에서 사용되는 동시성 프로그래밍 도구라고 한다. 복잡해 보이지만, 실생활의 예로 이해해보자.

GCD의 기본 개념

레스토랑을 상상해볼까. 이 레스토랑에는 여러 명의 요리사(쓰레드)가 있고, 다양한 주문(작업)이 들어올 것이다.
디스패치 큐(Dispatch Queue)는 주방에 있는 주문서 보드라고 생각한다면, 주문(작업)이 이 보드에 올라갈 것이고 요리사들이 이를 처리할 것이다.

GCD는 크게 두 종류가 있다

Serial Queue(직렬 큐) : 한 명의 요리사가 주문을 순서대로 처리한다.
Concurrent Queue(동시 큐) : 여러 요리사가 동시에 여러 주문을 처리할 수 있다.

그리고 메인 큐(Main Queue) 는 레스토랑의 홀을 담당하는 직원이라고 생각하면 된다. 손님과 직접 상호작용하는 일(예: UI 업데이트)을 담당한다.

비동기 실행(Async Execution) 의 경우 주문을 받고 바로 다음 손님을 받는 것과 같은데, 주문(작업)을 큐에 넣고 즉시 다른 일을 할 수 있다는 것이다.

이 코드에서 DispatchQueue.global().async 는 백그라운드에서 작업을 실행한다.
( 주방에서 요리하는 것과 같음 )
Thread.sleep 는 시간이 걸리는 작업을 시뮬레이션 해주고 DispatchQueue.main.async 는 UI 관련 작업을 메인 큐에서 실행해준다. ( 손님에게 음식을 서빙하는 것과 같음 )

마지막 줄은 비동기 작업이 시작된 후 즉시 실행된다.

네?


'마지막 줄은 비동기 작업이 시작된 후 즉시 실행된다' 라는 말이 뭘까?

실행되는 코드를 한번 보자.

먼저 위 코드를 보면 "시작"이 먼저 출력된다.

그리고 나서 DispatchQueue.global().async { ... } 블록이 실행되기 시작하는데, 저 코드가 이제 비동기 작업을 시작하라는 명령인 것이고, 비동기 작업이 백그라운드에서 시작되지만 메인 스레드는 기다리지 않고 즉시 다음 줄로 넘어가서 "메인 스레드 작업 계속" 이 출력된다.

이것이 바로 위에 소제목으로 말 했었던 ' 마지막 줄은 비동기 작업이 시작된 후 즉시 실행된다.' 라고 말한 부분이다.

그동안 백그라운드에서는 비동기 작업이 계속 실행되고 있다. 그리고 약 2초 후, 백그라운드 작업이 완료되고 "비동기 작업 완료"가 출력된 뒤, 마지막으로 5초 후"프로그램 종료"가 출력된다.

여기서 중요한 점은 "메인 스레드 작업 계속""비동기 작업 시작""비동기 작업 완료" 사이에 출력된다는 것이다. 이건 비동기 작업이 백그라운드에서 실행되는 동안 메인 스레드가 계속해서 다음 작업을 수행한다는 것을 보여준다.

이것이 바로 비동기 프로그래밍의 핵심인거다.

이러한 비동기 프로그래밍을 잘 이용한다면, 시간이 오래 걸리는 작업을 백그라운드에서 처리하면서 동시에 다른 작업을 계속할 수 있어 앱의 반응성과 효율성이 향상될 것이다.

비동기 작업이 뭔지 모르는 나 같은 사람들은 읽어보자.

비유로 이해하자면,

동기 작업은 식당에서 음식을 주문한 후, 음식이 나올 때까지 자리에 앉아서 기다리는 것과 비슷하다.
음식을 다 받은 후에야 다음 일을 할 수 있다.

하지만 비동기 작업은 식당에서 음식을 주문하고, 기다리는동안 다른 일을 할 수 있는 것과 같다.
예를 들어 음식을 기다리는 동안 친구와 대화하거나 책을 읽는 것처럼 여러 가지를 동시에 처리할 수 있다. 음식이 다 나오면 직원이 알려주거나 음식을 받으면 그때 먹으면 된다.

비동기 작업장점은 작업을 기다리지 않아도 된다는거다.
시간이 오래 걸리는 작업을 요청한 후, 그 작업이 끝날 때까지 다른 일을 할 수 있다. 이로 인해 앱이 멈추지 않고 계속 작동하게 된다. 또한 효율적인 작업 처리로 여러 작업을 동시에 처리할 수 있어 CPU와 시스템 자원을 더 효율적으로 사용할 수 있다.



다시 넘어와서 GCD의 주요 이점을 한번 다시 정리해보자.

  • 성능 향상 : 여러 작업을 동시에 처리할 수 있다.
  • 간편한 사용 : 복잡한 쓰레드 관리를 직접 하지 않아도 된다.
  • 반응성 향상 : 긴 작업을 백그라운드에서 처리하여 UI가 멈추지 않는다.

이렇게 GCD를 사용하면 앱이 여러 가지 일을 동시에 효율적으로 처리할 수 있게 되어 전반적인 성능과 사용자 경험이 향상된다.

디스패치 큐의 종류 정리표

디스패치 큐 (Dispatch Queue)의 종류 설명
메인 큐 (Main Queue)메인 큐는 앱의 가장 중요한 작업, 즉 화면을 업데이트하거나 버튼을 눌렀을 때 반응하는 것 같은 일을 처리한다. 한 번에 하나씩 차례대로 처리하며, 가장 중요하기 때문에 여기서는 너무 오래 걸리는 일을 시키면 안 된다
글로벌 큐 (Global Queue)글로벌 큐는 백그라운드에서 일을 처리하는 곳이다. 즉, 화면에 당장 보여주지 않아도 되는 일이나 시간이 오래 걸리는 작업들을 여기서 처리한다. 이 큐는 여러 가지 우선순위로 나누어져 있어서, 작업의 중요도에 따라 빠르거나 느리게 처리한다.
커스텀 큐 (Custom Queue)커스텀 큐는 내가 직접 만드는 큐이다. 메인 큐나 글로벌 큐와는 다르게, 개발자가 필요할 때 직접 만들어서 사용하는 것이다. 커스텀 큐는 아래에 나오는 직렬 큐(Serial Queue)동시 큐(Concurrent Queue)로 나뉜다.
*직렬 큐(Serial Queue)직렬 큐는 작업을 차례대로 한 줄로 줄 세워서 하나씩 처리한다. 한 작업이 끝나야 다음 작업이 시작된다. 그래서 앱이 안정적으로 동작해야 할 때 유용하다.
*동시 큐(Concurrent Queue)동시 큐는 여러 작업을 동시에 처리할 수 있다. 그래서 빠르게 여러 작업을 하고 싶을 때 좋다. 하지만 너무 많은 일을 동시에 하게 하면 앱이 느려질 수도 있으니 주의해야 한다.
  • 메인 큐 : 앱의 화면 관련 작업을 한 번에 하나씩 처리한다.
  • 글로벌 큐 : 시간이 오래 걸리는 일을 처리하고 우선순위에 따라 빨리 또는 천천히 처리한다.
  • 커스텀 큐 : 내가 직접 만들 수 있는 큐로, 차례대로 또는 동시에 작업을 처리할 수 있다.

혹시나 만약 디스패치의 종류말고, GCD의 종류가 뭔가요? 라고 물어본다면......

GCD(Grand Central Dispatch) 의 종류에 대한 질문과 Dispatch Queue(디스패치 큐) 의 종류에 대한 질문은 엄연히 다르다. GCD 는 동시성 작업을 처리하기 위한 기술로, Dispatch Queue 는 그 중 하나의 개념임을 잊지말자. 만약 "GCD의 종류가 뭐가 있죠?" 라는 질문을 받는다면, GCD 의 기능이나 개념을 중심으로 설명해야 한다.

GCD의 주요 개념과 기능

GCD 자체는 종류가 있다기보다는 여러 기능과 구성 요소를 제공하는 기술 이다.

  • Dispatch Queue (디스패치 큐)

    작업을 처리하는 줄로, 여러 작업을 관리하고 실행하는 큐. 직렬 큐(Serial Queue)동시 큐(Concurrent Queue)가 있다. 메인 큐(Main Queue)와 글로벌 큐(Global Queue)도 Dispatch Queue의 일종이다.
    (위에 배운 내용)

  • Dispatch Group (디스패치 그룹)

    여러 작업을 그룹화해서, 그룹 내의 모든 작업이 끝났을 때를 알 수 있게 해준다. 예를 들어, 여러 파일 다운로드가 끝났을 때 알림을 받을 수 있다.

  • Dispatch Semaphore (디스패치 세마포어)

    동기화 도구로, 제한된 자원(예: 네트워크 연결, 파일 접근 등)에 대한 접근을 제어하는 데 사용된다. 여러 스레드가 동시에 자원을 사용하지 못하게 하고, 순차적으로 접근할 수 있게 해준다.

  • Dispatch Source (디스패치 소스)

    시스템 이벤트를 감시하고, 특정 이벤트가 발생하면 자동으로 작업을 실행할 수 있게 해준다. 예를 들어, 파일 시스템 변경이나 타이머 이벤트 같은 것들을 감지할 수 있다.

  • Dispatch Barrier (디스패치 베어리어)

    동시 큐에서 사용되는 특수한 작업으로, 이 작업이 실행될 때는 다른 동시 작업을 모두 멈추고 오직 하나의 작업만 실행하도록 만든다. 데이터의 읽기/쓰기 충돌을 방지할 때 유용하다.

GCD의 종류라고 할 수 있는 것은 이러한 기능들로 설명할 수 있을 것이다.

음..

오늘은 GCD(Grand Central Dispatch)와 그 안에서 사용되는 Dispatch Queue에 대해 깊이 있게 공부해보았다. 처음에 GCD는 조금 막연하게 느껴졌고 특히 비동기 작업과 큐의 종류에 대해 혼란스러웠지만.. 차근차근 개념을 정리하면서 이해가 조금씩 되어가는 기분이 들었다.

가장 어려웠던 부분은 Dispatch Queue의 종류와 GCD의 다양한 기능을 구분하는 것이었다. 처음에는 GCD의 종류를 묻는 질문에 어떻게 답해야 할지 혼란스러웠는데, 나중에 알게 된 사실은 GCD는 여러 동시성 작업을 관리하는 기술이고, 그 안에서 사용되는 주요 개념이 Dispatch Queue라는 것이다. Dispatch Queue는 다시 직렬 큐와 동시 큐로 나뉘는데, 이 두 개념의 차이를 파악하는 데도 시간이 꽤나 걸렸다.

또한 DispatchQueue.global()을 사용해 백그라운드에서 비동기 작업을 처리하는 이유를 이해하는 것이 처음엔 헷갈렸다. 왜 굳이 글로벌 동시 큐를 사용하는지, 그리고 async를 사용해 비동기 작업을 처리해야 하는 이유가 바로 메인 스레드와의 분리에 있음을 깨달았을 때 좀 더 명확하게 이해를 한 기분이었다.

공부를 마치고 GCD와 Dispatch Queue가 효율적인 동시성 처리를 위해 얼마나 중요한지 알게 됐다. 특히나 비동기 작업과 큐의 종류를 구분해서 사용할 줄 알아야 한다는 점이 핵심이었다. UI와 관련된 작업은 메인 큐에서 처리하고, 시간이 많이 걸리는 작업은 글로벌 큐나 커스텀 동시 큐에서 처리함으로써 앱이 부드럽게 동작할 수 있다는 점을 배웠따.

오늘 공부하면서 느낀 것은 동시성 작업 처리가 생각보다 복잡할 수 있을 것 같다는 점이다. 하지만 제대로 이해하고 활용하면 성능적으로 최적화하는 것과 사용자 경험을 크게 개선할 수 있다는 것도 알게 되었다.

앞으로는 GCD의 다른 기능인 Dispatch Group, Semaphore 등도 공부하면서 더 효율적인 작업 처리 방법을 익혀보고 싶다. 이렇게 공부한 것이 코드를 짤 때 바로바로 생각나면 얼마나 좋을까..!

profile
iOS 좋아. swift 좋아.

2개의 댓글

comment-user-thumbnail
2024년 10월 8일

오,, 멋있어요
2주 안에 완성할 수 있기를

1개의 답글