(Part 1) Jetpack Compose와 Glide, Coil, Fresco 이미지 로딩 라이브러리 Landscapist

skydoves·2022년 2월 8일
4

본 포스트는 총 2부로 연재되며, 아래에서 2부 포스트를 확인하실 수 있습니다.

이번 포스트에서는 Jetpack Compose와 Twitter를 비롯하여 전 세계적으로 수많은 안드로이드 애플리케이션 개발에 사용되고 있는 오픈소스 라이브러리 landscapist 에 관한 이야기 및 사용법을 소개합니다.

Jetpack Compose

Jetpack Compose란 기존의 안드로이드 XML 레이아웃 구조를 완전히 대체하고, 선언형 구조를 통하여 UI 컴포넌트의 재사용성을 극대화함으로써 다양한 이득을 취할 수 있도록 Google에서 다년간 야심차게 개발한 차세대 UI 툴킷입니다. 구글에서는 Jetpack Compose를 다음과 같이 소개하고 있습니다.

Jetpack Compose is Android’s modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.

작년 7월 28에 1.0 stable 버전이 출시된 이후로, 세계적으로 다양한 테크 기업에서 안드로이드 앱 개발에 Jetpack Compose를 도입하기 시작했습니다. 가장 대표적으로 우리가 자주 사용하고 있는 Google Play의 많은 화면들이 Jetpack Compose로 개발되었으며, Twitter, Square의 Cash App, Airbnb, Lyft와 같은 글로벌 기업들이 이미 production level에서 Jetpack Compose를 적극 활용하고 있습니다.

구글에서 지속적으로 Jetpack Compose 개발에 리소스를 지원해 주고 다양한 글로벌 기업들에서 제품 개발에 도입하고 있는 것으로 보아 Jetpack Compose는 현재 매우 유망하고 향후 발전은 나날이 기대되고 있습니다.

Landscapist

구글이 Jetpack Compose라는 차세대 기술을 선보였지만, 선언형 UI 패러다임을 제시하면서 기존의 Android View와 관련된 많은 UI 관련 솔루션들이 Jetpack Compose를 지원하기 위한 별도의 솔루션을 내놓아야 했고, 앱 개발에서 큰 비중을 차지하는 이미지 로딩 솔루션 또한 예외는 아니었습니다.

안드로이드에서 이미지 로딩을 위해 가장 대중적으로 사용되는 오픈소스 라이브러리 Glide, Coil, Fresco는 기존의 Android View 시스템을 기반으로 개발되었기 때문에 Jetpack Compose에서는 해당 솔루션들을 사용하기 적합한 형태로 추가적인 작업이 요구되었습니다.

당시 구글의 비공식 Jetpack Compose 툴킷이라고 불리던 accompanist에서도 지원했던 이미지 로딩 라이브러리는 Coil 뿐이었고, 추후에 Glide와 Picasso를 위한 솔루션이 추가되었지만 현재는 모두 유지 보수 문제로 depcreated 된 상태입니다.

때문에 Jetpack Compose 도입을 고려할 때 자체 솔루션을 개발해야 하거나 이미지 라이브러리를 Coil로 통째로 마이그레이션 해야 하는 상당한 비용을 감수해야 했습니다. 이는 많은 기존의 프로젝트들이 Jetpack Compose를 도입하는데 큰 장벽이 될 수 있다는 것을 암시하였고, 그 비용을 최소화하는 데 도움을 드리고자 landscapist가 탄생하게 되었습니다. 🎉

Go Foraward with Landscapist

당시 Glide, Coil, Picasso를 지원하던 accompanist는 유지 보수 문제로 지원을 모두 중단하게 되었고, 그 이후 감사하게도 accompanist의 메인테이너인 Chris Banes님께서 landscapist를 대안으로 여러 번 추천해 주셨습니다.

landscapist가 탄생한지 1년 반이 지난 현재는 Twitter (트위터), Azar (아자르) 등을 비롯한 수많은 글로벌 안드로이드 앱 개발에 사용되고 있습니다.

Maven Nexus Repository 통계를 기준으로 매달 15만~20만 건의 download가 집계되고 있고, landscapist가 사용된 세계적인 앱들의 end user 수를 합치면 최소 5억 명을 넘어서는 것으로 추측되고 있습니다. 또한 구글의 각종 sample 프로젝트나 다양한 오픈소스 프로젝트에서도 사용 사례를 찾아보실 수 있습니다.

How to Use

이제 landscapist의 사용 방법에 대해 살펴보겠습니다. landscapist는 Glide, Coil, Fresco 3가지의 솔루션을 제공하기 때문에 프로젝트에서 사용하는 이미지 로딩 솔루션과 동일한 라이브러리를 선택하시는 것을 권장드립니다.

각 솔루션 별로 의존성과 기본적인 사용법에 대하여 살펴보겠습니다.

최신 버전은 release에서 확인하실 수 있습니다.

Glide

Glide의 경우에는 아래의 의존성을 build.gradle 파일에 추가해 주셔야 합니다.

dependencies {
    implementation "com.github.skydoves:landscapist-glide:1.4.7"
}

의존성이 추가된 후 아래 예시와 같이 GlideImage Composable 함수를 사용하여 네트워크 이미지를 로드하실 수 있습니다.

