Coil — 개념, 핵심 용어 및 Android ImageLoader

저자: IT Sectr 게시일: 2026-05-05 읽는 시간: 9 분

Coil은 Kotlin으로 작성되고 코루틴을 기반으로 하는 Android용 이미지 로딩 라이브러리입니다. 공식 문서에 따르면, 이 라이브러리는 Memory Cache, Disk Cache 및 하드웨어 가속 변환을 지원합니다. Coil은 최소 APK 크기(약 150KB)와 Jetpack Compose와의 완벽한 호환성으로 두드러집니다.

핵심 사항

  • Coil은 Kotlin Coroutines와 Kotlin Serialization을 사용하는 Android용 이미지 로딩 라이브러리입니다.
  • ImageLoader는 요청, 캐싱 및 이미지 변환을 관리하는 중앙 구성 요소입니다.
  • Memory Cache는 즉시 액세스를 위해 디코딩된 비트맵 이미지를 RAM에 저장합니다.
  • Disk Cache는 오프라인 작업 및 트래픽 감소를 위해 압축 파일을 저장소에 저장합니다.
  • Jetpack Compose — 라이브러리는 선언형 UI를 위한 AsyncImage 및 SubcomposeAsyncImage를 지원합니다.

Coil이란?

Coil(Coroutine Image Loader)은 완전히 Kotlin으로 작성되고 비동기 작업에 코루틴을 사용하는 Android용 이미지 로딩 라이브러리입니다. 네트워크, 리소스, 파일 시스템 및 Content Provider에서 비트맵 이미지를 로드하기 위한 통합 API를 제공하며, 자동 다중 레벨 캐싱을 지원합니다.

Glide 및 Picasso와 달리 Coil은 콜백 체인 대신 Kotlin Coroutines를 사용하여 코드를 더 선형적이고 예측 가능하게 만듭니다. 모든 로딩 및 디코딩 작업은 Dispatchers.IO 디스패처를 통해 백그라운드 스레드에서 실행되며, 결과는 명시적 전환 없이 메인 스레드에 전달됩니다.

Coil은 변환(Round, Blur, Grayscale), 전환 애니메이션, SVG 및 GIF, 그리고 비표준 디스플레이를 위한 사용자 정의 Target을 지원합니다. Google I/O 2023에 따르면, Coil은 Glide와 함께 공식 Jetpack Compose 튜토리얼에서 권장됩니다.

  • APK 크기 — 약 150KB(Glide의 500KB 대비)
  • 최소 Android 버전 — API 21(Lollipop)
  • 종속성 — Kotlin Coroutines(내장)

Coil 작동 방식: ImageLoader 및 ImageRequest

ImageLoader는 Coil의 주요 구성 요소로, 로딩 요청 실행 및 캐시 관리를 담당합니다. 각 인스턴스는 MemoryCache, DiskCache, BitmapPool 및 코루틴 풀에 대한 참조를 보유합니다. 기본적으로 Coil.imageLoader(context)를 통해 생성된 싱글톤이 사용됩니다.

ImageRequest

ImageRequest는 단일 이미지 로딩 요청을 설명하는 객체입니다: 데이터 소스(URL, URI, Int 리소스), 대상 ImageView 또는 Target, 변환, 캐싱 설정 및 플레이스홀더. ImageRequest는 빌더를 통해 구성되며, 유연성과 가독성을 보장합니다.

kotlin
val request = ImageRequest.Builder(context)
    .data("https://example.com/image.jpg")
    .crossfade(true)
    .size(512, 512)
    .transformations(listOf(RoundedCornersTransformation(12f)))
    .memoryCachePolicy(CachePolicy.ENABLED)
    .diskCachePolicy(CachePolicy.ENABLED)
    .target(imageView)
    .build()

구성 후 ImageRequest는 enqueue 또는 execute를 통해 ImageLoader에 전달됩니다. enqueue 메서드는 코루틴을 시작하고 Disposable을 반환하여 화면을 떠날 때 로딩을 취소할 수 있습니다. execute 메서드는 Result를 직접 반환하는 suspend 함수입니다.

