[Android] - Jetpack Compose Recyclerview : Lazy Column (Part 2- ft.Coil)

김민주·2022년 7월 22일
0

Jetpack-compose

목록 보기
2/2
post-thumbnail

배경

이전 시리즈에서는 이미지를 drawable 폴더에 저장한 후에, 해당 파일에서 이미지를 꺼내와서 이미지를 보여줬습니다.

하지만 이미지를 프로젝트 폴더 내부에 저장해놓고 사용하는 것이 아니라 백엔드 혹은 클라우드로부터 받아서 이미지를 뿌리는 경우도 많습니다.

따라서 이번에는 인터넷을 통해 이미지 주소로 이미지 파일을 가져와 뿌려주는 방식으로 Recyclerview를 보여주는 과정을 보여드리도록 하겠습니다.

Image Loader 라이브러리

google에 android image loader로 검색하면 여러가지 image loader library를 보실 수 있습니다.

그런데 왜 인터넷을 통해 image를 받아올 때 image loader library를 사용해야할까요?
왜냐햐면 image loading에서 개발자가 고려해야하는 것들이 너무 많기 때문입니다.

안드로이드는 앱 내에서 사용할 수 있는 heap 메모리가 정해져있습니다. Out of memory가 되면 앱은 버티지 못하고 죽습니다. 이를 막기 위해 image loading 할때 개발자는 out of memory, slow loading, bitmap caching, memory caching, disk caching, garbage collector 이슈 등을 고려해야합니다.

이러한 고려사항 하나하나 체크하기 힘드니까 라이브러리에게 위임해 부담을 줄인 것입니다.

유명한 Image Loader 라이브러리에는 Glide, Picasso, Coil, Fresco 등이 있습니다. 그 중 오늘 우리가 사용할 라이브러리는 제목에서 보셨듯이 Coil입니다.

Coil

CoilCoroutine Image Loader의 약자로, Kotlin Coroutine(코루틴)으로 만들어진 Android backend image loading 라이브러리입니다.

장점

  • 빠르다 : memory & disk caching, 메모리 이미지 downsampling, 일시정지/취소의 자동화 등 수많은 최적화 작업을 수행하므로 처리 속도가 빠릅니다.
  • 가볍다 : Picasso, Glide, Fresco에 비해 훨씬 가볍습니다.
  • 사용하기 쉽다 : 간단함과 최소한의 boilerplate를 위해 Kotlin 기능을 활용하였기에 사용하기 쉽습니다.
  • 현대적이다 : Kotlin으로 개발되었으며, Coroutines, OkHttp, Okio, AndroidX Lifecycles에서 최신 라이브러리를 사용합니다.

Android Jetpack에서 Coil 라이브러리를 사용하는 가장 큰 이유는 마지막 장점 때문입니다.

다시 말해, Coil이 Jetpack compose를 지원하기 때문입니다!
(android developer 공식 사이트에서도 jetpack compose를 만들 때 Coil을 사용하는 것을 보실 수 있습니다.)

이제 기존 프로젝트에 Coil을 사용하는 방법을 설명하도록 하겠습니다.

CODE

0. 초기 세팅

기존 프로젝트에서 build.gradle(:app) 파일에 들어가 라이브러리를 추가함으로써 Coil을 다운받아 주세요.

dependencies {
	...
	implementation "io.coil-kt:coil-compose:2.1.0"
}

참고로 Coil 버전은 Coil github 페이지에서 확인해주세요!

그리고 사진을 url로 받아올 것이기 때문에 internet 권한을 허용해줘야합니다.
AndroidManifest.xml 파일에 들어가 다음을 추가해주세요 :)

<uses-permission android:name="android.permission.INTERNET" />

이제 초기 세팅이 끝났습니다! 본격적으로 코드를 작성해봅시다 :)

1. 데이터 형식 및 데이터 초기화 수정

기존 Puppy data class는 image: Int 형태로 파일을 저장하고 있었습니다. 따라서 url 저장을 위해 image: String 으로 데이터 형식을 바꿔주는 작업이 필요합니다.

data class Puppy(
    val name: String,
    val image: String,
    val content: String
)

이렇게 바꿔주면 되겠죠?

그 다음, 초기화된 데이터를 수정해야합니다. DataProvider 파일에 들어가 puppyList를 다음과 같이 수정해주세요. 저는 기존 사이트를 그대로 썼고, 이미지 링크 주소 복사 붙여넣기하여 사용했습니다.

