- 디스패치 그룹2023년 07월 02일
- 2료일
- 작성자
- 2023.07.02.: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 업데이트 실행
'면접준비' 카테고리의 다른 글
Combine(1)-WhatisCombine(publish&subscirbe) (0) 2023.07.09 lazy var (1) 2023.07.07 GCD queue. (0) 2023.07.02 Actor🕴🏻 (0) 2023.06.29 Frame vs Bounds (0) 2023.06.04 다음글이전글이전 글이 없습니다.댓글