요청 실행 흐름

ImageLoader는 순차적으로 MemoryCache, DiskCache를 확인하고 둘 다 미스인 경우에만 HttpEngine을 통해 네트워크 요청을 실행합니다. 로딩 후 바이트는 대상 크기를 고려하여 Bitmap으로 디코딩되고, 변환이 적용되며, 결과는 두 캐시 모두에 저장되고 Target에 전달됩니다.

  • Memory Cache — 먼저 확인, 키는 URL + 매개변수
  • Disk Cache — 메모리 미스 시 확인, 키는 URL의 MD5
  • HttpEngine — 기본적으로 OkHttp, 구성 요소를 통해 사용자 정의 가능

Coil의 주요 구성 요소

Coil은 구성 요소 아키텍처를 기반으로 구축되었으며, 의존성 주입을 통해 모든 부분을 교체할 수 있습니다. 모든 구성 요소는 ImageLoaderFactory에 등록되고 빌더를 통해 ImageLoader 생성자에 전달됩니다.

ImageLoader

ImageLoader는 모든 로딩 작업의 진입점입니다. 각 인스턴스에는 코루틴 풀, BitmapPool, MemoryCache, DiskCache 및 인터셉터 목록이 포함됩니다. 기본적으로 하나의 전역 인스턴스가 생성되지만, 단위 테스트를 위해 격리된 캐시가 있는 별도의 인스턴스를 생성할 수 있습니다.

MemoryCache

MemoryCache는 LRU(Least Recently Used) 기반의 인메모리 캐시로, 디코딩된 Bitmap 객체를 저장합니다. 기본 최대 크기는 사용 가능한 애플리케이션 메모리의 25%이지만 32MB 미만이어서는 안 됩니다. 캐시 키는 URL + 크기 + 변환으로 구성되어 오래된 이미지 검색을 방지합니다.

DiskCache

DiskCache는 원시 데이터(JPEG, PNG, WebP) 및 디코딩된 메타데이터를 위한 파일 기반 캐시입니다. 애플리케이션의 캐시 디렉토리에 위치하며 제한을 초과할 때 자동 정리를 지원합니다. 디스크 작업은 디렉토리 및 최대 크기 구성을 갖춘 DiskCache.Builder를 통해 수행됩니다.

Coil의 캐싱 수준

Coil은 네트워크 요청을 최소화하고 이미지 표시를 가속화하는 다중 레벨 캐싱 전략을 구현합니다. 각 수준은 고유한 목적과 데이터 수명을 가지고 있습니다.

수준저장소 유형수명기본 크기
Memory CacheRAM의 BitmapLRU 제거까지힙의 25%, 32MB부터
Disk CacheJPEG/WebP 파일제한 초과까지250MB
Http CacheOkHttp 응답Cache-Control 헤더에 따름HTTP 클라이언트에 따라 다름

Memory Cache는 이미 디코딩된 Bitmap에 대한 즉각적인 액세스를 제공합니다. Disk Cache는 첫 번째 로드 후 네트워크 없이(오프라인 우선) 앱이 작동하도록 보장합니다. OkHttp 수준의 Http Cache는 ETag 및 If-Modified-Since를 사용한 조건부 요청을 처리합니다.

캐싱 정책은 CachePolicy를 통해 요청별로 구성되며 ENABLED, READ_ONLY, WRITE_ONLY, DISABLED의 세 가지 값이 있습니다. 예를 들어, 사용자 아바타의 경우 Memory Cache에 READ_ONLY를, Disk Cache에 ENABLED를 설정할 수 있습니다.

Kotlin에서 Coil 사용 예제

Coil은 애플리케이션 아키텍처에 따라 여러 통합 방법을 제공합니다. 작동하는 코드 예제와 함께 세 가지 주요 시나리오를 살펴보겠습니다.

확장 함수를 통한 ImageView 로딩