object DataProvider {
       val puppyList = listOf(
        Puppy("코코", "https://images.pexels.com/photos/1108099/pexels-photo-1108099.jpeg?cs=srgb&dl=pexels-chevanon-photography-1108099.jpg&fm=jpg", "코코코코코 코 코코코 입!"),
        Puppy("보리", "https://images.pexels.com/photos/39317/chihuahua-dog-puppy-cute-39317.jpeg?cs=srgb&dl=pexels-pixabay-39317.jpg&fm=jpg", "보리 보리 쌀"),
        Puppy("초코", "https://images.pexels.com/photos/2023384/pexels-photo-2023384.jpeg?cs=srgb&dl=pexels-dominika-roseclay-2023384.jpg&fm=jpg", "초코송이 먹고싶당"),
        Puppy("콩이", "https://images.pexels.com/photos/248307/pexels-photo-248307.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1", "나는 콩을 안좋아하지만 콩이는 좋아!"),
        Puppy("사랑이", "https://images.pexels.com/photos/1805164/pexels-photo-1805164.jpeg?cs=srgb&dl=pexels-valeria-boltneva-1805164.jpg&fm=jpg", "사랑이 덕분에 집에 사랑이 가득~"),
        Puppy("달이", "https://images.pexels.com/photos/1346086/pexels-photo-1346086.jpeg?cs=srgb&dl=pexels-brett-sayles-1346086.jpg&fm=jpg", "달 달 무슨 달 쟁반같이 둥근 달"),
        Puppy("별이", "https://images.pexels.com/photos/2523934/pexels-photo-2523934.jpeg?cs=srgb&dl=pexels-denniz-futalan-2523934.jpg&fm=jpg", "별.. 별.. 별.."),
        Puppy("해피", "https://images.pexels.com/photos/2664417/pexels-photo-2664417.jpeg?cs=srgb&dl=pexels-glenn-2664417.jpg&fm=jpg", "암 쏘 해피~~~~ "),
        Puppy("마루", "https://images.pexels.com/photos/33053/dog-young-dog-small-dog-maltese.jpg?cs=srgb&dl=pexels-pixabay-33053.jpg&fm=jpg", "마루야.. 가지마.."),
        Puppy("호랑이", "https://images.pexels.com/photos/3726314/pexels-photo-3726314.jpeg?cs=srgb&dl=pexels-julissa-helmuth-3726314.jpg&fm=jpg", "난 영어 이름도 있어. Kami."),
        Puppy("두리", "https://images.pexels.com/photos/3860306/pexels-photo-3860306.jpeg?auto=compress&cs=tinysrgb&w=600", "암 쏘 해피~~~~ "),
        Puppy("하나", "https://images.pexels.com/photos/3361722/pexels-photo-3361722.jpeg?auto=compress&cs=tinysrgb&w=600", "마루야.. 가지마.."),
        Puppy("곰이", "https://images.pexels.com/photos/1458925/pexels-photo-1458925.jpeg?auto=compress&cs=tinysrgb&w=600", "난 영어 이름도 있어. Kami.")
       )
}

2. Coil을 통해 이미지 로드해 뿌려주기

저희는 저희가 만든 PuppyImage 함수에서 Compose가 제공하는 Image 함수를 사용해 이미지를 뿌려주고 있었습니다. Image 함수를 Coil이 제공하는 AsyncImage 함수로 바꿔주도록 하겠습니다!

@Composable
fun PuppyImage(puppy: Puppy) {
    AsyncImage(
        model = puppy.image,
        contentDescription = null,
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .padding(8.dp)
            .size(84.dp)
            .clip(RoundedCornerShape(CornerSize(16.dp)))
    )
    
}

painter 인자 대신 model 인자를 썼고 데이터 형식이 바뀌었다는 것 빼고는 기존과 완전히 동일합니다!! 정말 쉽게 만들어놓은 라이브러리 같습니다
.☺

3. 완성

처음 보여드렸던 gif 화면이 완성되었습니다!🥳
인터넷을 통해 사진을 가져오기 때문에 로딩 시간이 걸립니다. lazy column은 view를 재사용하기 때문에 화면이 아래로 스크롤하여 새 화면이 보일 때 사진도 로딩됩니다.

다행히 이번 lazy column에서는 발생하지 않았지만, 한 화면 내에서도 사진 별 로딩 시간이 다르기 때문에 위에서부터 순차적으로 가져오지 않는 문제가 발생하기도 합니다.

이 부분은 다음 시리즈인 Part3에서 다루도록 하겠습니다!


더 자세히보기

완성 코드는 github에 올려놓았습니다. 확인하고 싶으신 분들은 아래를 클릭해주세요. 감사합니다 :)

🌼더 자세한 코드 보러가기


참고자료

https://coil-kt.github.io/coil/
https://developer.android.com/codelabs/jetpack-compose-layouts#5
https://velog.io/@jshme/Android-Hello-Out-Of-Memory

profile
즐거운 개발자 김민주입니다🙂

0개의 댓글