iOS KingFisher 사용법

KingFisher 란?

iOS에서 이미지를 관리해주는 오픈소스이다.

image

가령 URL에서 이미지를 요청하여 가져오는 경우를 생각해보자 기존의 경우 아래의 코드와 같이 단순하게 UIImageView에 직접적으로 이미지를 올릴뿐 아무런 작업을 하지 않는다.

@IBOutlet weak var imageView: UIImageView!
...
guard let url = URL(string: imageUrl) else { return nil }
guard let data = try? Data(contentsOf: url) else { return nil }
let image = UIImage(data: data)
imageView.image = image

하지만 만약 많은 양의 이미지 데이터가 올 경우나 용량이 큰 이미지 파일등을 다루어야 할 경우 이는 앱 성능에 심각한 영향을 준다. 이에 따라 image Cache 등 상황에 효율적으로 대처하기 위해서 추가적인 작업이 필요하다. 마찬가지로 위의 코드에서 실제로 동작을 할려면 아래와 같이 코드를 수정 해주어야 한다.

DispatchQueue.global().async {
		guard let url = URL(string: imageUrl) else { return nil }
		guard let data = try? Data(contentsOf: url) else { return nil }
		let image = UIImage(data: data)
  	DispatchQueue.main.async {
    		self.imageView.image = image
    }
}

또한 위처럼 URL로 된 이미지를 요청 하는 부분은 비동기적으로 동작이 되어야한다.(이미지를 다운받는데 다른 작업이 다 멈추고 이미지 다운을 기다릴수는 없다! ). 그리고 UI에 변화를 주는 작업은 main 스레드에서 동작하도록 설계해야한다.

Kingfisher는 아래와 같은 기능을 제공하여 위의 문제점을 해결하고 조금더 간결하고 직관적인 image 처리를 할 수 있다.

  1. 비동기 이미지 다운로드 및 Caching
  2. URLSession 기반 네트워킹이 이루어진다. 그리고 기본 이미지 processor 및 filter가 제공된다.
  3. 메모리와 디스크를 위한 다중 계층 캐시 제공
  4. 성능을 향상 시키기 위해서 다운로드 작업을 취소하거나 처리할 수 있는 작업이 있다
  5. UIImageView, NSImageUIButton 에 대한 확장으로 URL에서 이미지를 직접 설정가능하다
  6. 필요에 따라 downLoader, Caching 시스템을 별도로 사용한다.
  7. 이미지를 설정 시 내장된 애니메이션을 사용가능하다.
  8. 확장 가능한 이미지 처리(아래에 추가적으로 설명하겠다.) 및 GIF 이미지 형식 지원

Kingfisher를 이용한 이미지 로드 구현

guard let url = URL(string: imageURLString) else { return } 
// 이미지 로딩(비동기, 캐싱기능 포함)
let processor = RoundCornerImageProcessor(cornerRadius: 80)
// 이미지 변형 프로세서 설정(모서리 부분 동그랗게 )       
imageView.kf.setImage(with: url, options: [.processor(processor)])
// 기본 : imageView.kf.setImage(with: url)

위와 같이 UIImageVIew에서 kf로 접근하여 kingfisher를 사용할 수 있다. 그리고 다양하게 효과들을 위와 같이 processor를 통해 할 수있다.

  • Processor를 통한 이미지 확장 기능
// 둥근 모서리 효과
let processor = RoundCornerImageProcessor(cornerRadius: 20)

// 이미지 사이즈 재설정
let processor = ResizingImageProcessor(targetSizeL CGSize(width: 100, height: 100))

// 이미지 흐림(Blur) 정도 
let processor = BlurImageProcessor(blurRadius: 5.0)

// Overlay 색상과 fraction(Overlay가 차지하는 비율) 설정
let processor = OverlayImageProcessor(overlay: .red, fraction: 0.7)

// Color Tint 설정
let processor = TintImageProcessor(tint: .blue)

// 인접(Adjust) 색상
let processor = ColorControlProcessor(brightness: 1.0, contrast: 0.7, saturation: 1)

// 흑백 설정
let processor = BlackWhiteProcessor()

중복된 processor 적용을 위해 >> 로 여러개를 나열할 수 있다.

  • GIF 지원
let imageView = AnimatedImageView()

image

Kingfisher의 장점: High-resolution Image 처리
let url = URL(string: "https://example.com/high_resolution_image.png")
let processor = DownsamplingImageProcessor(size: imageView.size)
             >> RoundCornerImageProcessor(cornerRadius: 20)
imageView.kf.indicatorType = .activity
imageView.kf.setImage(
    with: url,
    placeholder: UIImage(named: "placeholderImage"),
    options: [
        .processor(processor),
        .scaleFactor(UIScreen.main.scale),
        .transition(.fade(1)),
        .cacheOriginalImage
    ])
{
    result in
    switch result {
    case .success(let value):
        print("Task done for: \(value.source.url?.absoluteString ?? "")")
    case .failure(let error):
        print("Job failed: \(error.localizedDescription)")
    }
}
kingfisher의 장점: 이미지 캐싱

kingfisher의 큰 장점 중 하나는 이미지를 캐싱하여 재접근 할 시에 캐시의 장점을 사용하여 이미지 로딩 시간을 다량으로 줄여준다. 기본적인 단계는 아래와 같다

  1. imageView.kf.setImage
  2. KingfisherManager.shared.retrieveImage
  3. tryToRetrieveImageFromCache
  4. ImageCache.default.retrieveImage
  5. 이미지 가져오는 작업
    1. memoryCache에서 저장된 이미지 캐시 가져오기
    2. 1에서 찾지 못한 경우 디스크에서 찾는다.
    3. memoryCache 및 디스크에 원본 저장
  6. imageView.image = image

캐시를 사용하여 memoryCache에 저장되어있는 이미지 캐시를 우선적으로 탐색 한 다음에 찾은 경우에 빠르게 가져오고 없는 경우에는 디스크에서 가져온다. 마찬가지로 캐시에 저장되는 기한등을 설정할 수 있는데 그 옵션 값은 아래와 같다.

ImageCache 클래스에 존재하는 프로퍼티로서 의미와 메모리 관리 기법은 다음과 같다.

  • maxCachePeriodInSecond : 기본값 1주일
  • maxMemoryCost (기본값 0. no limit) SDWebImage 와 마찬가지로 역시 NSCache 의 값을 조절한다.(캐시 임계값 설정)
  • maxDiskCacheSize (기본값 0. no limit)
  • cacheMemoryOnly, onlyFromCache, forceRefresh, fromMemoryCacheOrRefresh
  • clearMemoryCache : memory warning notification 을 받았을때 호출한다 호출하면 memoryCache를 다지워준다.
  • clearExpiredDiskCache: 앱이 꺼지거나 백그라운드 진입시에 호출되는 함수이다. expire 된 것들을 지운다음, 여전히 디스크 용량을 많이 차지하고 있으면 contentAccessData로 정렬하여 지운다.

추가) KingFisher에서 URL에 한국어가 포함 되어있을 때 대처

  • addingPercentEncoding() 메서드 사용
// 원하는 imageURL을 addingPercentEncoding을 통해 바꿔준다.
let url = imageURL?.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)

imageView.kf.setImage(with: URL(string: url), placeholder: defaultImg, options: [.transition(ImageTransition.fade(0.5))])

Reference





© 2020. by Gaki

Powered by gaki