[Android] Image Loading Library Coil

이승우·2023년 5월 31일
2
post-thumbnail

Coil

CoilCoroutine Image Loader의 약자로 Kotlin Coroutine 기반으로 만들어진 가벼운 Android Image Loading Library 이다.

100% kotlin으로 작성되었으며, 자체적으로 코루틴을 사용하고 있다는 특징이 있다.

왜 Coil인가?

Image Loading Library로는 Glide나 Picasso 같은 것들도 있는데 왜 Coil일까?

  • 장점
    • 최대 2000개의 메소드들을 APK에 추가한다.(이미 OkHttp와 Coroutines을 사용중인 앱에 한하여) 이는 Glide, Fresco보다 상대적으로 가볍다.
    • 코루틴이 기본이지만 메인까지는 아니며, 심플함과 최소한의 보일러 플레이트를 위하여 Koltin의 기능을 활용하여 Kotlin을 잘 다룬다면 사용하기가 매우 쉽다.
    • 메모리와 디스크의 캐싱, 메모리의 이미지 다운 샘플링, Bitmap 재사용, 일시정지/취소의 자동화 등등 수많은 최적화 작업을 수행하므로 처리 속도가 굉장히 빠르다.
    • 다이나믹 이미지 샘플링을 지원하며 이는 Coil에서 자동으로 알아서 처리된다.
    • Coil의 이미지 파이프라인은 크게 3가지로 구성된다. Mappers, Fetchers, Decoders 이러한 인터페이스를 사용하여 기본 이미지 로딩 기능을 강화하거나 재정의하고 Coil에 새로운 파일 형식에 대한 지원을 추가할 수 있다.
    • Kotlin으로 개발되었으며 Coroutines, OkHttp, Okio, AndroidX Lifecycles 등의 최신 라이브러리 등을 지원하여 현대적이다.
  • 단점
    • 최소 Android SDK 버전 14부터 지원을 하나 최신버전에서 사용하는 것을 권장한다.(AndroidX)
    • Kotlin을 모른다면 사용하기 어렵다.
    • Coroutine에 대한 개념을 어느정도 알아야 좋다.

coil vs glide vs picasso

안드로이드에서 사용할 수 있는 이미지 로딩 라이브러리는 많이 존재한다. 개발자가 어떠한 라이브러리 없이 이미지를 로드하려고 한다면 고려해야 하는 요소가 많이 존재하는데 이를 third party에게 위임함으로써 걱정을 덜게 될 수 있다.

대표적인 라이브러리의 종류로는 Picasso, Glide, Goil이 있으며, 어떻게 사용하는지 성능은 어떤지 비교해보려고 한다. 직접 해보지는 않았고, 다른 분의 블로그를 참고했다. 🙏

1. Picasso

MinSdkVersion = 14
CompileSdkVersion = 29
Library size : 121kb
GIF 지원 ❌

Square에서 만든 Picasso는 최소한의 메모리로 이미지의 다양한 Trasnformation을 지원하며 자동으로 메모리 & 디스크 캐싱, 어댑터에서 ImageView를 재활용 및 다운로드 취소가 가능하다는 점을 강조하고 있다.

Picasso.get().load(url)
	.transform(RoundedCornersTransformation(128, 3))
	.into(imageView5, object : Callback {
		override fun onSuccess() {
			toast("Complete")
		}

		override fun onError(e: Exception?) {
			TODO("Not yet implemented")
		}
})
  • 최초 로딩 속도 : 6.4s
  • 기본 캐싱 적용 : 1.6s

Picasso는 원본 이미지 크기를 그대로 비트맵에 그린 후에 이미지뷰에 적용한다. 예를 들어, 1000x800의 이미지가 존재할 때 Bitmap 1000x800x4bytes = 3MB가 ImageView 위에 올라갈 것이다. 그렇기 때문에 고화질의 이미지를 로드한다면 OOM이 발생할 가능성이 있다.

이러한 문제를 방지하기 위해 fit() 함수를 이용하여 이미지를 로드하기 전 리사이징한 이미지를 이미지뷰에 로드하여 메모리 사용량을 줄일 수 있다.

Picasso.get()
	.fit()
	.transform({...})
	.load(url)

Heap Dump

10,136,858 byte = 10MB

2. Glide

MinSdkVersion = 14
CompileSdkVersion = 26
Library size = 440kb
GIF 지원 ⭕️

Google에서 만든 이미지 로더 라이브러리인 Glide는 빠른 이미지 로딩, 버벅거림과 끊김 현상이 발생하지 않는다는 점을 강조하고 있다. 커스텀된 HttpUrlConnection을 사용하지만 Volly 또는 OkHttp 라이브러리에 연결할 수 있는 유틸리티 라이브러리도 포함되어 있어 우리가 자주 사용하고 있는 라이브러리와 호환성이 좋다.

Glide는 아래처럼 싱글톤으로 만들어서 간단하게 사용할 수 있다.

Glide.with(this)
	.load(url)
	.apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(128, 3)))
	.listener(object : RequestListener<Drawable> {
		override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
			TODO("Not yet implemented")
		}

		override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
			toast("Complete")
			return false
		}
	})
	.into(imageView)
  • 최초 로딩 속도 : 6.2s
  • 기본 캐싱 적용 : 0.72s

Picasso와 다르게 Glide는 원본 이미지를 비트맵에 그리는게 아니라 할당하려는 이미지뷰의 크기를 측정한 다음 원본 이미지를 이미지 뷰 크기에 맞게 리사이징한 뒤, 비트맵에 그려주는 것을 기본 옵션으로 하기 때문에 메모리 효율성이 Picasso보다 좋다.

또한, 라이브러리들 중에서 Glide가 GIF를 완벽하게 지원하는 것 같다. Picasso는 미지원, Coil은 1.2.2 기준 확장 라이브러리로 GIF를 지원하나 라이브러리 자체가 불안정했으며, Fesco는 GIF에 Transformation과 같은 다양한 옵션을 적용할 수는 없었다.

Heap Dump

11,004,024 byte = 11MB

3. Coil

MinSdkVersion = 14
CompileSdkVersion = 30
GIF 지원 ⭕️

Instacart에서 만든 Coil은 Coroutine Image Loader의 줄임말로 코틀린과 코루틴으로 구성이 되어 있다. 장점으로는 100% 코틀린으로 이루어졌다는 점과 AndroidX, OkHttp 등 현업에서 많이 쓰이고 있는 라이브러리들을 지원하고 있다는 점이다.

Coil의 내부는 Glide와 굉장히 비슷하다는 것을 알 수 있는데 Glide를 많이 벤치마킹 했다고 한다. 또한, ImageView의 확장 함수로 지원하고 코틀린의 함수형 언어 덕으로 다른 라이브러리보다 더욱 간결한 코드를 구성할 수 있다.

imageView.load(url) {
	listener(
		onError = { _,_ -> /** Show toast. */ },
		onSuccess = { _,_ -> toast("Complete") }
	}
)
transformations(RoundedCornersTransformation(128f))
}
  • 최초 로딩 속도 : 5.24s
  • 기본 캐싱 적용 : 1.3s

Heap Dump

6,995,072 byte = 7MB

Ref

profile
Android Developer

1개의 댓글

comment-user-thumbnail
2024년 2월 7일

좋은 글 감사합니다~

답글 달기