iOS/Swift

[Swift] OperationQueue

_Rey 2022. 4. 19. 16:36

DispatchQueue는 들어봤는데 OperationQueue는 처음 들어봤다.

OperationQueue에 대해서 아주 간단히 알아보자.

 

오늘 볼 두 개의 키위드 Document다.

https://developer.apple.com/documentation/foundation/operation

https://developer.apple.com/documentation/foundation/operationqueue

 

동시성(Concurrency) 프로그래밍을 위한 개념이라는 것을 알 수 있다.

*병렬성(Parallelism)과는 다른 개념입니다!

출처: https://www.codeproject.com/Articles/1267757/Concurrency-vs-Parallelism

 

동시성과 병렬성에 대한 기가막힌 사진이 있어 가져와봤습니다.

 

다시 OperationQueue로 돌아와서!

OperationQueue는 Operation object를 우선 순위와 준비 상태에 따라 호출한다.

그럼 Operation은 무엇인가?

 

"Because the Operation class is an abstract class, you do not use it directly but instead subclass or use one of the system-defined subclasses to perform the actual task."

Operation은 추상적인 객체이기 때문에, 직접 사용하지 않고 하위 클래스를 통해 task를 수행한다.

 

사실 무슨 말인지 잘 모르겠다 ㅎㅎ 직접 사용해보자.

let operationQueue = OperationQueue()
// let operationQueue = OperationQueue.main 으로 메인 Thread에서 호출도 가능하다.

let blockOperation0 = BlockOperation {
    for i in 0...10 {
        print("Operation Queue Before \(i)")
    }
}
let blockOperation1 = BlockOperation {
    for i in 0...10 {
        print("Operation Queue After \(i)")
    }
}
operationQueue.addOperation(blockOperation0)
operationQueue.addOperation(blockOperation1)
// blockOperation0과 blockOperation1이 뒤죽박죽 실행된다.

BlockOperation은 하나 이상의 블럭(코드블럭)을 동시에 실행하는 것을 관리할 수 있도록 하는 Operation이며,

Operation을 상속받았다.

 

코드가 뒤죽박죽 실행되는게 뭐가 중요한가 싶다.

하지만 blockOperation0과 blockOperation1이 단순 프린트가 아닌 특수한 기능(네트워크를 통한 다운로드 등)을 수행한다면

동시성 처리가 필요하게 될 것이다.

ex) 사진 또는 데이터 다운로드로 인해 프로세스가 멈춘 것처럼 보이는 문제

 

그럼 예시 상황처럼 하나의 Queue(Thread)에서 사진을 다운받고, 해당 사진 데이터를 컨트롤 해야한다면 어떨까요?

사진 데이터를 컨트롤 하는 블록은 무조건 사진이 다운받은 뒤에 실행이 되어야합니다.

// blockOperation1은 blockOperation0가 끝나서야 실행됩니다.
blockOperation1.addDependency(blockOperation0)
operationQueue.addOperation(blockOperation0)
operationQueue.addOperation(blockOperation1)

// 다음 코드처럼 addOperation의 순서가 바뀌어도 Dependency는 정상적으로 적용됩니다.
blockOperation1.addDependency(blockOperation0)
operationQueue.addOperation(blockOperation1)
operationQueue.addOperation(blockOperation0)

 

 

실제 코드처럼 흉내내어 보면 다음과 같다.

let operationQueue = OperationQueue()

let blockOperation0 = BlockOperation {
    for i in 1...10 {
        print("사진 다운 받는 중... \(i)0%")
    }
}
let blockOperation1 = BlockOperation {
    for i in 0...10 {
        print("사진 데이터 핸들링 중... \(i)0%")
    }
}
blockOperation1.addDependency(blockOperation0)
operationQueue.addOperation(blockOperation1)
operationQueue.addOperation(blockOperation0)

for i in 0...20 {
    print("Main Task입니다. \(i)")
}

 

실행결과

더보기

Main Task입니다. 0

사진 다운 받는 ... 10%

Main Task입니다. 1

Main Task입니다. 2

Main Task입니다. 3

사진 다운 받는 ... 20%

Main Task입니다. 4

사진 다운 받는 ... 30%

사진 다운 받는 ... 40%

Main Task입니다. 5

Main Task입니다. 6

사진 다운 받는 ... 50%

Main Task입니다. 7

사진 다운 받는 ... 60%

사진 다운 받는 ... 70%

사진 다운 받는 ... 80%

사진 다운 받는 ... 90%

사진 다운 받는 ... 100%

Main Task입니다. 8

사진 데이터 핸들링 ... 00%

사진 데이터 핸들링 ... 10%

Main Task입니다. 9

사진 데이터 핸들링 ... 20%

Main Task입니다. 10

사진 데이터 핸들링 ... 30%

Main Task입니다. 11

사진 데이터 핸들링 ... 40%

Main Task입니다. 12

사진 데이터 핸들링 ... 50%

Main Task입니다. 13

사진 데이터 핸들링 ... 60%

Main Task입니다. 14

사진 데이터 핸들링 ... 70%

Main Task입니다. 15

사진 데이터 핸들링 ... 80%

Main Task입니다. 16

사진 데이터 핸들링 ... 90%

Main Task입니다. 17

Main Task입니다. 18

Main Task입니다. 19

Main Task입니다. 20

사진 데이터 핸들링 ... 100%

MainTask가 실행되면서 OperationQueue의 블럭도 동시에 실행되는 것을 볼 수 있다.

 

 

Block에 대한 정확한 개념을 이해하기 위해서는

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html

해당 문서를 읽으면 된다.

 

+ 동시성(Concurrency) 프로그래밍 가이드

https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html

 

알아야할게 너무 많다...