Operation

Groot·2022년 10월 10일
0

TIL

목록 보기
82/148
post-thumbnail

TIL

🌱 난 오늘 무엇을 공부했을까?

📌 Operation

  • 단일 작업과 관련된 코드 및 데이터를 나타내는 추상 클래스입니다.

📍 Declaration

class Operation : NSObject

📍 Overview

  • Operation 클래스는 추상 클래스이기 때문에 직접 사용하지 않고 대신 서브클래스를 사용하거나 시스템 정의 서브클래스(NSInvocationOperation 또는 BlockOperation) 중 하나를 사용하여 실제 작업을 수행합니다.
  • 추상적임에도 불구하고 Operation의 기본 구현에는 작업의 안전한 실행을 조정하는 중요한 논리가 포함되어 있습니다.
  • 이 기본 제공 논리가 있으면 다른 시스템 개체와 올바르게 작동하도록 하는 데 필요한 글루 코드보다 작업의 실제 구현에 집중할 수 있습니다.

  • 작업 개체는 단일 샷 개체입니다. 즉, 작업을 한 번 실행하고 다시 실행하는 데 사용할 수 없습니다.
  • 일반적으로 작업을 작업 대기열(OperationQueue 클래스의 인스턴스)에 추가하여 작업을 실행합니다.
  • 작업 대기열은 보조 스레드에서 직접 작업을 실행하거나 libdispatch 라이브러리(Grand Central Dispatch라고도 함)를 사용하여 간접적으로 작업을 실행합니다.

  • 작업 대기열을 사용하지 않으려면 코드에서 직접 start() 메서드를 호출하여 작업을 직접 실행할 수 있습니다.
  • 준비 상태가 아닌 작업을 시작하면 예외가 트리거되기 때문에 작업을 수동으로 실행하면 코드에 더 많은 부담이 가해집니다. isReady 속성은 작업의 준비 상태를 보고합니다.

📍 Operation Dependencies

  • 종속성은 특정 순서로 작업을 실행하는 편리한 방법입니다.
  • addDependency(_:) 및 removeDependency(_:) 메서드를 사용하여 작업에 대한 종속성을 추가 및 제거할 수 있습니다.
  • 기본적으로 종속성이 있는 작업 개체는 모든 종속 작업 개체의 실행이 완료될 때까지 준비된 것으로 간주되지 않습니다.
  • 그러나 마지막 종속 작업이 완료되면 작업 개체가 준비되어 실행할 수 있습니다.

  • NSOperation이 지원하는 종속성은 종속 작업이 성공적으로 완료되었는지 여부를 구분하지 않습니다.(즉, 작업을 취소하면 마찬가지로 완료된 것으로 표시됩니다.)
  • 종속 작업이 취소되었거나 작업을 성공적으로 완료하지 못한 경우 종속 작업을 계속해야 하는지 여부를 결정하는 것은 사용자의 몫입니다. 이를 위해 일부 추가 오류 추적 기능을 작업 개체에 통합해야 할 수 있습니다.

📍 KVO-Compliant Properties

  • NSOperation 클래스는 여러 속성에 대해 KVC(키-값 코딩) 및 KVO(키-값 관찰)를 준수합니다.

  • 필요에 따라 이러한 속성을 관찰하여 애플리케이션의 다른 부분을 제어할 수 있습니다. 속성을 관찰하려면 다음 키 경로를 사용하십시오.

    • isCancelled - read-only

    • isAsynchronous - read-only

    • isExecuting - read-only

    • isFinished - read-only

    • isReady - read-only

    • dependencies - read-only

    • queuePriority - readable and writable

    • completionBlock - readable and writable

  • 이러한 속성에 관찰자를 연결할 수는 있지만 Cocoa 바인딩을 사용하여 애플리케이션 사용자 인터페이스의 요소에 바인딩해서는 안 됩니다.

  • 사용자 인터페이스와 관련된 코드는 일반적으로 애플리케이션의 메인 스레드에서만 실행되어야 합니다.

  • 작업은 모든 스레드에서 실행할 수 있으므로 해당 작업과 관련된 KVO 알림은 모든 스레드에서 유사하게 발생할 수 있습니다.

  • 앞의 속성에 대한 사용자 지정 구현을 제공하는 경우 구현에서 KVCKVO 규정을 유지해야 합니다.

  • NSOperation 개체에 대한 추가 속성을 정의하는 경우 해당 속성도 KVC 및 KVO와 호환되도록 만드는 것이 좋습니다.

