본문 바로가기
Swift

[iOS] About Kingfisher

by dsungc 2024. 11. 27.

이번 게시글에서는 제가 자주 사용하는 라이브러리 Kingfisher의 기능들에 대해서 알아보고자 합니다.

 

그런데 저의 경우, 초반에 학습할 때 Kingfisher를 사용하는 명확한 이유에 대해서 알지 못한 채로 사용했었는데요..!

 

그래서 이번에는 Kingfisher를 사용하는 이유와, 이를 통해 얻을 수 있는 장점들을 정리하며 보다 명확한 사용 목적을 이해하고자 합니다.

이를 위해 먼저 이미지 캐시의 기본 개념과 여러 캐싱 방법들을 간단히 짚어보고, 이후 Kingfisher가 이러한 캐싱 전략을 어떻게 활용하고 있는지 살펴보겠습니다!

이미지 캐시?

이미지 캐시는 어플리케이션에서 이미지를 효율적으로 로드하고 표시하기 위해 이미지 데이터를 임시로 저장하는 기술입니다.

 

이미지 캐시의 필요성

- 빠른 로드 시간

- 네트워크 트래픽 절약

- 사용자 경험 개선

 

이미지 캐시 방법

1. 메모리 캐시

 

이미지 데이터를 메모리(RAM)에 저장하는 방법

 

장점

- 접근속도가 빠름

- 단기적으로 반복되는 이미지 요청에 적합

단점

- 메모리 용량이 제한적이고, 앱 종료 시 캐시 데이터 삭제

 

 

2. 디스크 캐시

 

이미지를 디스크(Storage)에 저장

 

장점

- 앱을 재시작해도 캐시 데이터 유지 

- 대량의 이미지 데이터 저장 가능단점

- 메모리 캐시보다 접근 속도가 느림

 

3. 메모리 + 디스크 캐시

 

메모리 캐시와 디스크 캐시를 조합하여 사용

 

장점

- 빠른 접근성과 지속성 

동작원리

- 메모리 캐시에서 이미지 검색    >> 만약 있다면 밑의 과정 진행 X

- 없으면 디스크 캐시에서 검색    >> 만약 있다면 밑의 과정 진행 X

- 없으면 네트워크 요청 후 저장

 

 

4. 네트워크 기반 캐싱 (CDN Cache)

 

클라이언트 단이 아닌, 서버(CDN)에 이미지를 캐싱

 

장점

- 전 세계 사용자를 대상으로 빠른 이미지 로드

- 서버 부하 감소

단점 

- 클라이언트가 캐시 직접 관리 불가

 

 

Kingfisher

Swift로 작성된 오픈소스 라이브러리로, 이미지 다운로드, 캐싱, 관리를 간단하고 효율적으로 처리

특히 메모리와 디스크 캐싱을 자동으로 관리하며, 이미지 로드 및 디코딩 성능을 최적화해 개발자의 작업 시간을 단축

 

Kingfisher의 주요 특징

 

1. 메모리 및 디스크 캐싱

- 이미지 데이터를 메모리와 디스크에 자동으로 캐싱

- 메모리에서 먼저 이미지 검색 ------ (없다면)> 디스크에서 검색 ------ (없다면)> 네트워크 요청을 통해 이미지 다운로드

 

let url = URL(string: "이미지 url 넣으면 됩니당")
imageView.kf.setImage(with: url)

 

 

2. 다운샘플링

- 이미지 데이터를 메모리와 디스크에 자동으로 캐싱

- 메모리에서 먼저 이미지 검색 ------ (없다면)> 디스크에서 검색 ------ (없다면)> 네트워크 요청을 통해 이미지 다운로드

 

let processor = DownsamplingImageProcessor(size: CGSize(width: 100, height: 100))
imageView.kf.setImage(with: url, options: [.processor(processor)])

 

아마 빠른 시일내에 라이브러리를 사용하지 않는 방법에 대해서도 다룰텐데.. 

다운샘플링 기능처럼 복잡한 이미지 처리 로직을 단 몇 줄의 코드로 해결할 수 있다는 점이... 참.. 👍

 

3. 플레이스홀더 및 오류 처리

- 이미지가 로드되는 동안 플레이스홀더 이미지를 표시하거나 로드 실패 시 기본 이미지 설정 가능

 