load는 ImageView의 확장 함수로, 한 줄로 이미지를 로드하는 가장 간단한 방법입니다. 이 함수는 URL, URI, Int 리소스 또는 File과 함께 람다 구성기를 통해 모든 선택적 매개변수를 허용합니다.

kotlin
imageView.load("https://example.com/photo.jpg") {
    crossfade(true)
    placeholder(R.drawable.placeholder)
    error(R.drawable.error)
    size(300, 300)
    transformations(CircleCropTransformation())
}

load 메서드는 Disposable을 반환하며, onDestroy에서 또는 View 재사용 시 취소할 수 있습니다. 이는 빠른 목록 스크롤 중 메모리 누수 및 불필요한 네트워크 요청을 방지합니다.

Jetpack Compose에서 사용

AsyncImage는 선언형 UI에서 이미지를 로드하기 위한 컴포저블 함수입니다. 모든 데이터 소스와 플레이스홀더, 오류, 성공의 세 가지 선택적 상태 매개변수를 허용합니다.

kotlin
@Composable
fun NetworkImage(url: String) {
    AsyncImage(
        model = url,
        contentDescription = "네트워크 이미지",
        placeholder = ColorPainter(Color.Gray),
        error = ColorPainter(Color.Red)
    )
}

SubcomposeAsyncImage는 콘텐츠 슬롯을 통해 로딩 중 표시를 사용자 정의할 수 있는 더 유연한 버전입니다. 스켈레톤(shimmer) 및 진행 표시줄에 유용합니다.

비표준 출력을 위한 사용자 정의 Target

ImageView 또는 AsyncImage가 적합하지 않은 경우 Bitmap을 허용하는 단일 onSuccess 메서드가 있는 Target을 구현할 수 있습니다. 이는 Notification, RemoteViews 또는 OpenGL 텍스처에 로드하는 데 사용됩니다.

kotlin
val target = object : BitmapTarget() {
    override fun onSuccess(result: Bitmap) {
        notificationRemoteView.setImageViewBitmap(R.id.icon, result)
    }
}

imageLoader.enqueue(
    ImageRequest.Builder(context)
        .data(url)
        .target(target)
        .build()
)

다른 라이브러리와 Coil 비교

이미지 로딩 라이브러리의 선택은 프로젝트 요구 사항에 따라 다릅니다. Coil은 Glide 및 Picasso와 경쟁하며, 각각 강점이 있습니다. 주요 특성 비교가 표에 나와 있습니다.

특성CoilGlidePicasso
언어Kotlin(100%)Java + KotlinJava
APK 크기~150KB~500KB~120KB
코루틴내장없음(콜백)없음(콜백)
Jetpack Compose기본 지원accompanist를 통해타사
GIF/WebP예(내장)예(내장)아니요
Google 권장예(I/O 2023)아니요

Kotlin 및 Jetpack Compose의 새로운 프로젝트의 경우, Coil은 추가 코루틴 종속성이 없고 크기가 최소이므로 자연스러운 선택이 됩니다. Glide는 애니메이션 및 비디오 미리보기가 있는 복잡한 시나리오에서 여전히 선호됩니다. Picasso는 기능 면에서 둘 다 뒤떨어지지만 단순성에서 우수합니다.

Android 프로젝트에서 Coil 설정

Android 프로젝트에 Coil을 추가하는 것은 Gradle 종속성을 통해 이루어집니다. 추가 후 라이브러리는 ContentProvider를 통해 자동으로 ImageLoader를 등록하므로 Application에서 수동 초기화가 필요하지 않습니다. 사용자 정의가 필요한 경우 빌더를 통해 사용자 정의 ImageLoader가 생성됩니다.

kotlin
// build.gradle.kts (app module)
dependencies {
    implementation("io.coil-kt:coil:2.6.0")
    // Jetpack Compose의 경우 추가:
    implementation("io.coil-kt:coil-compose:2.6.0")
    // SVG 지원의 경우:
    implementation("io.coil-kt:coil-svg:2.6.0")
    // GIF 지원의 경우:
    implementation("io.coil-kt:coil-gif:2.6.0")
}

