ABOUT ME

작은 디테일에 집착하는 개발자

Today
-
Yesterday
-
Total
-
  • [Project/Android] `OutOfMemoryError` 오류 해결하기
    Daily/Project 2023. 12. 19. 15:52
    728x90

    1. Physical 안드로이드 기기 테스트 중 오류

    안드로이드 스튜디오에서 제공하는 Virtual(가상) 안드로이드 기기가 아닌,

    Physical(실제) 안드로이드 기기에서 테스트하던 중 다음과 같은 에러가 발생하였습니다.

     

    java.lang.OutOfMemoryError:
    Failed to allocate a 23425512 byte allocation with 16766392 free bytes and 21MB until OOM

     

    주목해야 할 단락은 위 메시지입니다. 해당 오류 메시지에서는 23,425,512 바이트를 할당하려고 했지만,

    현재 사용 가능한 메모리가 16,766,392 바이트 밖에 남아있지 않다는 것을 나타냅니다.

    이에 따라 시스템은 OutOfMemoryError를 발생시켰습니다.

     

     

    2. 해결하는 방법

    "사용자 경험(UX)이 더 중요할까, 성능이 더 중요할까?" 저는 방법을 모색하던 도중 선택의 기로에 서게 되었습니다.

    빠른 이미지 로드로 사용자 경험 향상하기 그리고 메모리나 디스크 사용의 최소화

    어떤 것을 선택해야 할지 고민하게 되었습니다.

     

    음... 앱이 잘 돌아가야 하니, 성능에 높은 우선순위를 두고 코드를 수정해 보도록 하죠.

    자세히 보니 이런 코드가 로그가 있더군요. 이 파일을 수정해야겠습니다.

     

    at com.three.green_defense_force.activities.GameDetailActivity.onCreate(GameDetailActivity.kt:50)

     

    2-1. 메모리 관리 코드 추가하기

    메모리 캐시를 사용하지 않도록 설정하였습니다. 이미지를 메모리에 캐싱할 경우 동일한 이미지를 빠르게 다시 로드할 수 있지만, 메모리 사용량이 높아지기 때문에 이를 해제시키도록 하겠습니다.
    .skipMemoryCache(true)

     

    Before

    private fun loadImageFromUrl(url: String, imageView: ImageView) {
        Glide.with(this)
            .load(url)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .into(imageView)
    }

     

    After

    private fun loadImageFromUrl(url: String, imageView: ImageView) {
        Glide.with(this)
            .load(url)
            .thumbnail(0.1f)
            .skipMemoryCache(true)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .into(imageView)
    }

     

    해결... 완료... ⭐️ 그럼 이만 마치 도로ㄱ... 이게 아니죠.. skipMemoryCache(true)가 무엇인지조금 더 보도록 하겠습니다.

     

     

    3. skipMemoryCache(true)

    skipMemoryCache는 Glide의 메모리 캐시를 비활성화하는 옵션입니다.

    Glide는 이미지를 메모리에 캐시 하여 동일한 이미지를 빠르게 로드하도록 하지만,

    가끔 큰 이미지를 다뤄야 할 때 메모리 부족 문제가 발생할 수 있습니다.

     

    skipMemoryCache(true)를 사용하면 Glide는 해당 이미지를 메모리에 캐시 하지 않고 디스크에만 캐시 하게 됩니다.

    (디스크에 캐시를 할지 말지도 선택할 수 있죠. 뒤에서 다루겠습니다.)

     

    ⛔️ 주의사항 ⛔️

    그러나 메모리 캐시를 건너뛰면 이미지를 다시 로드할 때마다 네트워크 또는 로컬 디스크에서 이미지를 읽어와야 하므로

    성능이 약간 감소할 수 있습니다.

     

     

    4. 해결한 코드 꼼꼼히 살펴보기

    /** URL → 이미지 변환하는 함수 */
    private fun loadImageFromUrl(url: String, imageView: ImageView) {
        Glide.with(this)
            .load(url)                                // Glide로 이미지 URL 로드
            .thumbnail(0.1f)                          // 이미지 로딩 속도 향상
            .skipMemoryCache(true)                    // 메모리 캐시 사용 X
            .diskCacheStrategy(DiskCacheStrategy.ALL) // 모든 이미지를 디스크에 캐싱
            .into(imageView)                          // ImageView에 이미지 설정
    }

     

    모든 이미지를 디스크에 캐싱하도록 설정하였습니다. 이미지를 디스크에 캐싱하여, 동일한 URL의 이미지에 대한 반복 다운로드를 방지하고 로딩 시간을 단축할 수 있습니다.
    .diskCacheStrategy(DiskCacheStrategy.ALL)

     

     

    5. 결론

    .skipMemoryCache(true)
    .diskCacheStrategy(DiskCacheStrategy.ALL)


    이 두 옵션을 함께 사용하는 경우, 메모리 측면에서는 캐싱을 하지 않고, 디스크 측면에서는 캐싱을 하게 됩니다.

    이를 통해 메모리 사용을 최소화하면서도 디스크 캐싱의 이점을 얻을 수 있습니다.

Designed by Tistory.