Glide

이미지 로드 라이브러리

Glide

Glide


쉽게 이미지를 로드하고 이미지 캐싱까지 지원해주는 이미지 로드 라이브러리이다.

사용법은 with()Context 를 지정하고, load() 에 불러올 이미지를 지정하고, into() 에 불러온 이미지를 바인딩할 ImageView 를 지정하면 된다.

fun ImageView.bindImage(url: String) =
    Glide.with(this)
        .load(url)
        .into(this)


Glide 는 이미지 로드 뿐만 아니라 다양한 처리를 위한 옵션들을 제공해준다.

fun ImageView.bindImage(url: String) =
    Glide.with(this)
        .load(url)
        .override(100, 100)
        .thumbnail(0.1f) // 0.1f = 10% 화질
        .placeholder(R.drawable.holder)
        .error(R.drawable.error)
        .fallback(R.drawable.empty)
        .into(this)
  • override() 를 사용하여 이미지의 크기를 조절해서 로드할 수 있는데, 만약 불러오는 이미지가 너무 클 경우 이미지 로드 속도가 느려지거나 OutOfMemory 가 발생하는 것을 방지할 수 있다.
  • thumbnail() 을 사용하여 먼저 화질이 낮은 이미지를 보여주고 이후 원본 이미지를 보여줄 수 있다.
  • placeholder() 를 사용하여 이미지가 로드되기 전 표시되는 이미지를 지정할 수 있다.
  • error() 를 사용하여 이미지 로드에 실패했을 때 표시되는 이미지를 지정할 수 있다.
  • fallback() 을 사용하여 로드할 이미지의 URLnull 인 경우 표시되는 이미지를 지정할 수 있다.

Glide 는 이미지 요청에 대한 콜백 리스너도 제공해준다.

val listener = object: RequestListener<Drawable> {
     override fun onResourceReady(
        resource: Drawable?, 
        model: Any?, 
        target: Target<Drawable>?, 
        dataSource: DataSource?, 
        isFirstResource: Boolean)
    : Boolean {
        /* 성공 */
    }

    override fun onLoadFailed(
        e: GlideException?, 
        model: Any?, 
        target: Target<Drawable>?, 
        isFirstResource: Boolean
    ): Boolean {
        /* 실패 */
    }
}


Glide 를 사용하는 ImageView 가 여러 개이고 모두 동일한 Option 을 공유한다면 RequestOptions 객체를 통해 옵션을 공유할 수 있다.

val option = RequestOptions()
        .override(100, 100)
        .placeholder(R.drawable.error)
        .error(R.drawable.error)
        .diskCacheStrategy(DiskCacheStrategy.ALL)

Glide.with(this).load(url).apply(option).into(this)



이미지 캐싱


동일한 URL 에서 반복적으로 이미지를 불러오게 된다면 이미지 크기가 작은 상황에서는 문제가 없지만, 큰 이미지를 받아오는 상황이라면 매번 수 초의 시간과 상당한 양의 메모리가 할당되기 때문에 성능적으로 좋지 않은데, 이러한 문제를 해결하기 위한 방법이 이미지 캐싱이다.

이미지 캐싱은 URL 에서 가져온 이미지를 캐시에 저장해서 동일한 URL 을 요청했을 때 재요청 없이 캐시에 저장한 이미지를 로드하는 방법으로, Glide 에서는 이를 쉽게 사용할 수 있도록 지원해준다.

Glide 의 이미지 캐시 처리는 리소스가 메모리에 있는지 확인하고, 그 다음으로 이미지가 디스크에 있는지 확인하고, 만약 이미지를 찾지 못한다면 Glide 는 원본 소스로 돌아가 데이터를 검색한다.


Glide 는 기본적으로 메모리 캐싱을 하기 때문에 메모리 캐싱을 위해 추가적으로 설정할 것은 없다.

하지만 URL 이미지 로드 시 한 번 로드한 이미지는 캐싱되어 서버에서 해당 이미지를 변경해도 이미지가 갱신되지 않는데, 이런 경우 skipMemoryCache(true) 로 메모리 캐시를 사용하지 않을 수 있다.

fun ImageView.bindImage(url: String) =
    Glide.with(this)
        .load(url)
        .skipMemoryCache(true)
        .into(this)


Glide 는 기본적으로 디스크 캐싱을 수행하며 메모리 캐싱과 동일하게 동작하고 5가지의 DiskCacheStrategy 를 지원한다.

fun ImageView.bindImage(url: String) =
    Glide.with(this)
        .load(url)
        .diskCacheStrategy(DiskCacheStrategy.NONE)
        .into(this)
  • DiskCacheStrategy.ALL 은 모든 이미지를 캐싱하는 전략이다.
  • DiskCacheStrategy.AUTOMATICResource 를 기반으로 전략적인 캐싱을 하는 전략이다.
  • DiskCacheStrategy.DATA 는 원본 이미지만 캐싱하는 전략이다.
  • DiskCacheStrategy.RESOURCE 는 해상도를 줄인 이미지만 캐싱하는 전략이다.
  • DiskCacheStrategy.NONE 은 디스크 캐싱을 안하는 전략이다.

이미지가 메모리 캐시 또는 디스크 캐시에서 발견되면 로드 되고, 없다면 로드가 되지 않는 옵션도 지원한다.

fun ImageView.bindImage(url: String) =
    Glide.with(this)
        .load(url)
        .onlyRetrieveFromCache(true)
        .into(this)



LRU Cashe


LRU Least Recently Used(최근에 가장 적게 참조됨)의 약자로, LRU Cache 는 제한된 사이즈에서 참조된지 가장 오래된 객체를 제거하는 데이터 구조로, 자주 참조되는 객체일 수록 빠르게 캐시를 통해 객체에 접근할 수 있다.

put(Key, Value) 를 통해 캐싱을 시도 할 수 있으며, 캐시에 있는 데이터를 참조할 때는 get(Key) 을 사용하면 된다.

 val cache = LruCache<String, Int>(5).apply { // maxSize = 5
    put("A",0) // [A]
    put("B",0) // [A, B]
    put("C",0) // [A, B, C]
    put("D",0) // [A, B, C, D]
    put("E",0) // [A, B, C, D, E] - A 부터 E 까지 캐싱 완료
    put("F",0) // [B, C, D, E, F] - F 를 캐싱하면, 캐시 사이즈를 초과하므로 최근에 가장 적게 참조된 A 는 제거됨
    put("D",0) // [B, C, E, F, D] - 캐시에 이미 포함된 키인 D 를 다시 캐싱을 하면 D 가 가장 최근에 참조된 키이므로 내부에서 데이터를 재배열하고 최근 참조된 상태로 변경됨
    get("C")   // [B, E, F, D, C] - 키가 C 인 값을 얻고자 하면 C 가 가장 최근에 참조된 키이므로 다시 내부에서 데이터를 재배열 하고 최근 참조된 상태로 변경됨
 } 


LRU Cache 를 사용하는 대표적인 예가 Bitmap 캐싱으로, RecyclerView 에서 대량의 이미지를 한번에 로드하고 스크롤하여 재사용되는 경우 LRU Cache 의 사용은 성능 향상에 많은 도움이 된다.

많은 Bitmap 을 메모리에 캐시하는 것은 부담될 수 있으므로 DiskLruCache 와 같은 디스크 캐싱을 같이 사용하면 좀 더 메모리 부담을 줄일 수 있으며, 이러한 Bitmap 캐싱을 최적화하여 제공하고 있는 라이브러리가 Glide 이다.

essential