비동기 UIImage 리사이징: GCD나 OperationQueue를 사용하여 이미지 리사이징을 비동기적으로 처리하는 기술.

작성일 :

Swift에서 비동기 UIImage 리사이징

이미지를 효과적으로 처리하는 것은 많은 iOS 애플리케이션에서 중요한 요구 사항입니다. 대용량 이미지를 처리하는 동안 메인 스레드의 부하를 줄이고 사용자 경험을 향상시키기 위해 비동기적으로 작업을 수행하는 것이 필수적입니다. Swift에서는 GCD(Grand Central Dispatch)와 OperationQueue를 사용하여 이러한 비동기 작업을 쉽게 구현할 수 있습니다. 이 글에서는 GCD와 OperationQueue를 활용하여 비동기적으로 UIImage를 리사이징하는 방법을 살펴보겠습니다.

GCD를 사용한 비동기 이미지 리사이징

GCD는 비동기 작업을 효율적으로 처리할 수 있는 강력한 도구입니다. GCD를 사용하면 작업을 전역 큐 또는 사용자 정의 큐에서 비동기적으로 실행할 수 있습니다. 아래는 GCD를 사용하여 이미지를 비동기적으로 리사이징하는 예제입니다.

swift
import UIKit

func resizeImage(image: UIImage, targetSize: CGSize, completion: @escaping (UIImage?) -> Void) {
    DispatchQueue.global(qos: .userInitiated).async {
        let size = image.size
        let widthRatio  = targetSize.width  / size.width
        let heightRatio = targetSize.height / size.height
        let newSize = widthRatio > heightRatio
            ? CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
            : CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
        let rect = CGRect(origin: .zero, size: newSize)
        UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
        image.draw(in: rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        DispatchQueue.main.async {
            completion(newImage)
        }
    }
}

위 코드에서 resizeImage 함수는 비동기로 이미지를 리사이징합니다. DispatchQueue.global을 사용하여 작업을 백그라운드 큐에서 실행하고, 완료된 후 메인 큐에서 결과를 반환합니다.

OperationQueue를 사용한 비동기 이미지 리사이징

OperationQueue는 GCD보다 더 고급의 작업 관리 기능을 제공합니다. 작업의 우선 순위를 설정하거나 작업 간의 종속성을 관리하는 데 유용합니다. 다음 예제는 OperationQueue를 사용하여 이미지를 비동기적으로 리사이징하는 방법을 보여줍니다.

swift
import UIKit

class ImageResizeOperation: Operation {
    let inputImage: UIImage
    let targetSize: CGSize
    var outputImage: UIImage?

    init(image: UIImage, targetSize: CGSize) {
        self.inputImage = image
        self.targetSize = targetSize
    }

    override func main() {
        if isCancelled { return }
        let size = inputImage.size
        let widthRatio  = targetSize.width  / size.width
        let heightRatio = targetSize.height / size.height
        let newSize = widthRatio > heightRatio
            ? CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
            : CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
        let rect = CGRect(origin: .zero, size: newSize)
        UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
        inputImage.draw(in: rect)
        outputImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    }
}

func asyncResizeImage(image: UIImage, targetSize: CGSize, completion: @escaping (UIImage?) -> Void) {
    let operationQueue = OperationQueue()
    let resizeOperation = ImageResizeOperation(image: image, targetSize: targetSize)
    resizeOperation.completionBlock = {
        DispatchQueue.main.async {
            completion(resizeOperation.outputImage)
        }
    }
    operationQueue.addOperation(resizeOperation)
}

ImageResizeOperation 클래스는 Operation을 상속받아 비동기적으로 이미지를 리사이징할 수 있는 커스텀 작업을 정의합니다. asyncResizeImage 함수는 이 작업을 OperationQueue에 추가하고 작업이 완료되면 메인 큐에서 결과를 처리합니다.

결론

Swift에서 GCD와 OperationQueue를 사용하여 비동기적으로 UIImage를 리사이징하는 방법에 대해 살펴보았습니다. GCD는 간단한 비동기 작업에 적합하며, OperationQueue는 더 복잡한 작업 관리를 필요로 할 때 유리합니다. 이 두 가지 방식을 잘 활용하면 애플리케이션의 성능을 최적화하고 사용자 경험을 향상시킬 수 있습니다.