KingFisher 심화 *DownSampling*

김재형·2024년 4월 24일
0
post-custom-banner

KingFisher 를 연구해 보자

작업중 동료분의 질문을 받던중 나도 모르던 정보를 알게 되었고 그것들을
정리 하기 위한 시간을 가져 보려고 합니다. 그중의 다운 샘플링도 알게되어 같이 정리해 볼께요

KingfisherManager.shared.retrieveImage(with: URL(string: imageUrl)!, options: [
            .processor(processor),
            .requestModifier(KingFisherNet()),
            .scaleFactor(scale),
            .cacheOriginalImage
        ]) { imageResult in
            switch imageResult {
            case .success(let result):
                self.image = result.image
            case .failure(let error):
                // print(error)
                break
            }
        }

processor 가 뭔데

“구글링 답변” : **컴퓨팅 및 컴퓨터 과학에서 외부 데이터 소스(일반적으로 메모리 또는 기타 데이터 스트림)에서 작업을 수행하는 전기 부품(디지털 회로)

흠 그래서 킹피셔에서 말하는건?
’이미지 처리를 위해 사용되는 하나의 구성 요소’**

종류

  • DownsamplingImageProcessor
  • BlurImageProcessor
  • ResizingImageProcessor
  • BorderImageProcessor 기타 등등

DownsamplingImageProcessor

일단 다운 샘플링이 무엇인지 알아야 겠죠?
이미지의 해상도를 실제 표시될 크기로 줄이는 과정 을 말합니다
즉 이미지 리사이징 개념과 비슷하죠!

let processor = DownsamplingImageProcessor(size: CGSize(width: 300, height: 300))
imageView.kf.setImage(
    with: url,
    options: [
        .processor(processor),
        .scaleFactor(UIScreen.main.scale)
    ]
)

이미지 리사이징이랑 무슨 차이인데?

가장 명확한 차이점은
이미지가 디코딩되는 단계에서 수행
VS
이미지가 이미 디코딩되어 메모리에 로드된 상태에서 수행

즉 이미지가 이미 로드 됬는데 리사이징을 하는 것인가?
아니면 이미지를 그리기 전에 걸러서 그리는 것인가 라는 개념입니다.

특정상황에 따라 선택하면 될 것 같은게
만약 사용자의 이미지를 저장할때는 그건 다운샘플링이 아니라 리사이징을 해야하는 것이고
네트워크를 통해 혹은 다른 루트에 의해 받아져야 할때 는 다운 샘플링 으로 처리해야 할 것 같습니다.


requestModifier

킹피셔도 결국엔 네트워크를 통해 이미지를 불러오는 라이브러리 이다 보니
중간에 헤더나, 토큰이나, 특정 URL 변경등 의 상황에 대처할수 있게 만들어준 기능이죠.

다음은 위와 같은 상황을 담아놓은 예시 코드입니다.

import Kingfisher
import Foundation

final class KingFisherNet: ImageDownloadRequestModifier {
    
    private 
    let baseURL = APIKey.baseURL.rawValue // 베이스 URL
    
    private
    let version = "/v1/" // 버전정보
    
    func modified(for request: URLRequest) -> URLRequest? {
        
        // 토큰을 추가 하기 위한 과정
        guard let accessTokken = TokenStorage.shared.accessToken else {
            return nil
        }
        // URLComponts 조립과정 시작
        var components = URLComponents(string: baseURL) // 1. 베이스 URL 
        components?.path = version + (request.url?.path() ?? "") // 패스 추가
        
        guard let url = components?.url else { // URL 변환 
            return nil
        }
        var urlRequest = URLRequest(url: url) // URL Request 변환 
        
        // 헤더 추가
        urlRequest.addValue(accessTokken, forHTTPHeaderField: NetHTTPHeader.authorization.rawValue)
        // 키 추가
        urlRequest.addValue(APIKey.sesacKey.rawValue, forHTTPHeaderField: NetHTTPHeader.sesacKey.rawValue)
        
        return urlRequest
    }
}

retrieveImage ? 이건 뭐야

URL을 통해 이미지를 검색 처리하는 작업을 수행하는데 이미지를 다운로드 하기전에
이미 캐시된 이미지가 있다면 캐시 이미지를 사용합니다.