📍 Multicore Considerations

  • NSOperation 클래스는 그 자체로 멀티코어를 인식합니다. 따라서 개체에 대한 액세스를 동기화하기 위해 추가 잠금을 생성하지 않고 여러 스레드에서 NSOperation 개체의 메서드를 호출하는 것이 안전합니다.
  • 이 동작은 일반적으로 작업을 생성하고 모니터링하는 스레드와 별도의 스레드에서 실행되기 때문에 필요합니다.

  • NSOperation의 하위 클래스를 만들 때 재정의된 메서드가 여러 스레드에서 호출하기에 안전한지 확인해야 합니다.
  • 사용자 정의 데이터 접근자와 같은 사용자 정의 메소드를 서브클래스에서 구현하는 경우 해당 메소드가 스레드로부터 안전한지 확인해야 합니다.
  • 따라서 잠재적인 데이터 손상을 방지하려면 작업의 모든 데이터 변수에 대한 액세스를 동기화해야 합니다. 동기화에 대한 자세한 내용은 Threading Programming Guide를 참조하세요.

📍 Asynchronous Versus Synchronous Operations

  • 작업 개체를 대기열에 추가하는 대신 수동으로 실행하려는 경우 동기 또는 비동기 방식으로 실행되도록 작업을 설계할 수 있습니다.
  • 작업 개체는 기본적으로 동기식입니다.
  • 동기 작업에서 작업 개체는 작업을 실행할 별도의 스레드를 만들지 않습니다.
  • 코드에서 직접 동기 작업의 start() 메서드를 호출하면 작업이 현재 스레드에서 즉시 실행됩니다.
  • 이러한 객체의 start() 메서드가 호출자에게 제어를 반환할 때까지 작업 자체가 완료됩니다.

  • 비동기 작업의 start() 메서드를 호출하면 해당 작업이 완료되기 전에 해당 메서드가 반환될 수 있습니다.
  • 비동기 작업 개체는 별도의 스레드에서 작업을 예약합니다.
  • 작업은 새 스레드를 직접 시작하거나, 비동기 메서드를 호출하거나, 실행을 위해 디스패치 큐에 블록을 제출하여 이를 수행할 수 있습니다.
  • 제어가 호출자에게 반환될 때 작업이 계속 진행 중인지 여부는 실제로 중요하지 않으며 계속 진행 중일 수만 있습니다.

  • 항상 대기열을 사용하여 작업을 실행할 계획이라면 대기열을 동기식으로 정의하는 것이 더 간단합니다.
  • 그러나 작업을 수동으로 실행하는 경우 작업 개체를 비동기식으로 정의할 수 있습니다.
  • 비동기 작업을 정의하려면 작업의 진행 중인 상태를 모니터링하고 KVO 알림을 사용하여 해당 상태의 변경 사항을 보고해야 하기 때문에 더 많은 작업이 필요합니다.
  • 비동기 작업을 정의하는 것은 수동으로 실행된 작업이 호출 스레드를 차단하지 않도록 하려는 경우에 유용합니다.

  • 작업 대기열에 작업을 추가하면 대기열은 isAsynchronous 속성 값을 무시하고 항상 별도의 스레드에서 start() 메서드를 호출합니다.
  • 따라서 항상 작업을 작업 대기열에 추가하여 작업을 실행한다면 비동기식으로 만들 이유가 없습니다.

📍 Subclassing Notes

  • NSOperation 클래스는 작업의 실행 상태를 추적하는 기본 논리를 제공하지만 그렇지 않으면 실제 작업을 수행하기 위해 하위 클래스화되어야 합니다.
  • 서브클래스를 생성하는 방법은 작업이 동시에 실행되도록 설계되었는지 또는 동시에 실행되지 않도록 설계되었는지에 따라 다릅니다.

