[클라우드인증] 동기 구조의 패킷의 비동기 프로세스 결합
dispatch_group과 NSOperationQueue는 비동기 작업의 순서 및 동시성을 제어하기 위해 사용되지만, 기능과 용도가 약간 다릅니다. 각각의 차이를 자세히 살펴보겠습니다.
1. dispatch_group
dispatch_group은 **GCD(Grand Central Dispatch)**를 기반으로, 여러 비동기 작업을 그룹화하여 작업 완료 여부를 관리하는 방식입니다. 여러 작업을 그룹에 추가한 후, 그룹 내 모든 작업이 완료될 때까지 기다리거나 완료 후 특정 작업을 실행할 수 있습니다.
주요 특징
- 동시성 제어가 아니라 작업 완료 확인에 집중합니다. 즉, 여러 작업이 동시에 실행될 수 있고, 모든 작업이 완료될 때까지 대기하거나 완료 후 특정 작업을 실행할 때 사용됩니다.
- 단순한 작업 그룹화에 적합하여 여러 비동기 작업이 완료되었는지 확인하거나, 완료 후 특정 작업을 수행하는 데 유용합니다.
사용 예시
예를 들어, 여러 비동기 네트워크 요청을 병렬로 수행한 뒤, 모든 요청이 완료되었을 때 결과를 처리하는 데 유용합니다.
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// 첫 번째 작업
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// 두 번째 작업
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 모든 작업 완료 후 실행할 작업
NSLog(@"모든 작업 완료");
});
장점
- 간단하고 가볍게 여러 비동기 작업의 완료 여부를 확인할 수 있습니다.
- 동기화 작업: dispatch_group_wait을 사용하면 모든 작업이 완료될 때까지 기다릴 수 있습니다.
단점
- 작업 순서 제어에는 적합하지 않으며, 단지 작업의 완료를 대기하는 데 초점이 맞춰져 있습니다.
- 작업에 의존성이나 우선순위 설정이 필요할 경우에는 적합하지 않습니다.
2. NSOperationQueue
NSOperationQueue는 더 복잡한 작업 제어가 필요한 경우에 적합하며, 여러 NSOperation 작업의 순서, 의존성, 우선순위 등을 설정하여 실행할 수 있습니다.
주요 특징
- 작업의 우선순위, 의존성, 동시성 제어를 제공합니다. 여러 작업이 실행될 때, 작업 간의 순서를 정하거나 특정 작업이 완료된 후 다른 작업을 실행하는 등, 복잡한 작업 흐름을 설정할 수 있습니다.
- 작업이 동기 또는 비동기적으로 실행될 수 있는 방식을 지원하며, 작업 완료 시 콜백을 통해 후속 작업을 쉽게 추가할 수 있습니다.
사용 예시
예를 들어, 특정 작업이 완료된 후에만 다음 작업을 실행하고, 작업 간의 우선순위를 설정하는 데 유용합니다.
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 작업 1 정의
NSOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"작업 1 실행");
}];
// 작업 2 정의 (작업 1이 완료된 후 실행)
NSOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"작업 2 실행");
}];
[operation2 addDependency:operation1]; // 작업 1이 완료된 후 실행되도록 설정
// 작업 3 정의 (우선순위 설정)
NSOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"작업 3 실행");
}];
operation3.queuePriority = NSOperationQueuePriorityHigh; // 우선순위 높게 설정
[queue addOperations:@[operation1, operation2, operation3] waitUntilFinished:NO];
장점
- 의존성 설정: 작업 간의 의존 관계를 설정할 수 있어, 특정 작업이 완료된 후에 다른 작업이 실행되도록 할 수 있습니다.
- 우선순위 설정: 작업의 우선순위를 지정할 수 있어, 중요한 작업이 먼저 처리되도록 제어할 수 있습니다.
- 취소 및 재시도 가능: NSOperation은 작업의 취소가 가능하며, 재시도할 수도 있습니다.
단점
- 상대적으로 복잡도가 높고 메모리 사용량이 많아질 수 있습니다.
- 간단한 완료 여부 확인만 필요할 경우에는 오히려 불필요하게 복잡할 수 있습니다.
dispatch_group과 NSOperationQueue 비교 요약
특징dispatch_groupNSOperationQueue
용도 | 여러 비동기 작업의 완료 여부 확인 | 작업 순서, 의존성, 우선순위 제어 |
동시성 제어 | 작업 간 순서나 의존성 설정은 불가능 | 의존성 및 우선순위 제어 가능 |
작업 완료 후 처리 | dispatch_group_notify로 모든 작업 완료 후 처리 | 완료된 작업 이후의 작업을 순서에 맞춰 처리 가능 |
작업 취소/재시도 | 기본적으로 지원되지 않음 | 작업 취소, 재시도 가능 |
복잡한 작업 흐름 제어 | 비동기 작업 완료 확인 정도의 간단한 흐름에 적합 | 복잡한 작업 흐름 제어에 적합 |
사용 시기 | 여러 비동기 작업이 완료된 후 후속 작업을 수행할 때 유용 | 작업 간 순서, 의존성 및 우선순위가 필요한 경우 |
정리
- dispatch_group은 단순히 비동기 작업이 모두 완료되었는지 확인하거나, 완료 후 특정 작업을 수행하는 데 적합합니다. 간단한 병렬 작업의 완료 여부 확인 용도로 사용하기 좋습니다.
- NSOperationQueue는 작업 간 의존성, 우선순위, 동시성 제어가 필요한 경우에 적합합니다. 각 작업을 보다 세밀하게 관리하고, 복잡한 비동기 작업 흐름을 구성해야 할 때 유리합니다.
delay와 sleep을 사용하여 문제를 해결할 수 있는 경우도 있지만, 동기적 실행 흐름을 정확히 제어하거나, 복잡한 비동기 작업 간의 의존성을 관리해야 할 경우에는 NSOperationQueue와 dispatch_group을 사용하는 것이 더 적합합니다. delay와 sleep을 사용하면 제어할 수 있는 범위가 제한적이고, 비동기 작업 관리에 불편함이 따를 수 있기 때문입니다.
1. delay와 sleep의 한계점
- sleep: 동기적 일시 정지로, 지정된 시간 동안 현재 스레드를 멈추게 합니다. 메인 스레드에서 sleep을 사용하면 UI가 멈추고 사용자 경험이 저하될 수 있어 비동기 처리나 비동기 흐름 제어가 필요한 경우에는 부적합합니다.
- delay (performSelector:afterDelay: 또는 dispatch_after): 지연된 작업을 예약하는 용도로 사용되며, 비동기적 흐름을 만들 수 있지만 동기적인 작업 완료 여부를 보장하거나 작업 간 의존성을 설정하는 데는 한계가 있습니다.
2. delay와 sleep을 사용한 경우의 제한된 시나리오
단순히 특정 시간 후에 특정 작업을 실행해야 하거나, 비동기 작업의 순서가 중요하지 않은 경우에는 delay와 sleep으로 간단히 해결할 수 있습니다. 예를 들어:
- 특정 작업 A가 완료된 후 지연을 두고 작업 B를 실행하는 경우:
[self performSelector:@selector(taskB) withObject:nil afterDelay:2.0];
- 비동기 함수 호출 없이 단순히 일정 시간 후에 다음 작업을 실행하는 경우:
sleep(2); // 2초 동안 일시 정지
[self taskB];
이러한 경우에는 NSOperationQueue나 dispatch_group이 필요하지 않을 수 있습니다.
3. 복잡한 비동기 흐름에서는 한계가 있음
하지만, 다음과 같은 경우 delay와 sleep만으로는 한계가 있습니다.
- 작업 완료를 기다린 후에만 다음 작업을 수행해야 하는 경우: dispatch_group은 여러 비동기 작업이 모두 완료된 후 특정 작업을 실행할 때 유용한데, delay와 sleep으로는 이런 제어가 어렵습니다.
- 작업 간의 의존성 관리: NSOperationQueue를 사용하면 작업 간 의존성을 쉽게 설정할 수 있지만, delay와 sleep만으로는 의존 관계를 표현하기 어려워 복잡한 작업 순서를 제어하기 어렵습니다.
- 작업 취소 및 재시도: NSOperationQueue는 작업을 취소하거나 재시도할 수 있어 유연한 오류 처리와 제어가 가능합니다. 반면, delay와 sleep은 이 기능을 제공하지 않아 오류 상황에 대처하기 어렵습니다.
+ 증권에서는 속도가 굉장히 중요한데 sleep으로 잡아두면 그만큼 패킷 통신 속도가 저하되는 이슈
4. 권장하는 접근 방식
delay와 sleep으로 간단한 지연 실행은 구현할 수 있지만, 비동기 작업의 완료를 보장해야 하거나 작업 간 순서와 의존성을 엄격히 제어해야 할 경우 NSOperationQueue와 dispatch_group을 사용하는 것이 훨씬 더 적합합니다.