Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

Olive Study Room

[Swift] GCD? (Dispatch Queue & OperationQueue) 본문

Coding/iOS

[Swift] GCD? (Dispatch Queue & OperationQueue)

Olive Dev 2021. 4. 6. 12:46

앞서 알아야 할 개념

  • 연산 대기열 (Operation Queue) : 비동기적으로 실행되어야 하는 작업을 객체 지향적인 방법으로 사용
  • 종속성 (Depedency) : A작업이 끝나면 B작업을 수행해야하는 관계

 

[ GCD ] 

Grand Central Dispatch(GCD) : 멀티코어 하드웨어에서 동시에 코드를 실행할 수 있도록 하는 애플 제공 C기반 저수준 api.
  • 해야할 일들을 넘기면 시스템에서 스레드를 할당하고 처리한다.
  • Dispatch queue 클래스를 갖는다.
  • FIFO 

 

[ Dispatch Queue ]

앱의 메인스레드나 백그라운드 스레드에서 작업 실행을 순차적 또는 동시에 관리하는 GCD의 클래스

1. Serial Dispatch Queue - 직렬 큐

  • 대기열의 작업을 차례로 처리한다.
  • 분산된 작업을 다른 하나의 스레드에서 처리한다.

2. Concurrent Distpatch Queue - 병렬 큐

  • 여러 작업을 동시에 처리한다.
  • 분산된 작업을 여러 개의 스레드에서 처리한다. 

* 기본은 Serial Queue이고 Concurrent Queue로 설정하려면 attribute로 선언해줘야 한다.

 

 

Main Queue

시스템 작동시 자동으로 생성되는 Serial Queue

UI관련 작업은 반드시 여기서 수행해야 한다.

 

Global Queue

백그라운드에서 동작하는 Concurrent Queue

끝나는 시간을 알 수 없을 때 주로 사용한다. ( 데이터, 네트워킹 등..)

처리를 위한 우선순위 파라미터를 제공한다.

 

우선순위 파라미터
useruserInteractive  > userInitiated > default > utility > background > unspecified

 

 

Dispatch Queue을 추가하면 GCD가 자동으로 알맞는 스레드를 생성하여 실행한다!

 


[ Operation & Operation Queue ]

연산(Operation)의 실행을 관리하고 대기열의 동작을 관리

Operation은 태스크(작업)과 관련된 코드와 데이터를 나타내는 추상클래스.

Operation Queue는 연산의 실행을 관리하고 대기열에 추가한 동작은 직접 제거가 불가능하다. 

연산은 작업이 끝날 때까지 대기열에 남아있다. ( 제거는 안되지만 취소는 가능함)

 

* 연산을 대기열에서 제거하는 방법

1. 연산 객체(Operation Object)의 cancel() 메서드를 호출

2. Operation Queue의 cancelAllOperation() 메서드를 호출

 

* 실행 중인 연산의 경우 연산 객체의 취소 상태를 확인하고 실행 중인 연산을 중지 후 완료 상태로 변경됨.

 

실행 순서 결정

1. 준비 상태에 따른 실행 순서  (task 간 종속성은 없을 때)
2. 우선순위에 따른 실행 순서 ( task 간 종속성은 없을 때)

(opeartion object지만 편의상 task로 표기.. ) 

 

1. 준비 상태, 2. 우선 순위 수준 3 .상호 작용 종속성에 따라 결정되는데, 대기 중인 모든 작업은 대기열 우선 순위가 동일하다. 대기열에 저장될 때 실행할 준비가 되면(=대기열에 제출된 순서대로 해당 속성이 ture로 반환됨) 실행된다. 그렇지 않으면 우선순위가 가장 높은 작업을 실행한다.

 

작업 준비 상태를 변경하면 실행순서가 변경되니까 대기열 의미에 의존하여 특정 작업 순서를 변경할 수 있다. 상호 작용 종속성은 서로 다른 작업 대기열에 있는 경우에도 작업에 대한 절대 실행 순서를 제공한다. operation object는 모든 종속 작업이 실행을 완료할 때까지 실행할 준비가 되지 않은 것으로 간주한다. 

 

 

[ Operation Queue의 주요 메소드 & 프로퍼티 ]

Operation 취소

// 대기 중이거나 실행 중인 모든 operation을 취소한다.
func cancelAllOperations()
  • 현재 실행 중인 경우 : opeartion object의 작업 코드가 취소 상태를 확인하고, 작업을 중지한 후 종료된 것으로 표시한다.
  • 대기열에 있지만 실행되지 않은 경우 : 취소 이벤트를 처리하고 종료된 것으로 표시하도록 start()메서드(동기적으로 처리)를 호출 (이해 못함..)

Operation 중단

var isSuspended: Bool { get set }

Operation 추가

 func addOperation(_ op: Operation)
 func addOperations(_ ops: [Operation], waitUntilFinished wait: Bool)
 func addOperation(_ block: @escaping () -> Void)

스레드 접근 차단

// 모든 대기 중인 opertion이 완료될 때까지 해당 스레드로의 접근을 차단한다.
func waitUntilAllOperationsAreFinished()

 

Operation Queue 를 활용한 비동기 프로그래밍 (버튼을 누르면 URL을 통해 이미지 다운받아와 띄워주는 코드)

http를 통해 url을 받아오는 경우 info.plist에 세팅을 해주고 왠만하면 optional binding을 해주는게 좋을 듯

@IBAction func downloadBtn(_ sender: UIButton) {
        // 이미지 다운로드 -> 이미지 뷰에 세팅
        // https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Multithreaded_process.svg/1920px-Multithreaded_process.svg.png
        let imageURL: URL = URL(string: "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Multithreaded_process.svg/1920px-Multithreaded_process.svg.png")!
        
        // 버튼을 누르면 imageData를 생성하는 과정에서 freeze. 다른 동작을 할 수 없음
        // -> main thread에서 작동하기 때문.
        let imageData: Data = try! Data.init(contentsOf: imageURL)
        let image: UIImage = UIImage(data: imageData)!
        
        self.imageView.image = image
        
    }

 

freeze되지 않도록 main thread에서 작동되었던 것을 서브 스레드로 옮겨 줌

 

@IBAction func downloadBtn(_ sender: UIButton) {
        // 이미지 다운로드 -> 이미지 뷰에 세팅
        // https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Multithreaded_process.svg/1920px-Multithreaded_process.svg.png
        let imageURL: URL = URL(string: "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Multithreaded_process.svg/1920px-Multithreaded_process.svg.png")!
        
        // 버튼을 누르면 imageData를 생성하는 과정에서 freeze. 다른 동작을 할 수 없음
        // -> main thread에서 작동하기 때문.
        // -> 다른 스레드에서 동작하도록 함
        OperationQueue().addOperation {
            let imageData: Data = try! Data.init(contentsOf: imageURL)
            let image: UIImage = UIImage(data: imageData)!
            // UI관련 코드는 메인 스레드에서 처리해야함
            OperationQueue.main.addOperation {
                self.imageView.image = image
            }
        }
    }

 

 


[ GCD vs Operation Queue ]

 

Operation Queue는 내부적으로 GCD위에서 동작된다. GCD에 기능이 추가된 것!

추가된 기능

1. 동시에 실행할 수 있는 operation최대 수 지정 가능

2. operation 일시 중지, 다시 시작 및 취소

그리고 위에서 소개한 프로퍼티도 사용 가능하다. 

 

이렇게 operation이 더 복잡하기 때문에 대부분 GCD를 사용한다. 

 

 

 

 

Comments