📍 Methods to Override

  • 동시 작업이 아닌 경우 일반적으로 한 가지 방법만 재정의합니다.
    • main()

  • 이 메서드에 주어진 작업을 수행하는 데 필요한 코드를 배치합니다. 물론 사용자 정의 클래스의 인스턴스를 더 쉽게 생성할 수 있도록 사용자 정의 초기화 메서드도 정의해야 합니다.
  • 작업의 데이터에 액세스하기 위해 getter 및 setter 메서드를 정의할 수도 있습니다.
  • 그러나 사용자 지정 getter 및 setter 메서드를 정의하는 경우 이러한 메서드가 여러 스레드에서 안전하게 호출될 수 있는지 확인해야 합니다.

  • 동시 작업을 생성하는 경우 최소한 다음 메서드와 속성을 재정의해야 합니다.
    • start()
    • isAsynchronous
    • isExecuting
    • isFinished
  • 동시 작업에서 start() 메서드는 비동기 방식으로 작업을 시작하는 역할을 합니다.
  • 스레드를 생성하든 비동기 함수를 호출하든 이 메서드에서 수행합니다.
  • 작업을 시작할 때 start() 메서드는 isExecuting 속성에 의해 보고된 대로 작업의 실행 상태도 업데이트해야 합니다.
  • isExecuting 키 경로에 대한 KVO 알림을 전송하여 이를 수행합니다.
  • 그러면 관심 있는 클라이언트가 작업이 현재 실행 중임을 알릴 수 있습니다.
  • 또한 isExecuting 속성은 스레드로부터 안전한 방식으로 상태를 제공해야 합니다.

  • 작업이 완료되거나 취소되면 동시 작업 개체는 작업의 최종 상태 변경을 표시하기 위해 isExecuting 및 isFinished 키 경로 모두에 대해 KVO 알림을 생성해야 합니다.
  • (취소의 경우 작업이 작업을 완전히 완료하지 않았더라도 isFinished 키 경로를 업데이트하는 것이 여전히 중요합니다. 대기열에 있는 작업은 대기열에서 제거되기 전에 완료되었음을 보고해야 합니다.)
  • KVO 알림을 생성하는 것 외에도 isExecuting 및 isFinished 속성 재정의는 작업 상태에 따라 정확한 값을 계속 보고해야 합니다.
    >**Important**
    >**start() 메서드에서 절대로 super를 호출해서는 안 됩니다**
    >동시 작업을 정의할 때 작업 시작 및 적절한 KVO 알림 생성을 포함하여 기본 start() 메서드가 제공하는 것과 동일한 동작을 스스로 제공해야 합니다.
    >또한 start() 메서드는 작업을 실제로 시작하기 전에 작업 자체가 취소되었는지 확인해야 합니다. 취소 의미에 대한 자세한 내용은 취소 명령에 응답을 참조하십시오.

  • 동시 작업의 경우에도 위에서 설명한 것 이외의 메서드를 재정의할 필요가 거의 없습니다.
  • 그러나 작업의 종속성 기능을 사용자 지정하는 경우 추가 메서드를 재정의하고 추가 KVO 알림을 제공해야 할 수 있습니다.
  • 종속성의 경우 isReady 키 경로에 대한 알림만 제공하면 됩니다.
  • 종속성 속성에는 종속 작업 목록이 포함되어 있으므로 해당 속성에 대한 변경 사항은 이미 기본 NSOperation 클래스에 의해 처리됩니다.

