Android/Jetpack Compose

AsyncImage를 Preview에서 보는 3가지 방법

chattymin 2025. 2. 16. 22:38
728x90

 

Android 개발을 하다보면 URL 이미지를 화면에 나타내기 위해 라이브러리들을 주로 사용할 것이다. 

Glide, Coil 등등 다양한 라이브러리가 존재하고 이를 사용하다보면 Compose에서 불편한게 딱 하나 있다.

 

 

Preview에서 이미지 영역이 안나온다.

물론 이미지를 제외한 나머지 영역의 크기를 보고 대충 이미지가 저기 안에 들어가겠구나~ 생각할 수는 있지만, 앱을 실행하지 않고도 Preview에서 정확하게 테스트 하고 싶은 마음이 든다.

 

그렇기에 이를 해결하기위해 적용해본 3가지 방법을 공유하고자 한다.

 

제가 적용한 모든 방법은 Coil 기준으로 작성되었습니다.
아마... Glide도 될껄요...?

 

 

1. PlaceHolder

Coil을 사용할 때 사용되는 AsyncImage의 속성을 사용했다.

 

다양한 속성 중에서 placeholder를 주목해보자.

    AsyncImage(
        model = ImageRequest.Builder(LocalContext.current)
            .data(url)
            .crossfade(true)
            .build(),
        contentDescription = contentDescription,
        contentScale = contentScale,
        placeholder = painterResource(id = R.drawable.img_error),
        modifier = modifier
    )

 

placeHolder를 넣게 된다면 이미지가 뜨기 전 placeHolder가 먼저 떠있다가 url에 해당하는 이미지가 나오게 된다.

그래서 아래처럼 preview에 placeholder 이미지가 떠있게 된다.

어차피 preview라 아무이미지 넣었어요 ㅎ.ㅎ...

 

이 방법의 제일 큰 문제는 실제 결과물에도 영향을 끼친다는 것이다.

아래 실제 영상을 보게 되면 이미지가 뜨기 전 잠깐 placeholder가 나오게 된다.

 

 

물론 실제 운영을 할 때에 placeHolder를 사용한다면 문제가 없다. 

하지만 그게 아닐 경우에는 UI적으로 큰 문제가 될 수 있다.

 

그래서 찾은게 두번째 방법이다.

 

 

2. Coil3

* coil 공식 페이지 : https://coil-kt.github.io/coil/compose/

 

Compose - Coil

Compose To add support for Compose UI, import the extension library: implementation("io.coil-kt.coil3:coil-compose:3.1.0") Then use the AsyncImage composable to load and display an image: AsyncImage( model = "https://example.com/image.jpg", contentDescript

coil-kt.github.io

 

내부에 있는 코드를 보다보면 아래쪽에 Preview라는것이 보인다.

Preview에서 Image를 보여주기 위해서는 아래처럼 코드를 작성하면 된다.

이유는 모르겠지만, 공식문서에서는 ColorImage를 사용하라 하지만 오류가 발생해서 FakeImage로 구현했다.

val previewHandler = AsyncImagePreviewHandler {
	FakeImage(color = 0xFFE0E0E0.toInt())
}
        
CompositionLocalProvider(LocalAsyncImagePreviewHandler provides previewHandler) {
    AsyncImage(
        model = "https://example.com/image.jpg",
        contentDescription = null,
    )
}

이 기능들을 이용하기 위해서는 test와 관련된 dependency를 추가해줘야 한다.

coil3-test = { group = "io.coil-kt.coil3", name = "coil-test", version.ref = "coil3" }

 

 

다시 코드 설명으로 돌아가면 CompositionLocalProvider로 Handler를 아래로 넘겨준다.

그렇게 되면 AsyncImage 내부에서 알아서 Preview에서는 FakeImage를 띄워준다.

 

이 방법을 사용하면 실제 프로덕트에는 전혀 영향이 가지 않는 방법으로 Preview에서의 AsyncImage를 볼 수 있다.

 

 

하지만 제일 큰 단점은 AsyncImage가 존재하는 Preview마다 Handler를 만들고, CompositionLocalProvider를 적어줘야 한다.

즉, 보일러플레이트가 과하게 발생된다.

 

 

그래서 이를 해결하고자 마지막 방법을 찾았다.

 

 

3. LocalInspectionMode.current

https://developer.android.com/develop/ui/compose/tooling/previews?hl=ko

 

컴포저블 미리보기로 UI 미리보기  |  Jetpack Compose  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 컴포저블 미리보기로 UI 미리보기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 컴포저블은 함수에

developer.android.com


이 값을 활용한다면 Preview인지 아닌지 확인할 수 있다.

그래서 공식문서의 예시를 본다면 아래처럼 작성할 수 있다.

@Composable
fun GreetingScreen(name: String) {
    if (LocalInspectionMode.current) {
        // Show this text in a preview window:
        Text("Hello preview user!")
    } else {
        // Show this text in the app:
        Text("Hello $name!")
    }
}

 

 

이를 활용하여 아래처럼 UrlImage라는 컴포넌트를 만들었다

@Composable
fun UrlImage(
    url: String,
    modifier: Modifier = Modifier,
    contentScale: ContentScale = ContentScale.Fit,
    contentDescription: String? = null,
) {
    if (LocalInspectionMode.current) {
        Image(
            imageVector = ImageVector.vectorResource(R.drawable.img_fake_red),
            contentDescription = contentDescription,
            contentScale = contentScale,
            modifier = modifier
        )
    } else {
        AsyncImage(
            model = url,
            contentDescription = contentDescription,
            contentScale = contentScale,
            modifier = modifier
        )
    }
}

 

Preview에 해당 컴포넌트를 호출하기만 해도 이렇게 이미지가 잘 나온다.

테스트라서 빨간색 이미지 넣어뒀어요~

 

 

이를 활용해서 다른 컴포넌트를 구현하고 Preview에서 확실하게 AsyncImage가 담당하는 영역을 확인할 수 있었다.

 

 

 

네트워크 이미지도 이제 Preview로 확인하면서 개발하자~

728x90