Operation 문제 #2
Replies: 4 comments 1 reply
-
Operation의 4가지 상태를 설명하고, 각 상태의 특징과 전환 조건을 자세히 설명하세요.
Operation의 주요 특징 3가지를 설명하고, 각 특징이 동시성 프로그래밍에 미치는 영향을 논하세요.
OperationQueue의 maxConcurrentOperationCount 속성의 의미와 동시성 관리에 대해 설명하세요.
Operation을 상속받아 Custom Operation을 구현할 때 고려해야 할 주요 메서드와 프로퍼티는 무엇인가요?
Operation과 GCD(Grand Central Dispatch)의 주요 차이점 3가지를 설명하세요.
Operation을 이용해서 아래와 동작하는 코드를 작성하시오.
import UIKit
class AsyncOperation: Operation {
enum State: String {
case ready, executing, finished
fileprivate var keyPath: String {
return "is\(rawValue.capitalized)"
}
}
var state = State.ready {
willSet {
willChangeValue(forKey: newValue.keyPath)
willChangeValue(forKey: state.keyPath)
}
didSet {
didChangeValue(forKey: oldValue.keyPath)
didChangeValue(forKey: state.keyPath)
}
}
}
extension AsyncOperation {
override var isReady: Bool {
super.isReady && state == .ready
}
override var isExecuting: Bool {
state == .executing
}
override var isFinished: Bool {
state == .finished
}
override var isAsynchronous: Bool {
true
}
override func start() {
if isCancelled {
state = .finished
return
}
main()
state = .executing
}
override func cancel() {
super.cancel()
state = .finished
}
}
protocol ImageProvider {
var image: UIImage? { get }
}
final class DownloadOperation: AsyncOperation {
var inputUrl: String?
var outputImage: UIImage?
override func main() {
guard let inputUrl, let url = URL(string: inputUrl),
isCancelled == false else {
return
}
URLSession.shared.dataTask(with: url) { data, _, error in
defer {
self.state = .finished
}
if let error {
return
}
guard let data,
let image = UIImage(data: data) else {
return
}
self.outputImage = image
}.resume()
}
}
extension DownloadOperation: ImageProvider {
var image: UIImage? { outputImage }
}
extension UIImage {
func convertToGrayScale() -> UIImage {
let context = CIContext(options: nil)
guard let currentFilter = CIFilter(name: "CIPhotoEffectMono"),
let ciImage = CIImage(image: self) else { return self }
currentFilter.setValue(ciImage, forKey: kCIInputImageKey)
guard let output = currentFilter.outputImage,
let cgImage = context.createCGImage(output, from: output.extent) else { return self }
return UIImage(cgImage: cgImage)
}
}
class GrayScaleOperation: Operation {
var inputImage: UIImage?
var outputImage: UIImage?
override func main() {
guard inputImage == .none,
let dependencyImageProvider = dependencies.filter({ $0 is ImageProvider }).first as? ImageProvider else {
return
}
inputImage = dependencyImageProvider.image
outputImage = inputImage?.convertToGrayScale()
}
}
let urlString = "https://github.com/yavuzceliker/sample-images/blob/main/images/image-1.jpg?raw=true"
let downloadOperation = DownloadOperation()
downloadOperation.inputUrl = urlString
let grayScaleOperation = GrayScaleOperation()
grayScaleOperation.addDependency(downloadOperation)
let imageQueue = OperationQueue()
imageQueue.addOperations(
[downloadOperation, grayScaleOperation],
waitUntilFinished: true
)
downloadOperation.outputImage
grayScaleOperation.outputImage |
Beta Was this translation helpful? Give feedback.
-
Operation의 4가지 상태를 설명하고, 각 상태의 특징과 전환 조건을 자세히 설명하세요.
Operation의 주요 특징 3가지를 설명하고, 각 특징이 동시성 프로그래밍에 미치는 영향을 논하세요.
OperationQueue의 maxConcurrentOperationCount 속성의 의미와 동시성 관리에 대해 설명하세요.오퍼레이션 큐가 몇개의 쓰레드에 작업을 배치할지 지정할 수 있는 프로퍼티. defualt는 -1로, 따로 카운트를 설정해주지 않으면 OS 에서 알아서 결정하지만, 2,3 등의 숫자를 정해주면 지정된 수만큼의 쓰레드 내에서 동작하도록 한다. 1일 경우에 메인쓰레드에서만 사용하도록 한다. Operation을 상속받아 Custom Operation을 구현할 때 고려해야 할 주요 메서드와 프로퍼티는 무엇인가요?input, output, main() Operation과 GCD(Grand Central Dispatch)의 주요 차이점 3가지를 설명하세요.
Operation을 이용해서 아래와 동작하는 코드를 작성하시오.
class MyOperation: Operation {
var inputImageUrl: URL
var outputUIImage: UIImage?
init(url: URL) {
self.inputImageUrl = url
}
override func main() {
if isCancelled {
return
}
guard let data = try? Data(contentsOf: inputImageUrl) else {
return
}
if isCancelled {
return
}
outputUIImage = UIImage(data: data)
}
}let operationQueue = OperationQueue()
let imageUrl = URL(string: "https:... .jpg")!
let downloadOperation = MyOperation(url: imageUrl)
downloadOperation.completionBlock = {
let downloadedImage = downloadOperation.downloadedImage
print("downloadedImage 를 흑백으로 전환하면 됩니다")
}
operationQueue.addOperation(downloadOperation) |
Beta Was this translation helpful? Give feedback.
-
// 호출부 ==============================
let downloadOperation = ImageDownloadOperation(url: url)
let grayscaleOperation = ImageGrayscaleFilterOperation(imageProvider: downloadOperation)
// 의존성 추가
grayscaleOperation.addDependency(downloadOperation)
let operationQueue = OperationQueue()
operationQueue.addOperations([downloadOperation, grayscaleOperation], waitUntilFinished: false)
// =======================================// 이미지 전달을 위한 프로토콜
protocol ImageDataProvider {
var image: UIImage? { get }
}
// 추상 비동기 오퍼레이션의 정의==============================
class AsyncOperation: Operation {
// Enum 생성
enum State: String {
case ready, executing, finished
// KVO notifications을 위한 keyPath설정
fileprivate var keyPath: String {
return "is\(rawValue.capitalized)"
} // isReady/isExecuting/isFinished
}
// 직접 관리하기 위한 상태 변수 생성
var state = State.ready {
willSet {
willChangeValue(forKey: newValue.keyPath)
willChangeValue(forKey: state.keyPath)
}
didSet {
didChangeValue(forKey: oldValue.keyPath)
didChangeValue(forKey: state.keyPath)
}
}
}
extension AsyncOperation {
// 상태속성은 모두 read-only
override var isReady: Bool {
return super.isReady && state == .ready
}
override var isExecuting: Bool {
return state == .executing
}
override var isFinished: Bool {
return state == .finished
}
override var isAsynchronous: Bool { // 무조건 true로 리턴
return true
}
override func start() {
if isCancelled {
state = .finished
return
}
main()
state = .executing
}
override func cancel() {
super.cancel()
state = .finished
}
}// 이미지 다운로드 오퍼레이션
class ImageDownloadOperation: AsyncOperation, ImageDataProvider {
let url: URL
private(set) var image: UIImage? // 프로토콜의 image -> 얘를 통해 전달
init(url: URL) {
self.url = url
}
override func main() {
if isCancelled {
finish()
return
}
let task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
guard let self = self else { return }
defer { self.finish() } // 작업 완료 후 상태 변경
if self.isCancelled { return }
guard let data = data, error == nil else { return }
self.image = UIImage(data: data)
}
task.resume()
}
}
// 흑백 변환 오퍼레이션
class ImageGrayscaleFilterOperation: AsyncOperation {
private let imageProvider: ImageDataProvider
private(set) var outputImage: UIImage?
init(imageProvider: ImageDataProvider) {
self.imageProvider = imageProvider
}
override func main() {
if isCancelled {
return
}
guard let inputImage = imageProvider.image,
let ciImage = CIImage(image: inputImage) else {
return
}
let filter = CIFilter(name: "CIPhotoEffectMono")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
if let outputCIImage = filter?.outputImage,
let cgImage = CIContext().createCGImage(outputCIImage, from: outputCIImage.extent) {
outputImage = UIImage(cgImage: cgImage)
}
}
} |
Beta Was this translation helpful? Give feedback.
-
1. Operation의 4가지 상태와 특징, 전환 조건Operation은 내부적으로 4가지 상태를 가지며, 상태 전환은 OperationQueue나 수동으로 관리할 수 있다. isReady (준비 상태)
isExecuting (실행 상태)
isFinished (완료 상태)
isCancelled (취소 상태)
2. Operation의 주요 특징 3가지와 동시성 프로그래밍 영향1. 의존성(Dependency) 관리 가능
2. 취소 가능 (cancel)
3. 동기/비동기 작업 처리 가능
3. OperationQueue의 maxConcurrentOperationCount 속성• maxConcurrentOperationCount는 한 번에 실행할 수 있는 최대 Operation 개수를 의미 • 기본값은 -1이며, 이는 시스템이 적절하게 관리하도록 설정됨 (CPU 코어 수에 따라 자동 조정) • 1로 설정하면 직렬 실행(Serial Execution) 큐처럼 동작함 • 2 이상으로 설정하면 여러 작업을 병렬로 실행할 수 있음 • 이를 통해 CPU 사용량을 조절하고, 과도한 동시 실행을 방지하여 리소스를 효율적으로 관리 가능 4. Operation을 상속받아 Custom Operation을 구현할 때 고려해야 할 주요 메서드와 프로퍼티
• 실행할 작업을 정의하는 메서드 • main() 내부에서 isCancelled 체크 후 조기 종료를 고려해야 함
• isExecuting, isFinished를 수동으로 관리해야 함 • main() 대신 직접 실행 로직을 작성해야 함
• 기본적으로 false이므로, 비동기 작업을 하려면 true로 설정해야 함
• 취소 요청을 확인하고 실행 중인 작업을 중단할 수 있도록 구현해야 함
• addDependency(_:)를 활용하여 실행 순서를 조정 가능 5. Operation과 GCD(Grand Central Dispatch)의 주요 차이점 3가지
6. Operation을 이용한 이미지 다운로드 및 흑백 변환 코드import UIKit
// MARK: - 1. 이미지 다운로드 작업
class ImageDownloadOperation: Operation {
private let imageURL: URL
var downloadedImage: UIImage?
init(imageURL: URL) {
self.imageURL = imageURL
}
override func main() {
if isCancelled { return }
guard let data = try? Data(contentsOf: imageURL) else { return }
if isCancelled { return }
downloadedImage = UIImage(data: data)
}
}// MARK: - 2. 흑백 변환 작업
class GrayscaleFilterOperation: Operation {
var inputImage: UIImage?
var outputImage: UIImage?
init(image: UIImage?) {
self.inputImage = image
}
override func main() {
if isCancelled { return }
guard let inputImage = inputImage else { return }
let filter = CIFilter(name: "CIPhotoEffectMono")
let ciImage = CIImage(image: inputImage)
filter?.setValue(ciImage, forKey: kCIInputImageKey)
if isCancelled { return }
if let outputCIImage = filter?.outputImage,
let cgImage = CIContext().createCGImage(outputCIImage, from: outputCIImage.extent {
outputImage = UIImage(cgImage: cgImage)
}
}
}// MARK: - 실행 코드
let imageURL = URL(string: "https://example.com/sample.jpg")!
let downloadOp = ImageDownloadOperation(imageURL: imageURL)
let filterOp = GrayscaleFilterOperation(image: nil)
// downloadOp가 끝난 후 filterOp가 실행되도록 설정
filterOp.addDependency(downloadOp)
let operationQueue = OperationQueue()
operationQueue.addOperations([downloadOp, filterOp], waitUntilFinished: true)
// 변환된 이미지 출력
if let finalImage = filterOp.outputImage {
print("흑백 이미지 변환 완료")
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Operation의 4가지 상태를 설명하고, 각 상태의 특징과 전환 조건을 자세히 설명하세요.
Operation의 주요 특징 3가지를 설명하고, 각 특징이 동시성 프로그래밍에 미치는 영향을 논하세요.
OperationQueue의 maxConcurrentOperationCount 속성의 의미와 동시성 관리에 대해 설명하세요.
Operation을 상속받아 Custom Operation을 구현할 때 고려해야 할 주요 메서드와 프로퍼티는 무엇인가요?
Operation과 GCD(Grand Central Dispatch)의 주요 차이점 3가지를 설명하세요.
Operation을 이용해서 아래와 동작하는 코드를 작성하시오.
Beta Was this translation helpful? Give feedback.
All reactions