Swift (Foundation)의 Operation과 OperationQueue는 더 높은 수준의 비동기 작업 제어를 위한 도구입니다.
GCD 기반 작업과 달리, 캡슐화, 의존성, 취소(cancellation), 상태 추적 등이 구조적으로 제공됩니다.
직역 하자면
Operation 클래스는 추상 클래스이기 때문에 직접 사용하지 않고 서브 클래스를 사용하거나 시스템 정의 하위 클래스(NSInvocationOperation 또는 BlockOperation) 중 하나를 사용하여 실제 작업을 수행합니다. 추상적임에도 불구하고, Operation의 기본 구현에는 작업의 안전한 실행을 조정하기 위한 중요한 논리가 포함되어 있습니다. 이 내장 논리의 존재는 다른 시스템 개체와 올바르게 작동하는지 확인하는 데 필요한 접착제 코드보다는 작업의 실제 구현에 집중할 수 있습니다.
작업 객체는 싱글 샷 객체입니다. 즉, 작업을 한 번 실행하고 다시 실행하는 데 사용할 수 없습니다. 일반적으로 작업을 작업 대기열(OperationQueue 클래스의 인스턴스)에 추가하여 작업을 실행합니다. 작업 대기열은 보조 스레드에서 직접 실행하거나 libdispatch 라이브러리(Grand Central Dispatch라고도 함)를 사용하여 간접적으로 작업을 실행합니다. 대기열이 작업을 실행하는 방법에 대한 자세한 내용은 OperationQueue를 참조하십시오.
작업 대기열을 사용하고 싶지 않다면, 코드에서 직접 start() 메서드를 호출하여 직접 작업을 실행할 수 있습니다. 작업을 수동으로 실행하는 것은 준비 상태가 아닌 작업을 시작하면 예외가 발생하기 때문에 코드에 더 많은 부담을 줍니다. isReady 속성은 작업 준비 상태를 보고합니다.
작업 대기열은 우선 순위와 준비 상태에 따라 대기열에 있는 작업 객체를 호출합니다. 대기열에 작업을 추가한 후에는 작업이 작업을 완료할 때까지 대기열에 남아 있습니다. 작업을 추가한 후에는 대기열에서 직접 제거할 수 없습니다.
Operation
을 서브클래싱하거나 클로저 기반 BlockOperation
을 사용함으로써 하나의 작업(task)을 명확하게 캡슐화할 수 있음 Operation
은 다음과 같이 명확한 상태(Status) 를 제공합니다:.isReady
.isExecuting
.isFinished
.isCancelled
operation.addDependency(otherOperation)
으로 선행 작업 후행 작업으로 순서를 지정할 수 있음 OperationQueue
는 이 종속성을 자동으로 해석하여 실행 순서를 관리operation.cancel()
호출로 작업 취소를 요청 .isCancelled
상태는 작업이 Pending, Ready, Executing 상태에 있을 때만 넘어올 수 있음 .isFinished
상태로 전이됨isCancelled
체크하여, 가능한 빨리 종료할 수 있도록 구현 필요Pending (큐 대기) ---> Ready (실행 조건 만족)
⇓ ⇓
Cancelled? ---------------> Executing (start() 호출)
⇓
Finished (작업 완료)
OperationQueue
에 추가된 상태 start()
실행) Finished
로 전이 Operation
은 자신이 수행할 단일 책임(single responsibility) 만 가짐 Progress
API 또는 커스텀 상태 제공을 통해 작업 진행 상황 추적 가능 Operation
으로 분리Swift에서 비동기 작업을 수행하는 대표적인 두 가지 방법은 GCD(Grand Central Dispatch) 와 Operation / OperationQueue 입니다.
Operation은 내부적으로 GCD를 활용하며, 더 높은 수준의 추상화와 기능(종속성, 취소 등)을 제공합니다.
구분 | GCD | Operation / OperationQueue |
---|---|---|
정의 | 동시에 실행될 작업 단위(closure) 를 큐에 제출 | Operation 객체로 작업을 캡슐화 |
종속성 | 종속성 설정 불가 (A 후에 B 보장 어려움) | .addDependency() 로 작업 간 순서 보장 가능 |
재사용성 | Closure 중심 → 재사용 어려움 | 클래스 서브클래싱 / BlockOperation 으로 모듈화 가능 |
취소 | 취소 불가 | cancel() 로 취소 가능 |
상태 추적 | 작업 상태 추적 불가 | .isReady , .isExecuting , .isFinished , .isCancelled 로 상태 확인 가능 |
모듈화 | 코드 블록 단위 실행 | Operation 클래스로 기능 캡슐화 가능 |
Operation
을 subclassing → main()
오버라이드main()
: setup + 작업 실행, 반드시 super.main()
호출 금지start()
: 스레드 생성 또는 비동기 작업 호출 시작 isAsynchronous
isExecuting
isFinished
isCancelled
let blockOperation = BlockOperation {
print("Executing!")
}
let queue = OperationQueue()
queue.addOperation(blockOperation)
final class ContentImportOperation: Operation {
let itemProvider: NSItemProvider
init(itemProvider: NSItemProvider) {
self.itemProvider = itemProvider
super.init()
}
override func main() {
guard !isCancelled else { return }
print("(main) Importing content...")
// .. import the content using the item provider
}
}
let queue = OperationQueue()
let fileURL = URL(fileURLWithPath: "..")
let contentImportOperation = ContentImportOperation(itemProvider: NSItemProvider(contentsOf: fileURL)!)
contentImportOperation.completionBlock = {
print("Importing completed!")
}
queue.addOperation(contentImportOperation)
// 출력 예시:
// (main) Importing content...
// Importing completed!
⚠️ 주의: Operation 인스턴스는 한 번만 실행 가능
(완료 or 취소된 이후에는 동일 인스턴스를 다시 실행할 수 없음)
B 작업은 A 작업이 끝난 뒤 실행되도록 종속성 설정 가능:
let fileURL = URL(fileURLWithPath: "..")
let contentImportOperation = ContentImportOperation(itemProvider: NSItemProvider(contentsOf: fileURL)!)
contentImportOperation.completionBlock = {
print("Importing completed!")
}
let contentUploadOperation = ContentUploadOperation(itemProvider: NSItemProvider(contentsOf: fileURL)!)
contentUploadOperation.addDependency(contentImportOperation)
contentUploadOperation.completionBlock = {
print("Uploading completed!")
}
queue.addOperations([contentImportOperation, contentUploadOperation], waitUntilFinished: true)
// 출력 예시:
// (main) Importing content...
// (main) Uploading content...
// Importing completed!
// Uploading completed!
Operation
서브클래싱 또는 BlockOperation
으로 작업 캡슐화 .addDependency()
로 작업 순서 정의 cancel()
호출 처리 & isCancelled
체크 구현 isReady
, isExecuting
, isFinished
, isCancelled
) 추적 가능한 구조 설계 에 작업 추가 및 동시성 조절 (예:
maxConcurrentOperationCount`) Progress
또는 커스텀 상태 로깅으로 진행 상황 시각화