기기별 RAM 용량에 따른 이미지 동적 캐시 사이즈 설계
글로벌 서비스를 운영하다 보면 RAM 2~3GB 수준의 구형 기기(iPhone 6s, SE 1, 2세대 등)를 사용하는 유저가 여전히 많이 존재.
비율이 낮더라도 절대 사용자 수 기준으로 보면 무시하기 어려운 규모
- 저사양 기기에서는 메모리 압박으로 인한 크래시 위험 증가
- 고사양 기기에서는 사용 가능한 자원을 충분히 활용하지 못하는 비효율 발생
기기의 물리적 RAM 용량을 기준으로 캐시 크기를 동적으로 결정하는 방향으로 설정
왜 동적 설정이 필요할까?
iOS는 앱이 사용할 수 있는 메모리 한도를 초과하면 명시적인 에러 없이 프로세스를 종료할 수 있음.
저사양 기기의 경우
- RAM 2GB 기기에서 캐시를 1GB로 고정하는 것은 실제 사용 가능한 메모리 대비 과도한 점유가 될 수 있음.
- 경우에 따라서는 결과적으로 메모리 부족으로 인한 크래시 확률이 높아짐.
고사양 기기의 경우
- 더 큰 이미지 캐시를 사이즈를 유지하여 더 부드러운 경험 제공 가능
- 디스크 접근 및 네트워크 재요청 감소
- 이미지 디코딩 비용 감소
전체 코드
메모리 캐시 사이즈에 기기별 가용 가능한 메모리 크기를 기반으로 상한값을 다르게 설정.
pyshicalMemory는 기기 스펙의 메모리 용량과 일치하지 않음.
- 아래 코드에서 1/8 값을 사용하고 있으나 프로젝트 특성에 맞게 변경해도 됨.
- 안드로이드 공식 문서에서 1/8 사용하고 있는 예제가 있어서 그대로 적용
private func configureImageCacheLimits() {
// 기기의 물리적 RAM 전체 용량 (단위: bytes)
// 예) 6GB RAM → 6,442,450,944 bytes
let physicalMemory = ProcessInfo.processInfo.physicalMemory
// 이미지 캐시에 허용할 최소 메모리 한도 (단위: MB)
let minimumLimitMB: UInt64 = 100
// 이미지 캐시에 허용할 최대 메모리 한도 (단위: MB)
let maximumLimitMB: UInt64 = 512
// physicalMemory(bytes) → MB 변환 과정:
// ÷ 8 : 전체 RAM의 1/8만 캐시에 사용 (나머지는 OS·앱 등이 사용)
// ÷ 1024 : bytes → KB
// ÷ 1024 : KB → MB
//
// 예) 6GB RAM 기기:
// 6,442,450,944 ÷ 8 = 805,306,368 bytes (약 768MB, RAM의 1/8)
// 805,306,368 ÷ 1024 = 786,432 KB레
// 786,432 ÷ 1024 = 768 MB
// → min(512, 768) = 512 → max(100, 512) = 512MB 적용
//
// 예) 2GB RAM 기기:
// 2,147,483,648 ÷ 8 = 268,435,456 bytes (약 256MB)
// → 256MB → max(100, 256) = 256MB 적용
let computedLimitMB = max(
minimumLimitMB,
min(maximumLimitMB, physicalMemory / 8 / 1024 / 1024)
)
// 최종 캐시 한도를 다시 bytes로 변환 (SDImageCache에 bytes 단위로 전달해야 하므로)
// 예) 512MB → 512 × 1024 × 1024 = 536,870,912 bytes
let physicalMemoryMB = physicalMemory / 1024 / 1024
let physicalMemoryGB = physicalMemoryMB / 1024
var systemInfo = utsname()
uname(&systemInfo)
let deviceModel = withUnsafePointer(to: &systemInfo.machine) {
$0.withMemoryRebound(to: CChar.self, capacity: 1) {
String(validatingUTF8: $0) ?? "Unknown"
}
}
print("기기 모델: \(deviceModel)")
print("물리 메모리: \(physicalMemoryGB) GB")
print("캐시 한도: \(computedLimitMB) MB")
}
아이폰 15 Pro

아이폰 13 mini

| 기기 | RAM | 1/8 계산값 | 최종 적용 |
| iPhone SE (1st) | 2GB | 256MB | 256MB |
| iPhone 11 | 4GB | 512MB | 512MB |
| iPhone 15 Pro | 6GB | 1024MB | 512MB (상한 제한) |
(참고)
https://developer.android.com/topic/performance/graphics/cache-bitmap?hl=ko
비트맵 캐싱 | App quality | Android Developers
단일 비트맵을 사용자 인터페이스(UI)에 로드하는 것은 간단하지만 한 번에 더 큰 이미지의 집합을 로드해야 하면 더 복잡해집니다. 많은 경우(ListView, GridView 또는 LruCache 클래스와 같은 구성요소
developer.android.com
'project > 개발 업무' 카테고리의 다른 글
| UNUserNotificationCenter `requestAuthorization`에서 발생하는 희귀한 버그 현상 분석 (0) | 2025.10.27 |
|---|---|
| l-value, r-value (0) | 2025.10.23 |
| Actor에서 Class + OSAllocatedUnfairLock (2) | 2025.08.06 |
| Swift Concurrency Task weak self 실험 정리 (0) | 2025.07.29 |
| Tuist CocoaPod 연동 (0) | 2025.07.05 |