CS, Swift: LRU(Least Recently Used)을 활용해 ImageCacher 구현해보자

Insub
4 min readJul 4, 2024

--

들어가며

최근에 정보처리기사를 공부하며 LRU(Least Recently Used), LFU(Least Frequently Used)에 대해 공부한 것을 실전에 적용하기 위해 이미지 캐셔를 구현해보겠습니다. 이 글에서는 LRU 캐싱 전략을 사용하여 간단하면서도 효율적인 ImageCacher를 만들어 보겠습니다.

설명

LRU 캐싱은 가장 최근에 사용된 데이터를 캐시에 유지하고, 오래된 데이터를 제거하는 방식입니다. 이를 통해 자주 사용되는 데이터는 캐시에 남겨두고, 사용되지 않는 데이터는 자동으로 제거할 수 있습니다. 아래의 코드는 Swift의 actor를 활용하여 스레드 안전한 LRU 캐시를 구현한 예제입니다.

actor ImageCacher {

static let shared = ImageCacher()
private init() { }

private var cachedImages: [String: UIImage] = [:]
private var accessOrder: [String] = []
private let cacheLimit = 100

func cachedImage(for key: String) -> UIImage? {
if let image = cachedImages[key] {
updateAccessOrder(for: key)
return image
}
return nil
}

func cacheImage(_ image: UIImage, for key: String) {
if cachedImages.keys.count >= cacheLimit {
removeOldestImage()
}
cachedImages[key] = image
updateAccessOrder(for: key)
}

private func updateAccessOrder(for key: String) {
accessOrder.removeAll { $0 == key }
accessOrder.append(key)
}

private func removeOldestImage() {
if let oldestKey = accessOrder.first {
cachedImages.removeValue(forKey: oldestKey)
accessOrder.removeFirst()
}
}
}

코드 설명

캐시 구조:

  • cachedImages: 이미지 데이터를 저장하는 딕셔너리입니다.
  • accessOrder: 이미지 키의 접근 순서를 저장하는 배열입니다.
  • cacheLimit: 캐시에 저장할 이미지의 최대 수를 설정합니다.

cachedImage(for:):

  • 주어진 키에 해당하는 이미지를 반환합니다.
  • 이미지가 존재하면 접근 순서를 업데이트합니다.

cacheImage(_:for:):

  • 주어진 키와 이미지 데이터를 캐시에 저장합니다.
  • 캐시의 크기가 제한을 초과하면 가장 오래된 이미지를 제거합니다.
  • 접근 순서를 업데이트합니다.

updateAccessOrder(for:):

  • 접근한 키를 accessOrder에서 제거한 후 맨 뒤에 추가하여 최신 접근으로 업데이트합니다.

removeOldestImage():

  • accessOrder 배열의 첫 번째 항목을 제거하여 가장 오래된 이미지를 삭제합니다.

결론

LRU(Least Recently Used) 페이지 교체 기법을 활용한 이미지 캐셔를 구현했습니다. 이 방식은 자주 사용되는 데이터를 캐시에 유지하고, 오래된 데이터를 자동으로 제거하여 메모리 사용을 효율적으로 관리할 수 있습니다. Swift의 actor를 사용하여 스레드 안전성을 보장하였습니다.

--

--