디스패치 그룹

2023. 7. 2. 12:54·면접준비

iOS 개발에서 비동기 작업을 그룹화하고 실행을 제어하는 방법은 매우 중요하다. 여러 개의 비동기 작업이 동시에 실행될 때 작업이 언제 끝나는지 감지하고 후속 작업을 실행해야 하는 경우가 많다. 이때 DispatchGroup과 DispatchSemaphore가 유용하게 쓰인다.

1. DispatchGroup

(1) DispatchGroup이란?

DispatchGroup을 사용하면 여러 개의 비동기 작업을 그룹화하여 해당 그룹의 모든 작업이 끝났을 때 특정 코드를 실행할 수 있다.

이것을 활용하면 예를 들어 런치스크린 이후 첫 화면을 로딩할 때, 모든 필수 리소스(이미지, 데이터)를 다 받은 후 UI를 업데이트할 수 있다

그룹1의 작업이 여러쓰레드에서 작업을 해도 묶여있고 마지막 task가 끝나는 시점을 알 수 있다.

ex) 런치스크린 후 앱첫화면 나오는데 메인에서 이미지를 다 다운받지 못한다면? 에러처럼 보이게 된다. 그러면 마지막꺼까지 다 받고 앱을 그려주자!

(2) DispatchGroup 사용법

let group1 = DispatchGroup()
DispatchQueue.global(qos:).async(group: group1){}
group1.notify(queue.DispatchQueue.main){[weak self] in 
	self.textLabel.text = "끝"}

• async(group: group)을 사용하여 그룹 내에서 실행할 작업을 등록한다.

• group.notify(queue:)를 사용하여 그룹 내 모든 작업이 끝났을 때 실행할 코드를 등록한다.

 

모든작업이 끝날때까지 현재 대기열 블락하는 동기적 방법

group1.wait(timeout: .now() + 60) == .timedOut {}

당연히 메인에서는 하면안되겟죠~? 어느정도 시간을 주고 그 시간 이후에는 다른 작업을 한다는 코드!

 비동기 작업을 직접 추가하는 방법

위 방식은 DispatchQueue의 async(group:)를 사용하는 방식이지만, 비동기 함수 내부에서 작업을 감싸야 하는 경우가 있다.

예를 들어 URLSession을 이용한 네트워크 요청을 DispatchGroup에 포함하려면 enter()와 leave()를 명시적으로 사용해야 한다.

let group = DispatchGroup()

func fetchData(from url: String) {
    group.enter() // 그룹에 입장 (+1)
    URLSession.shared.dataTask(with: URL(string: url)!) { data, response, error in
        defer { group.leave() } // 네트워크 응답이 끝나면 그룹에서 나감 (-1)
        if let data = data {
            print("다운로드 완료: \(data.count) bytes")
        }
    }.resume()
}

fetchData(from: "https://example.com/data1.json")
fetchData(from: "https://example.com/data2.json")

group.notify(queue: DispatchQueue.main) {
    print("모든 데이터 다운로드 완료! UI 업데이트")
}

• group.enter()를 사용해 그룹에 직접 추가

• group.leave()를 사용해 작업이 끝났음을 명시적으로 알림

• 모든 작업이 끝난 후 group.notify가 실행됨

2. DispatchSemaphore

1) DispatchSemaphore란?

DispatchSemaphore는 동시에 실행할 수 있는 작업의 개수를 제한하는 동기화 도구다.

예를 들어, 한 번에 너무 많은 네트워크 요청을 보내면 서버에 부담이 될 수 있다. 이럴 때 한 번에 최대 3개의 네트워크 요청만 허용하고, 기존 작업이 끝나면 새로운 작업이 실행되도록 조절할 수 있다.

let semaphore = DispatchSemaphore(value: 3)
queue.async(group: group1){
	semaphore.wait()
    AsyncMethod{
    	semaphore.signal()
    }}

작업은 최대한번에3개씩 실행가능하다. wait을 3개. 종료하면 signal메소드가 실행되면 큐에서 다음 작업이 배치되어 실행. 

 

오늘 배운걸로 만약 내가 실무에 적용을 한다면 어떻게 적용할 수 있을지 생각해보았다.

1. 런치 스크린 이후 필수 리소스를 로딩할 때

• DispatchGroup을 이용해 모든 이미지, 데이터 로딩이 끝난 후 화면을 표시

2. API 요청을 동시에 여러 개 보내되, 요청 개수를 제한할 때

• DispatchSemaphore를 이용해 서버 부하를 줄이면서 요청을 보냄

3. 비동기 작업이 끝난 후 특정 UI 업데이트가 필요할 때

• DispatchGroup.notify를 사용해 모든 작업이 끝난 후 한 번만 UI 업데이트 실행

 

'면접준비' 카테고리의 다른 글

TaskGroup  (0) 2023.08.13
Swift Concurrency - Async/Await⭐️  (0) 2023.08.08
GCD queue.  (0) 2023.07.02
Actor🕴🏻  (0) 2023.06.29
Frame vs Bounds  (1) 2023.06.04
'면접준비' 카테고리의 다른 글
  • TaskGroup
  • Swift Concurrency - Async/Await⭐️
  • GCD queue.
  • Actor🕴🏻
2료일
2료일
좌충우돌 모든것을 다 정리하려고 노력하는 J가 되려고 하는 세미개발자의 블로그입니다. 편하게 보고 가세요
  • 2료일
    GPT에게서 살아남기
    2료일
  • 전체
    오늘
    어제
    • 분류 전체보기 (120) N
      • SWIFT개발 (29)
      • 알고리즘 (25)
      • Design (6)
      • ARkit (1)
      • 면접준비 (30)
      • UIkit (2)
      • Vapor-Server with swift (3)
      • 디자인패턴 (5)
      • 반응형프로그래밍 (12)
      • CS (3)
      • 도서관 (1) N
  • 인기 글

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
2료일
디스패치 그룹
상단으로

티스토리툴바