📍 Maintaining Operation Object States

  • 작업 개체는 실행하기에 안전한 시기를 결정하고 작업의 수명 주기를 통해 진행 상황을 외부 클라이언트에 알리기 위해 내부적으로 상태 정보를 유지합니다.
  • 사용자 지정 하위 클래스는 코드에서 작업이 올바르게 실행되도록 이 상태 정보를 유지 관리합니다.
  • 작업 상태와 관련된 주요 경로는 다음과 같습니다.

  • isReady
    • isReady 키 경로를 통해 클라이언트는 작업을 실행할 준비가 되었음을 알 수 있습니다.
    • isReady 속성에는 작업을 지금 실행할 준비가 되었을 때 true 값이 포함되어 있고 종속되어 있는 아직 완료되지 않은 작업이 있는 경우 false 값이 포함되어 있습니다.

    • 대부분의 경우 이 키 경로의 상태를 직접 관리할 필요가 없습니다.
    • 귀하의 작업 준비 상태가 종속 작업 이외의 요인에 의해 결정되는 경우, 그러나 프로그램의 일부 외부 조건과 같이 isReady 속성의 자체 구현을 제공하고 작업의 준비 상태를 직접 추적할 수 있습니다.
    • 외부 상태에서 허용하는 경우에만 작업 개체를 만드는 것이 더 간단합니다.

    • macOS 10.6 이상에서 하나 이상의 종속 작업이 완료될 때까지 기다리는 동안 작업을 취소하면, 그런 다음 이러한 종속성은 무시되고 이 속성의 값은 이제 실행할 준비가 되었음을 반영하도록 업데이트됩니다.
    • 이 동작은 작업 대기열에 취소된 작업을 대기열에서 더 빨리 플러시할 수 있는 기회를 제공합니다.
  • isExecuting
    • isExecuting 키 경로를 통해 클라이언트는 작업이 할당된 작업에서 활발하게 작동하는지 여부를 알 수 있습니다.
    • isExecuting 속성은 작업이 작업에서 작동 중이면 true 값을 보고하고 그렇지 않으면 false 값을 보고해야 합니다.

    • 작업 객체의 start() 메서드를 교체하는 경우 isExecuting 속성도 교체하고 작업의 실행 상태가 변경될 때 KVO 알림을 생성해야 합니다.
  • isFinished
    • isFinished 키 경로를 통해 클라이언트는 작업이 성공적으로 완료되었거나 취소되어 종료되고 있음을 알 수 있습니다.
    • isFinished 키 경로의 값이 true로 변경될 때까지 작업 개체는 종속성을 지우지 않습니다.
    • 마찬가지로 작업 대기열은 isFinished 속성에 true 값이 포함될 때까지 작업을 대기열에서 빼지 않습니다.
    • 따라서 작업을 완료된 것으로 표시하는 것은 대기열이 진행 중이거나 취소된 작업으로 백업되지 않도록 하는 데 중요합니다.

    • start() 메서드 또는 작업 객체를 교체하는 경우 isFinished 속성도 교체해야 하며 작업 실행이 완료되거나 취소될 때 KVO 알림을 생성해야 합니다.
  • isCancelled
    - isCancelled 키 경로는 클라이언트가 작업 취소가 요청되었음을 알려줍니다.
    - 취소 지원은 자발적이지만 권장되며 자체 코드에서 이 키 경로에 대한 KVO 알림을 보낼 필요가 없습니다.

📍 Responding to the Cancel Command

  • 대기열에 작업을 추가하면 작업이 손에서 벗어날 수 있습니다.
  • 대기열이 해당 작업의 일정을 인계받아 처리합니다.
  • 그러나 나중에 사용자가 진행 패널에서 취소 버튼을 눌렀거나 응용 프로그램을 종료했기 때문에 작업을 실행하지 않으려는 경우, 예를 들어 작업을 취소하여 CPU 시간을 불필요하게 소모하지 않도록 할 수 있습니다.
  • 작업 개체 자체의 cancel() 메서드를 호출하거나 OperationQueue 클래스의 cancelAllOperations() 메서드를 호출하여 이 작업을 수행합니다.

    macOS 10.6 이상에서 작업 대기열에 있고 완료되지 않은 종속 작업이 있는 작업에서 cancel() 메서드를 호출하면 해당 종속 작업은 이후에 무시됩니다.
    작업이 이미 취소되었기 때문에 이 동작을 사용하면 대기열이 작업의 start() 메서드를 호출하여 main() 메서드를 호출하지 않고 대기열에서 작업을 제거할 수 있습니다.
    대기열에 없는 작업에 대해 cancel() 메서드를 호출하면 작업이 즉시 취소된 것으로 표시됩니다.
    각 경우에 작업을 준비 또는 완료로 표시하면 적절한 KVO 알림이 생성됩니다.

  • 작성하는 모든 사용자 지정 코드에서 항상 취소 의미 체계를 지원해야 합니다.
  • 특히 주 작업 코드는 isCancelled 속성 값을 주기적으로 확인해야 합니다.
  • 속성이 값을 true로 보고하면 작업 개체가 최대한 빨리 정리되고 종료되어야 합니다.

  • 사용자 지정 start() 메서드를 구현하는 경우 해당 메서드는 취소에 대한 조기 확인을 포함하고 적절하게 작동해야 합니다.
  • 이러한 유형의 조기 취소를 처리하려면 사용자 지정 start() 메서드를 준비해야 합니다.
  • 작업이 취소되면 단순히 종료하는 것 외에도 취소된 작업을 적절한 최종 상태로 이동하는 것도 중요합니다.
  • 특히 isFinished 및 isExecuting 속성의 값을 직접 관리하는 경우(동시 작업을 구현하기 때문에) 그에 따라 해당 속성을 업데이트해야 합니다.
  • 특히 isFinished에서 반환된 값을 true로 변경하고 isExecuting에서 반환된 값을 false로 변경해야 합니다. 작업이 실행을 시작하기 전에 취소된 경우에도 이러한 변경을 수행해야 합니다.
profile
I Am Groot

0개의 댓글