Coil 간단하게 알아보기

이윤설·2025년 2월 27일
0

안드로이드 연구소

목록 보기
26/33

Coil 소개

Coil은 "Coroutine Image Loader"의 약자로, Instacart에서 개발한 Android용 이미지 로딩 라이브러리다. 주요 특징은 다음과 같다.

  • Kotlin 기반: 코틀린 코루틴으로 구현되어 비동기 작업이 간결하고 효율적
  • 가벼운 크기: 최소한의 메서드 수와 작은 바이너리 크기로 앱 크기 증가 최소화
  • 빠른 속도: OkHttp, Okio, MemoryCache, 비트맵 풀링 등 최신 기술 활용
  • 사용 편의성: 간결한 API로 빠르게 구현 가능
  • 모던 이미지 형식 지원: WebP, HEIF, SVG, GIF, JPEG 등 지원
  • Jetpack Compose 지원: Compose UI와 원활하게 통합

이제 본격적으로 Coil의 사용법을 알아보자.

설치 방법

Coil을 사용하기 위해 app 모듈의 build.gradle 파일에 다음 의존성을 추가한다:

// 기본 Coil
implementation("io.coil-kt:coil:2.5.0")

// Jetpack Compose 지원
implementation("io.coil-kt:coil-compose:2.5.0")

// GIF 지원
implementation("io.coil-kt:coil-gif:2.5.0")

// SVG 지원
implementation("io.coil-kt:coil-svg:2.5.0")

// 비디오 프레임 지원
implementation("io.coil-kt:coil-video:2.5.0")

기본 사용법

Coil의 가장 기본적인 사용법은 매우 간단하다:

// 이미지 로딩 (View 시스템)
imageView.load("https://example.com/image.jpg")

이것만으로도 이미지 로딩, 캐싱, 메모리 관리가 자동으로 이루어진다. 더 많은 옵션을 지정하려면 다음과 같이 할 수 있다.

imageView.load("https://example.com/image.jpg") {
    crossfade(true)  // 크로스페이드 효과 적용
    placeholder(R.drawable.placeholder)  // 로딩 중 표시할 이미지
    error(R.drawable.error_image)  // 에러 발생 시 표시할 이미지
    transformations(CircleCropTransformation())  // 원형으로 자르기
    size(ViewSizeResolver(imageView))  // 이미지 크기 지정
}

다양한 데이터 소스를 지원한다.

// URL 문자열
imageView.load("https://example.com/image.jpg")

// Uri 객체
imageView.load(Uri.parse("https://example.com/image.jpg"))

// 파일 객체
imageView.load(File("/path/to/image.jpg"))

// 리소스 ID
imageView.load(R.drawable.image)

// Drawable 객체
imageView.load(drawable)

// 비트맵 객체
imageView.load(bitmap)

이미지 변환 및 효과

Coil은 다양한 이미지 변환(transformations)을 지원한다.

imageView.load("https://example.com/image.jpg") {
    // 원형으로 자르기
    transformations(CircleCropTransformation())
    
    // 둥근 모서리 적용
    transformations(RoundedCornersTransformation(20f))
    
    // 흑백 효과
    transformations(GrayscaleTransformation())
    
    // 블러 효과
    transformations(BlurTransformation(context, 10f, 3f))
    
    // 여러 변환 함께 적용
    transformations(
        CircleCropTransformation(),
        GrayscaleTransformation()
    )
}

커스텀 변환도 만들 수 있다:

class MyCustomTransformation : Transformation {
    override val cacheKey: String = "my_custom_transformation"
    
    override suspend fun transform(input: Bitmap, size: Size): Bitmap {
        // 이미지 변환 로직 구현
        return transformedBitmap
    }
}

// 사용
imageView.load("https://example.com/image.jpg") {
    transformations(MyCustomTransformation())
}

이미지 로딩 상태 처리

Coil은 이미지 로딩 상태를 세밀하게 제어할 수 있다.

val request = ImageRequest.Builder(context)
    .data("https://example.com/image.jpg")
    .target(imageView)
    .listener(
        onStart = {
            // 로딩 시작 시 호출
            progressBar.visibility = View.VISIBLE
        },
        onSuccess = { _, result ->
            // 성공 시 호출
            progressBar.visibility = View.GONE
            Toast.makeText(context, "이미지 로드 성공", Toast.LENGTH_SHORT).show()
        },
        onError = { _, error ->
            // 에러 발생 시 호출
            progressBar.visibility = View.GONE
            Toast.makeText(context, "이미지 로드 실패: ${error.throwable}", Toast.LENGTH_SHORT).show()
        }
    )
    .build()

