GCD에 대해 (DispatchGroup)

JinSeok Hong·2021년 9월 29일
0

왜 DispatchGroup을 이용할까?


GCD를 사용하게 되면 여러 스레드로 분산처리되어 작업을 처리하는 비동기 프로그래밍을 적용할 것이다. 이때 우리는 모든 작업이 다 끝난 시점이 필요하기 때문에 Dispatch Group을 사용한다.


예를 들어 앱의 첫 화면의 모든 이미지를 다운로드 한 후, 런치스크린이 종료하기를 원한다.
하지만 모든 이미지의 작업을 다운로드하는, 작업들을 다 끝난 시점을 정확하게 구분하지 못한다면 사진과 같은 사용자에게는 오류적인 화면을 보일 것이다. 이러한 문제를 해결하기 위해 작업들을 하나의 그룹으로 만들어서 모든 작업들이 끝난 시점 파악해야 한다.

DispatchGroup 사용 예시


let group1 = DispatchGroup()

DispatchQueue.global(qos: ).async(group: group1) { //동기적 함수 }
DispatchQueue.global(qos: ).async(group: group1) { //동기적 함수 }
DispatchQueue.global.async(group: group1){ //동기적 함수 }

//notifiy
group1.notify(queue. DispatchQueue.main) { [weak self] in
   self?.textLabel.text = "group1 completed"
   
//wait1
group1.wait(timeout: DispatchTime.distantFuture

//wait2
if group1.wait(timeout: .now() + 60) == .timedOut {
	print("60초 안이 작업이 모두 완료되지 않습니다.")
}

1) notify


원하는 작업들을 하나의 DispatchGroup에 묶고 다른 큐로 보내 비동기적으로 작업을 처리한다. 또한 이 모든 작업들이 완료되면 메인 스레드에서 작업을 모두 완료되었음을 알리는 메소드를 사용한다. 진행과정은 아래 그림과 같다.

2) wait

모든 작업이 완료 될 떄까지 현재 대기열을 차단하는 동기적 방법이다. 다만 notify와 다른 점은 메인스레드에서 호출하면 안된다는 것이다. 왜냐하면 메인 스레드에서 기다린다면 앱이 멈춰버리기 때문에 다른 스레드를 이용하여 처리해야한다.

  • group1.wait(timeout : DispatchTime.distantFuture)
    무작적 기다리기는 방법이다.


  • if group1.wait(timeout: .now() + 60) == .tiemdOut
    시간의 제한을 두는 것이다.


DispatchGroup 주의할점


앞서 각 스레드로 작업 처리된 함수들은 동기적 함수였다.
DispatchQueue.global(qos: ).async(group: group1) { //동기적 함수 }

그런데 만약 내부 함수가 동기적 함수가 아니라 비동기적 함수라면 어떤 문제가 있을까? 비동기적 메소드를 사용한다면 작업을 다른 스레드로 보내고 바로 리턴을 받기 때문에 작업을 동시에 진행할 뿐 작업의 완료는 아니다. 따라서 내가 원하는 작업이 종료되는 시점을 잘못 파악할 수 있다. 이러한 경우에는 DispatchGroup의 enter, leave 를 사용해야한다. 이는 입장한 개수와 퇴장한 개수를 동일했을 때 그룹의 작업들이 모두 끝났다고 판단을 할 수 있도록 만든 것이다. 사용 예시는 아래와 같다.

queue.async(group: group1){
	group1.enter()
    someAsyncMethod{//비동기함수의 클로저 
    	group1.leave() //끝났으면 퇴장 알림
    }
}

마치며..


비동기 함수를 이용하면서도 작업의 끝난 시점들을 파악하여 처리하는 것을 배우면서 최근에 Kakao Blind 2차 테스트가 생각난다.. 지금껏 알고리즘을 C++로 풀었지만 이번 테스트에서는 API 호출과 Json Parser를 사용해야했기 때문에 아직 자신이 없는 Swift로 시험을 봤다. 당시 요구사항에 맞는 시뮬레이션을 만들었어야 했는데 여러 API를 호출하고 내가 원하는 작업들의 완료에 따른 처리를 하는 것이 너무 어려웠다. 분명 Alamofire라는 비동기 라이브러리를 사용하고 있음에도 원하는 수행 단계를 만들어내지 못하는 스스로의 부족함을 느꼈던 계기였다. GCD와 클로저 등 최근에 배우고 있는 비동기 프로그래밍에 대한 개념과 응용을 키워 효율적인 앱을 만들어가는 능력을 키우도록 노력해야겠다.

0개의 댓글