project/개발 업무

기기별 RAM 용량에 따른 이미지 동적 캐시 사이즈 설계

lgvv 2026. 3. 25. 23:02

기기별 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

아이폰 15 Pro

 

아이폰 13 mini

아이폰 13 미니

 

기기 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