안녕하세여 린다임니다.
저번 글에 이어서 GCD의 DispatchGroup에 대해서 정리해보려고 해요.
(https://sy-catbutler.tistory.com/31)
마찬가지로 앨런님의 강의를 보고 정리한 글입니다!
밑에서부터 편한 말투로 정리할게요!
그룹이라는 개념이 필요한 이유, 그룹이 무엇인가?
- 지금 우리는 작업을 비동기, 다른 큐로 보내서 여러 쓰레드로 보내서 분산처리를 하고 있음
- 즉 하나의 일이 여러가지로 나뉘어져서 처리중인데 이렇게 여러 쓰레드로 보낸 작업들이 언제 끝나는지 알고 싶다에서 생성된 개념
- 분산된 어떤 일이 모두 끝난 시점을 알고 싶을 때 (== Group의 작업이 다 끝난 시점을 알고 싶을 때)
- 분산된 어떤 일 = 그룹
여러 쓰레드에서 일을 하지만, 원래는 하나의 일임 == 그룹
얘) 여러 애니메이션 효과가 겹쳐있을 때, 애니메이션이 모두 끝난 타이밍을 알고 싶다.
Swift에서 DispatchGroup를 생성하는 방법
let group1 = DispatchGroup()
DispatchQueue.global(qos: ).async(group: group1) { }
// ()을 통해, 큐로 작업을 보낼때, 어떤 그룹에 넣을 것인지 정해주기
async 파라미터 안에 그룹을 넣어주면, 그룹으로써 해당 작업이 묶이게 되는 것
그룹으로 묶인 작업이 끝나는 시점을 아는 방법 → 끝나면 해당 코드가{} 실행됨
group1.notifty(queue: DispatchQueue.main) { [weak self] in
self?.textLabel.text = "모든 작업이 완료되었습니다"
}
사용법
- DispatchGroup로 그룹 생성
- 작업을 보낼때 group1이라고 꼬리표를 붙이기
- 모든 작업이 끝났을 때를 알기 위해 notify를 사용하기
DispatchGroup에서 동기적인 기다림이 필요할때 (-> wait 을 사용하자)
- 특정 작업이 끝날때까지 기다리고 싶을 때 wait을 사용하면 기다릴 수 있음
let group = DispatchGroup()
group1.wait(timeout: DispatchTime.distantFuture)
wait 메서드는..
- 그룹 작업이 다 끝나야만 다른 작업을 할 수 있는 상황일 때 사용하면 됨
- 비동기인 작업들을 묶어서 동기적으로 작동하게 만드는 것
- 즉, 작업이 완료될 때까지 현재큐 블락하는 것이기 때문에 동일한 그룹내에서 해당 큐를 사용하는 작업이 있으면 안 된다. (있을경우 DeadLock 발생 가능)
주의사항
- 메인큐(메인쓰레드)에서는 wait메서드를 사용하면 안 됨 → 버벅임 발생
- 메인큐가 아닌 이미 다른큐에서는 wait 메서드를 사용 가능 할 수 있음
비동기에서 DispatchQueue Group의 사용
Q1. 디스패치 그룹안에 있는 클로저 내에서 비동기 함수를 호츨할 때 어떤 문제가 있을까?
let group1 = DispatchGroup()
DispatchQueue.global(qos: ).async(group: group1) {
// 큐로 보내는 클로저 내부에 비동기 함수가 있을때
print("async group task started")
// 비동기 클로저
asyncMethoud(input: url) { result in
...
}
print("async group task finished")
}
- group1이라고 작업을 묶어서 다른 쓰레드로 배치됨
- 다른 쓰레드로 보내진 작업 안에는 print, closure, print 작업이 있음
- 먼저 print 문부터 실행 → 비동기 클로저 실행
- 비동기 클로저이기 때문에 클로저 안의 task는 다른 큐로 보내고 다른 쓰레드로 보내지면 리턴되고,
finished print 문이 실행되고 종료됨 - 클로저 내부의 task까지 끝나는 시점을 알 수 없음! (제대로 일이 끝난 시점을 잘못 인식함)
이를 해결하기 위해서는 enter(), leaver() 를 사용
- 그룹을 보낼 때 enter()를 통해서 들어간다는 명령을 넣어주고
- 실제 클로저 내부의 일이 끝날 때 group1.leave()로 떠난다고 명령을 넣어준다.
- 즉, 입장과 퇴장을 정의해주기
let group1 = DispatchGroup()
DispatchQueue.global(qos: ).async(group: group1) {
group1.enter() // 입장
print("async group task started")
// 비동기 클로저
asyncMethoud(input: url) { result in
// leave를 통해 언제 퇴장해야하는지 알려주기
group1.leave() // 퇴장
}
print("async group task finished")
}
즉, DispathGroup는 여러가지 일을 묶고 싶을 때 사용하면 되고
비동기에서 올바르게 사용하기 위해서는 쓰레드를 잘 고려하여 enter, leave를 적절하게 사용해야 한다!
'Swift' 카테고리의 다른 글
Tuist와 Signing, Tuist 에서 프로비저닝 프로파일 설정하기 (0) | 2024.02.05 |
---|---|
DispatchQueue(GCD)를 알아보자4, DispatchWorkItem과 Semaphore (0) | 2024.01.15 |
SwiftUI로 디자인 시스템(Design System)을 구현해보자 (SYM - Part 1) (1) | 2024.01.06 |
냅다 정리해보는 Combine 개념, (Combine을 알아보자 1) (0) | 2023.12.10 |
iOS Push Notification 구현하기 (feat, Firebase) (0) | 2023.12.01 |