GlideImage(
  imageModel = imageUrl,
  // Crop, Fit, Inside, FillHeight, FillWidth, None
  contentScale = ContentScale.Crop,
  // shows an image with a circular revealed animation.
  circularReveal = CircularReveal(duration = 250),
  // shows a placeholder ImageBitmap when loading.
  placeHolder = ImageBitmap.imageResource(R.drawable.placeholder),
  // shows an error ImageBitmap when the request failed.
  error = ImageBitmap.imageResource(R.drawable.error)
)

imageModel에는 String, Uri, HttpUrl, File, DrawableRes, Drawable, Bitmap 타입을 사용하실 수 있습니다. 이미지 로드를 위해서 위의 예시에서 보여드린 모든 인자가 필요한 것은 아니기 때문에, 상황에 맞도록 사용자 정의하시는 것을 권장 드립니다.

추가적인 참고 자료가 필요하신 경우는 Landscapist-Glide를 참조해 주시길 바랍니다.

Coil

Coil을 포함하기 위해서는 아래의 의존성을 build.gradle 파일에 추가해 주셔야 합니다.

dependencies {
    implementation "com.github.skydoves:landscapist-coil:1.4.7"
}

의존성이 추가된 후 아래 예시와 같이 CoilImage Composable 함수를 사용하여 네트워크 이미지를 로드하실 수 있습니다.

CoilImage(
  imageModel = imageUrl,
  // Crop, Fit, Inside, FillHeight, FillWidth, None
  contentScale = ContentScale.Crop,
  // shows an image with a circular revealed animation.
  circularReveal = CircularReveal(duration = 250),
  // shows a placeholder ImageBitmap when loading.
  placeHolder = ImageBitmap.imageResource(R.drawable.placeholder),
  // shows an error ImageBitmap when the request failed.
  error = ImageBitmap.imageResource(R.drawable.error)
)

imageModel에는 String, Uri, HttpUrl, File, DrawableRes, Drawable, Bitmap 타입을 사용하실 수 있습니다. 이미지 로드를 위해서 위의 예시에서 보여드린 모든 인자가 필요한 것은 아니기 때문에, 상황에 맞도록 사용자 정의하시는 것을 권장 드립니다.

추가적인 참고 자료가 필요하신 경우는 Landscapist-Coil을 참조해 주시길 바랍니다.

Fresco

Fresco를 포함하기 위해서는 아래의 의존성을 build.gradle 파일에 추가해 주셔야 합니다.

dependencies {
    implementation "com.github.skydoves:landscapist-fresco:1.4.7"
}

Fresco의 경우에는 의존성을 추가하신 후 파이프라인 세팅이 필요합니다. 먼저, 아래의 예시와 같이 ImagePipelineConfig를 Application 클레스에서 초기화 해야합니다.

class App : Application() {

  override fun onCreate() {
    super.onCreate()

    val pipelineConfig =
      OkHttpImagePipelineConfigFactory
        .newBuilder(this, OkHttpClient.Builder().build())
        .setDiskCacheEnabled(true)
        .setDownsampleEnabled(true)
        .setResizeAndRotateEnabledForNetwork(true)
        .build()

    Fresco.initialize(this, pipelineConfig)
  }
}

다음으로, 아래 예시와 같이 FrescoImage Composable 함수를 사용해서 네트워크 이미지를 로드하실 수 있습니다.

FrescoImage(
  imageUrl = stringImageUrl,
  // Crop, Fit, Inside, FillHeight, FillWidth, None
  contentScale = ContentScale.Crop,
  // shows an image with a circular revealed animation.
  circularReveal = CircularReveal(duration = 250),
  // shows a placeholder ImageBitmap when loading.
  placeHolder = ImageBitmap.imageResource(R.drawable.placeholder),
  // shows an error ImageBitmap when the request failed.
  error = ImageBitmap.imageResource(R.drawable.error)
)

FrescoImage의 경우는 imageUrlString 타입만을 사용하실 수 있습니다.

추가적인 참고 자료가 필요하신 경우는 Landscapist-Fresco을 참조해 주시길 바랍니다.

Conclusion

이번 포스트에서는 차세대 UI 툴킷인 Jetpack Compose와 오픈소스 라이브러리 landscapist에 대하여 살펴보았습니다.

Jetpack Compose가 등장한 이후로 Jetpack Compose를 위한 새로운 솔루션들이 지속적으로 탄생하고 있으며 landscapist도 그중 하나입니다. Jetpack Compose는 매우 유망한 UI 툴킷이지만 아직은 우리가 풀어야 할 숙제가 적지 않습니다. 따라서 앞으로도 현업의 개발자분들께 많은 도움이 될 수 있는 솔루션을 고안하고 지속적으로 발전시켜 나가고자 합니다.

landscapist의 사용법에 대해 자세히 다룬 포스트를 보고 싶으시다면 Loading images for Jetpack Compose using Glide, Coil, and Fresco를 참고해 주시길 바랍니다.

즐거운 코딩 되시길 바랍니다!

작성자 엄재웅 (skydoves)

profile
http://github.com/skydoves

1개의 댓글

comment-user-thumbnail
2022년 2월 9일

좋은 정보 감사합니다 ^^

답글 달기