ImageLoader를 사용자 정의하려면 ImageLoaderFactory가 사용됩니다 — Application.onCreate에서 생성되는 싱글톤입니다. 팩토리에서 캐시 제한, HTTP 클라이언트, 사용자 정의 디코더 및 로깅을 구성할 수 있습니다. 기본적으로 Coil은 준비된 연결 풀과 함께 OkHttp를 사용합니다.

kotlin
class App : Application(), ImageLoaderFactory {
    override fun newImageLoader(): ImageLoader {
        return ImageLoader.Builder(this)
            .memoryCache {
                MemoryCache.Builder()
                    .maxSizePercent(0.25)
                    .build()
            }
            .diskCache {
                DiskCache.Builder()
                    .directory(cacheDir.resolve("coil_cache"))
                    .maxSizeBytes(512 * 1024 * 1024)
                    .build()
            }
            .build()
    }
}

자주 묻는 질문

Coil이란 무엇이며 어떤 용도로 사용되나요?

Coil은 Kotlin으로 코루틴을 사용하여 작성된 Android용 이미지 로딩 라이브러리입니다. 네트워크, 리소스 또는 파일 시스템에서 비트맵 이미지를 비동기적으로 로드, 캐싱 및 표시하는 데 사용됩니다.

Coil과 Glide의 차이점은 무엇인가요?

Coil은 100% Kotlin으로 작성되었으며 Glide의 콜백 메커니즘 대신 코루틴을 사용합니다. Coil은 APK 크기가 더 작고(~150KB 대 ~500KB) AsyncImage를 통한 Jetpack Compose 기본 지원을 제공합니다.

Kotlin 프로젝트에 Coil을 어떻게 추가하나요?

build.gradle.kts에 종속성 io.coil-kt:coil:2.6.0을 추가하세요. Jetpack Compose의 경우 io.coil-kt:coil-compose:2.6.0도 추가하세요. 라이브러리는 ContentProvider를 통해 자동으로 ImageLoader를 등록합니다.

Coil은 어떤 이미지 형식을 지원하나요?

Coil은 JPEG, PNG, WebP, BMP, SVG(coil-svg 모듈을 통해) 및 GIF(coil-gif 모듈을 통해)를 지원합니다. AVIF 및 HEIF 형식은 Android 10+ 기기에서 사용자 정의 디코더를 통해 지원됩니다.

Coil에서 캐시를 구성하려면 어떻게 하나요?

캐시는 ImageLoader.Builder를 통해 구성됩니다: memoryCache는 힙의 백분율, diskCache는 경로와 바이트 제한을 지정합니다. 캐시 정책(ENABLED, DISABLED, READ_ONLY)은 CachePolicy를 통해 요청별로 구성됩니다.

요약

  • Coil은 완전한 코루틴 및 Jetpack Compose 지원을 갖춘 Kotlin용 이미지 로딩 라이브러리입니다.
  • ImageLoader는 Memory Cache와 Disk Cache의 두 가지 캐시 수준을 사용하여 요청, 캐싱 및 변환을 관리합니다.
  • AsyncImageSubcomposeAsyncImage는 플레이스홀더, 오류 및 성공 상태를 지원하는 Compose 통합을 제공합니다.
  • APK 크기 ~150KB는 Coil을 시장에서 가장 컴팩트한 이미지 로딩 라이브러리 중 하나로 만듭니다.
  • 변환(RoundedCorners, CircleCrop, Blur)은 라이브러리에 내장되어 있으며 하드웨어 가속과 함께 작동합니다.
  • Disk Cache는 구성 가능한 저장소 제한으로 이전에 로드된 이미지에 대한 오프라인 액세스를 제공합니다.
  • Coil은 Google 권장 공식 Jetpack Compose 가이드에 포함되어 현대 표준으로서의 위상을 확인합니다.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기