// 요청 실행
val imageLoader = ImageLoader(context)
imageLoader.enqueue(request)

이미지 로딩을 코루틴과 함께 사용할 수도 있다:

// 코루틴 내에서 이미지 로딩 (suspend 함수)
lifecycleScope.launch {
    try {
        val result = imageLoader.execute(request)
        // 성공적으로 로드된 DrawableResult 사용
        val drawable = result.drawable
    } catch (e: Exception) {
        // 에러 처리
    }
}

메모리 및 디스크 캐싱

Coil은 기본적으로 메모리와 디스크 캐싱을 지원한다.
필요에 따라 캐싱 설정을 커스터마이즈할 수 있다.

// 커스텀 ImageLoader 구성
val imageLoader = ImageLoader.Builder(context)
    .memoryCache {
        // 메모리 캐시 크기를 사용 가능한 메모리의 25%로 설정
        MemoryCache.Builder(context)
            .maxSizePercent(0.25)
            .build()
    }
    .diskCache {
        // 디스크 캐시 설정
        DiskCache.Builder()
            .directory(context.filesDir.resolve("image_cache"))
            .maxSizeBytes(512 * 1024 * 1024) // 512MB
            .build()
    }
    .build()

// 기본 ImageLoader 설정
Coil.setImageLoader(imageLoader)

Jetpack Compose에서 사용하기

Coil은 Jetpack Compose와 원활하게 통합된다.

@Composable
fun ImageCard(imageUrl: String) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        elevation = 8.dp
    ) {
        // 기본 사용법
        AsyncImage(
            model = imageUrl,
            contentDescription = "이미지 설명",
            modifier = Modifier.fillMaxWidth(),
            contentScale = ContentScale.Crop
        )
    }
}

Glide, Picasso와 비교

Coil, Glide, Picasso는 모두 인기 있는 Android 이미지 로딩 라이브러리다. 각각의 특징을 비교해보자~!

특징CoilGlidePicasso
언어KotlinJavaJava
비동기 처리Coroutines자체 구현자체 구현
바이너리 크기~2MB~4MB~1.5MB
메모리 효율매우 좋음좋음보통
API 편의성매우 좋음좋음좋음
Compose 지원네이티브서드파티서드파티
커뮤니티성장 중매우 활발활발

Coil의 장점:

  • Kotlin 친화적인 API
  • Coroutines 기반 비동기 처리
  • 더 적은 보일러플레이트 코드로 구현 가능
  • Jetpack Compose와의 원활한 통합
  • OkHttp 기반으로 네트워크 요청 공유

Glide의 장점:

  • 성숙한 라이브러리로 광범위한 기능
  • 방대한 커뮤니티와 풍부한 문서
  • 다양한 변환 및 플러그인

Picasso의 장점:

  • 작은 바이너리 크기
  • 간결한 API
  • 오래된 기기에서도 안정적

선택 기준:

  • Kotlin과 Jetpack Compose를 사용한다면 Coil
  • 다양한 기능과 성숙도가 필요하다면 Glide
  • 최소한의 크기와 단순함이 필요하다면 Picasso

결론

Coil은 Kotlin과 코루틴을 활용한 현대적인 Android 이미지 로딩 라이브러리다.
간결한 API, 효율적인 메모리 관리, Jetpack Compose와의 통합 등 다양한 장점을 제공한다.
특히 Kotlin을 기본 언어로 사용하는 최신 Android 프로젝트에 가장 적합하다.

주요 이점을 요약하면 다음과 같다.

  • 코틀린 코루틴 네이티브 지원으로 비동기 작업 간소화
  • 선언적이고 간결한 API로 개발 시간 단축
  • 메모리 및 디스크 캐싱으로 성능 최적화
  • 다양한 이미지 변환 및 효과 지원
  • Jetpack Compose와의 원활한 통합

참고: https://coil-kt.github.io/coil/compose/

profile
화려한 외면이 아닌 단단한 내면

0개의 댓글

관련 채용 정보