아니또 캐시는 어떻게 하는거에요

종류는 대표적인 것으로 준비해 왔습니다.

  • .forceRefresh : 나 캐쉬 안해
  • .onlyFromCache : 캐쉬 한 것만 쓸래
  • .cacheOrigialImage

cacheOrigialImage

이미지 다운(통신) 을 성공적으로 처리하였다면 원본 데이터를 킹피셔 캐시 시스템에
저장합니다. 즉 같은 URL이미지를 재 요청시엔 이미 다운로드된 데이터를 로드할수 있어요!

imageView.kf.setImage(
    with: url,
    placeholder: UIImage(named: "placeholder"),
    options: [
        .processor(DownsamplingImageProcessor(size: imageView.bounds.size)),
        .scaleFactor(UIScreen.main.scale),
        .cacheOriginalImage
    ]
)

Cash Types

public enum CacheType {
    /// The image is not cached yet when retrieving it.
    /// 이미지를 검색할 때 이미지가 아직 캐시되지 않았습니다.
    case none
    /// The image is cached in memory.
    /// 이미지가 메모리에 캐시되어 있습니다.
    case memory
    /// The image is cached in disk.
    /// 이미지가 디스크에 캐시됩니다.
    case disk
    
    /// Whether the cache type represents the image is already cached or not.
    /// 캐시 유형이 이미지가 이미 캐시되어 있는지 여부를 나타냅니다.
    public var cached: Bool {
        switch self {
        case .memory, .disk: return true
        case .none: return false
        }
    }
} 

++ /// 디스크에 저장되는 캐시의 기간은 7일
open var maxCachePeriodInSecond: TimeInterval = 60 * 60 * 24 * 7 //Cache exists for 1 week

+++ // +++ 캐시 사이즈나 개수를 지정 할수 있습니다.
// Limit memory cache size to 300 MB.
cache.memoryStorage.config.totalCostLimit = 300 * 1024 * 1024

// Limit memory cache to hold 150 images at most. 
cache.memoryStorage.config.countLimit = 150

// Limit disk cache size to 1 GB.
cache.diskStorage.config.sizeLimit =  = 1000 * 1024 * 1024

// Memory image expires after 10 minutes.
cache.memoryStorage.config.expiration = .seconds(600)

// Disk image never expires.
cache.diskStorage.config.expiration = .never

이말인 즉 메모리에 캐시되어 있을건지 디스크에 캐시해 놓을건지 인데
추가적으로 디스크에 저장되는 캐시의 기간은 7일이다.

  1. none
    • 이미지가 아직 어떠한 캐시에도 저장되지 않았음을 의미합니다.
      이미지가 처음 요청되었을 때, 캐시에서 해당 이미지를 찾을 수 없음을 말하며,
      네트워크를 통해 이미지를 다운로드해야 함을 말합니다!
  2. memory
    • 이미지가 메모리 캐시에 저장되어 있음을 나타냅니다
      메모리 캐시는 빠른 속도를 제공하지만, 앱이 종료되면 사라지는 휘발성 캐시입니다.
      메모리에 캐시된 이미지는 앱이 실행 중인 동안 빠르게 접근할 수 있으며,
      반복적인 이미지 로딩에 유용하게 사용됩니다.
  3. disk
    • 이미지가 디스크 캐시에 저장되어 있음을 의미해요
      디스크 캐시는 비교적 느린 속도를 가지지만, 앱이 종료된 후에도 지속됩니다.
      이를 통해 앱을 재시작하거나 장기간에 걸쳐 이미지를 유지할 필요가 있을 때 유용하게 사용됩니다!
imageView.kf.setImage(
    with: url,
    options: [
        .processor(DownsamplingImageProcessor(size: imageView.bounds.size)),
        .scaleFactor(UIScreen.main.scale),
        .cacheOriginalImage,
        .memoryCacheExpiration(.days(1)), // 메모리 캐시 유지 기간을 1일로 설정
        .diskCacheExpiration(.never) // 디스크 캐시는 만료되지 않도록 설정
    ]
)
profile
IOS 개발자 새싹이
post-custom-banner

0개의 댓글