Tong's Blog

[Swift] Operation(NSOperation)이란? 본문

iOS/Swift

[Swift] Operation(NSOperation)이란?

통스 2020. 10. 28. 10:00
반응형

안녕하세요. 오늘은 Operation(NSOperation)에 대해 알아보겠습니다.

 

오늘도 시작은 공식문서를 통해 알아보겠습니다.

 

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

 

Apple Developer Documentation

 

developer.apple.com

 개요(OverView)만 간단히 살펴보면,

 

 Operation은 추상 클래스라 직접 사용할 순 없지만 Operation을 수행하는데 필요한 중요한 로직을 포함하고 있다고 합니다. 또한 start() 함수를 통해 직접적으로 사용할 순 있지만, 일반적으로 OperationQueue를 통해 실행합니다.

 

 역시나 문서만 보고서는 어떤 개념인지 알기가 어렵네요...

 

 우선 Operation이 어떤 기능을 수행하는 것인지 알아봐야겠습니다.

 제가 예전에 GCD(Dispatch Queue)에 대해 포스트한 글이 있는데, 보통 GCD와 Operation을 비교하면서 설명을 하니 참고하시면 좋을 거 같습니다.

 

https://tong94.tistory.com/13

 

[iOS] GCD(Grand Central Dispatch)란?

안녕하세요. 오늘은 iOS에서 중요한 개념 중 하나인 GCD에 대해 알아보겠습니다. GCD에 대해서 알려면 우선 Disapatch Queue에 대해 알아야하는데요. 우선은 역시 공식문서를 살펴보겠습니다. https://deve

tong94.tistory.com

 

 우선 GCD에서는 보통 큐를 생성혹은 지정하고 {} 블록 내부에 원하는 코드를 실행하면 생성한 큐의 속성에 따라 비동기 혹은 우선 순위를 정해 특정 작업을 수행할 수 있었습니다.

 

 Operation은 GCD에 기반해서 여러가지 기능을 추가한 추상 클래스라고 생각하시면 될 거 같습니다.

 Operation이 제공해주는 기능은 많지만 그 중에서 GCD와 비교해서 특징되는 기능은 크게 2개라고 생각합니다:

 

  1. 데이터와 기능을 캡슐화했기 때문에 재사용이 가능하다.
  2. 해당 작업의 실행 상태(실행, 정지, 대기 등)를 알 수 있고 이를 통해 Operation들을 취소 혹은 순서를 지정이 가능하다.

 이런 특징들을 통해 얻을 수 있는 장점은 무엇이 있을까요?

 예를 들어 우리가 UITableView에 있는 셀들이 각각 url로 부터 이미지를 받아온다고 생각해보죠.

 

 일반적인 경우라면

if let data = try? Data(contentsOf: url){
  if let image = UIImage(data: data){
    self.image = image
  }
}

이런식으로 url 이미지를 받아와서 입력받도록 합니다.

 

하지만 실제로 이렇게 코드를 구현하면 UITableView가 상당히 느리거나 끊기는 현상을 보실 수 있습니다.

왜냐하면 셀에 이미지를 넣는 작업들이 동기적으로 실행되기 때문에 이미지들을 다 받기전에 다음 작업이 제한되기 때문이죠.

 

DispatchQueue.global().async {
  if let data = try? Data(contentsOf: url){
    if let image = UIImage(data: data){
      DispatchQueue.main.async {
        self.image = image
      }
    }
  }
}

 

따라서 부드러운 UITableView 사용을 위해서는 이미지를 불러오는 로직을 다른 큐에 비동기적으로 작업을 위임하고 image를 넣는 작업은 UI 작업이므로 다시 메인큐에 넣는 작업을 해주어야 합니다.

 

사실 이정도만 해도 일반적인 경우에는 충분히 사용가능합니다.

하지만 만약에 UITableView가 빠르게 스크롤 되는 경우에는 어떻게 될까요?

 

즉, 이미지를 다 받기전에 이미 cell이 넘어가서 재사용되는 거라면 굳이 이미지를 다운받는 작업을 계속 할 필요가 없겠죠?

그러므로 우리는 해당 상황이라면 진행중인 작업을 취소해야 합니다.

 

하지만 우리가 DispatchQueue를 사용해 바로 위에 선언한 코드에서는 해당 작업을 취소할 방법이 없죠.

이런 경우에 Operation과 OperationQueue를 통해 해결할 수 있습니다.

 

그럼 우선 오늘은 Operation을 사용한 예제까지만 같이 알아보고 다음에 좀 더 깊게 알아보죠.

(Operation이 제공하는 기능과 사용하는 방법이 너무 방대해서 계속 공부해야 할 거 같아요 ㅠ)

 

우선 Operation은 추상 클래스라서 그대로 사용할 수 없었죠?

새로운 클래스를 생성하고 Operation을 상속받아야겠죠

예를 들어 글자를 번역하는 Operation을 생성한다고 가정해보죠.

 

class TranslateOperation: Operation {
  var beforeTranslate: String?
  var afterTranslate: String?
  
  //Operation의 오버라이드 메소드
  override func main() {
    //어딘가 구현되어 있을 translate함수
    outputImage = translate(before: beforeTranslate)
  }
}

 

Operation을 상속받게 되면 기본적으로 main이라는 함수를 오버라이드해서 사용할 수 있습니다.

main은 Operation이 시작될 때 실행할 작업을 입력하게 됩니다.

 

실행은 다음과 같이 할 수 있습니다.

 

let trOp = TranslateOperation()
trOp.beforeTranslate = "사랑해요"

//일반적으로 OperationQueue에 넣어서 사용하지만 직접 실행하능(기본적으로 동기적으로 실행)
trOp.start()

print(trOp.afterTranslate)

 

오늘은 이렇게 Operation에 대해 간략하게 알아봤는데요.

최대한 간략하게 작성해보려 했는데, 저도 공부하면서 새로 배우는 개념이다 보니 부족한 점이 많은 글이였던 것 같습니다.

 

감사합니다.

반응형
Comments