imageView.kf.setImage(
    with: url,
    placeholder: UIImage(systemName: "person.circle"),
    options: [.transition(.fade(0.2))],
    completionHandler: { result in
        switch result {
        case .success(let value):
            print("Image loaded: \(value.image)")
        case .failure(let error):
            print("Error: \(error)")
        }
    }
)

 

 

4. 이미지 처리(Transformations)

- 이미지를 다운로드한 후 필터, 자르기, 리사이징 등의 작업을 간단히 적용 가능

 

let processor = RoundCornerImageProcessor(cornerRadius: 20)
imageView.kf.setImage(with: url, options: [.processor(processor)])

 

 

5. GIF 및 애니메이션 이미지 지원

- GIF 및 애니메이션 이미지도 Kingfisher로 쉽게 로드 및 캐싱 가능

 

이 부분은 제가 사용해 본 적이 없어서.. Pass~ 슉 지나가겠습니다

 

6. 캐시 관리 기능

- 다양한 캐시 옵션 제공

 

a. 캐시 저장 위치 지정

- 이미지를 메모리 캐시에만 저장하고 디스크에는 저장 X

imageView.kf.setImage(
    with: url,
    options: [.cacheMemoryOnly]
)

 

b. 캐시 무효화

- 기존 캐시된 이미지를 무시하고, 항상 네트워크 요청으로만 이미지 다운로드

imageView.kf.setImage(
    with: url,
    options: [.forceRefresh]
)

 

c. 캐시 데이터 만료 설정

-  캐시된 데이터의 만료 기간을 설정하여 자동으로 오래된 데이터를 삭제 가능

let cache = ImageCache.default
cache.diskStorage.config.expiration = .days(7) // 디스크 캐시 데이터 7일 후 만료
cache.memoryStorage.config.expiration = .seconds(300) // 메모리 캐시 데이터 5분 후 만료

 

d. 캐시 정리

-  불필요한 데이터 정리 캐시 크기 감소

 

let cache = ImageCache.default
cache.clearMemoryCache() // 메모리 캐시 초기화
cache.clearDiskCache() // 디스크 캐시 초기화
cache.cleanExpiredDiskCache() // 만료된 디스크 캐시 데이터 삭제

 

 

7. URLRequest 커스텀

- 인증토큰, 헤더 변경 등을 통해 네트워크 됴청을 세부적으로 커스텀 가능

- 언제쓰냐?? >> 인증이 필요한 이미지 요청(프로필 이미지 등)

  func fetchProfileImage(imageString: String) -> ( URL, AnyModifier)? {
        
        guard let url = URL(string: "이미지 URL에 ImageString 합쳐요") else {
            print("유효하지 않은 URL")
            return nil
        }
        let header: [String : String] = [
            APIKey.HTTPHeaderName.authorization.rawValue: UserDefaultsManager.accessToken,
            APIKey.HTTPHeaderName.sesacKey.rawValue: APIKey.developerKey,
            APIKey.HTTPHeaderName.productID.rawValue : APIKey.HTTPHeaderName.productIDContent.rawValue
        ]
        
        let modifier = AnyModifier { request in
            var request1 = request
            header.forEach { (key, value) in
                request1.setValue(value, forHTTPHeaderField: key)
            }
            return request1
        }
        
        
        return (url, modifier)
    }
    
    
     if let (url, modifier) = NetworkManager.shared.fetchProfileImage(imageString: urlString) {
            imageView.kf.setImage(
                with: url,
                options: [
                    .requestModifier(modifier),
                    .processor(processor),
                    .scaleFactor(UIScreen.main.scale),
                    .cacheMemoryOnly, // 메모리 캐시만 사용
                    .transition(.fade(0.2))
                ]
            )
        } else {
            imageView.image = UIImage(systemName: "person")
        }

 

 

여기까지 Kingfisher라는 라이브러리의 사용법 / 기능 들에 대해서 알아보았는데요..!

그래도 근본은 알고있어야 하니 최대한 빠르게 라이브러리를 사용하지 않는 방법에 대해서도 글을 적어보겠습니다.

 

.

.

.

.

 

'Swift' 카테고리의 다른 글

[iOS] About 채팅 UI  (0) 2024.11.20
[iOS] About Local Notification  (0) 2024.11.13
[iOS] About 동시성  (0) 2024.11.10
[iOS] About WidgetKit - 2(App Group)  (0) 2024.11.02
[iOS] About TDD  (1) 2024.10.30