이미지 작업을 할 때는 주의하지 않으면 금방 성능 문제가 발생할 수 있습니다. 큰 비트맵으로 작업할 때 OutOfMemoryError가 발생하기가 매우 쉽습니다. 앱이 최상의 성능을 발휘하게 만들려면 다음 권장사항을 따르세요.
필요한 크기의 비트맵만 로드하기
대부분의 스마트폰에는 큰 이미지 파일을 생성하는 고해상도 카메라가 있습니다. 화면에 이미지를 표시하는 경우 이미지 해상도를 낮추거나 이미지 컨테이너 크기까지만 이미지를 로드해야 합니다. 필요보다 더 큰 이미지를 지속적으로 로드하면 GPU 캐시가 소진되어 UI 렌더링 성능이 저하될 수 있습니다.
이미지 로드 라이브러리를 사용하여 화면의 뷰 크기에 맞게 이미지를 축소합니다. 이렇게 하면 화면 로드 성능이 개선됩니다.
가능하면 비트맵 대신 벡터 사용하기
화면에 무언가를 시각적으로 표시할 때 벡터로 표현할 수 있는지 결정해야 합니다. 벡터 이미지는 다른 크기로 조정할 때 픽셀화되지 않으므로 비트맵보다 벡터 이미지를 사용하는 것이 좋습니다. 그러나 모든 것을 벡터로 표시할 수는 없습니다. 카메라로 촬영한 이미지는 벡터로 변환할 수 없습니다.
다양한 화면 크기에 맞는 대체 리소스 제공
앱과 함께 이미지를 제공하는 경우 기기 해상도에 따라 다양한 크기의 애셋을 제공하는 것이 좋습니다. 이렇게 하면 기기에서 앱의 다운로드 크기가 줄어들고 해상도가 낮은 기기에 더 낮은 해상도의 이미지가 로드되므로 성능이 개선됩니다. 다양한 기기 크기에 맞는 대체 비트맵을 제공하는 방법에 관한 자세한 내용은 대체 비트맵 문서를 확인하세요.
ImageBitmap을 사용할 때 그리기 전에 prepareToDraw 호출
ImageBitmap을 사용할 때 GPU에 텍스처를 업로드하는 프로세스를 시작하려면 실제로 그리기 전에 ImageBitmap#prepareToDraw()를 호출합니다. 그러면 GPU가 텍스처를 준비하고 화면에 시각 요소를 표시하는 성능을 향상할 수 있습니다. 대부분의 이미지 로드 라이브러리는 이러한 최적화를 이미 실행하지만 ImageBitmap 클래스를 직접 사용한다면 이 사항에 유의해야 합니다.
컴포저블에 Painter 대신 IntDrawableRes 또는 URL을 매개변수로 전달
이미지 처리의 복잡성으로 인해(예: Bitmaps의 equals 함수를 작성하는 데 드는 높은 계산 비용) Painter API는 안정적인 클래스로 명시하지 않습니다. 불안정한 클래스의 경우 데이터가 변경되었는지 컴파일러가 쉽게 추론할 수 없으므로 불필요한 리컴포지션으로 이어질 수 있습니다.
따라서 Painter를 매개변수로 전달하는 대신 URL 또는 드로어블 리소스 ID를 매개변수로서 컴포저블에 전달하는 것이 좋습니다.
// Prefer this:@ComposablefunMyImage(url:String){}// Over this:@ComposablefunMyImage(painter:Painter){}
비트맵을 필요한 기간보다 오래 메모리에 저장하지 않기
메모리에 로드하는 비트맵이 많을수록 기기의 메모리가 부족할 가능성이 커집니다. 예를 들어 화면에 대량의 이미지 컴포저블 목록을 로드하는 경우 큰 목록을 스크롤할 때 메모리가 확보되도록 LazyColumn 또는 LazyRow를 사용합니다.
대용량 이미지를 AAB/APK 파일로 패키징하지 않기
앱 다운로드 크기가 커지는 주요 원인 중 하나는 AAB 또는 APK 파일 내에 패키징된 그래픽 때문입니다. APK Analyzer 도구를 사용하여 필요한 이미지 파일보다 크게 패키징하지 않도록 합니다. 크기를 줄이거나
이미지를 서버에 두고 필요할 때만 다운로드하는 것이 좋습니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-08-21(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-08-21(UTC)"],[],[],null,["# Optimizing performance for images\n\nWorking with images can quickly introduce performance issues if you aren't\ncareful. You can quite easily run into an `OutOfMemoryError` when working\nwith large bitmaps. Follow these best practices to ensure your app performs at\nits best.\n\nOnly load the size of the bitmap you need\n-----------------------------------------\n\nMost smartphones have high resolution cameras that produce large image files. If\nyou're showing an image on screen, you must either reduce the resolution of the\nimage or only load the image up to the size of your image container. The\nconstant loading of larger than needed images can exhaust GPU caches, leading to\nless performant UI rendering.\n\nTo manage image sizes:\n\n- Scale down your image files to be as small as possible (without affecting output image).\n- Consider [converting your images to WEBP](/studio/write/convert-webp) format instead of JPEG or PNGs.\n- Supply smaller images for different screen resolutions (see [Tip #3](/develop/ui/compose/graphics/images/optimization#screen-sizes)),\n- Use an [image loading library](/develop/ui/compose/graphics/images/loading#load_an_image_from_the_internet), which scales down your image to fit the size of your view on screen. This can help improve the loading performance of your screen.\n\n| **Caution:** Using `painterResource` will **not** scale your image to the size of the Composable that is visible on screen. If you have a large image in a small Composable, be sure to use an image loading library which scales the image down for you to fit the bounds.\n\n#### Use vectors over bitmaps where possible\n\nWhen representing something visually on screen, you need to decide if it can be\nrepresented as a vector or not. Prefer vector images over bitmaps, as they\ndon't pixelate when you scale them to different sizes. However, not everything\ncan be represented as a vector - images taken with a camera can't be converted\ninto a vector.\n\n#### Supply alternative resources for different screen sizes\n\nIf you are shipping images with your app, consider supplying different sized\nassets for different device resolutions. This can help reduce the download size\nof your app on devices, and improve performance as it'll load up a lower\nresolution image on a lower resolution device. For more information on providing\nalternative bitmaps for different device sizes, [check out the alternative\nbitmap documentation](/training/multiscreen/screendensities#TaskProvideAltBmp).\n\n#### When using `ImageBitmap`, call `prepareToDraw` before drawing\n\nWhen using `ImageBitmap`, to start the process of uploading the texture to the\nGPU, call [`ImageBitmap#prepareToDraw()`](/reference/kotlin/androidx/compose/ui/graphics/ImageBitmap#prepareToDraw()) before actually drawing it. This\nhelps the GPU prepare the texture and improve the performance of showing a\nvisual on screen. Most image loading libraries already do this optimization, but\nif you are working with the `ImageBitmap` class yourself, it is something to\nkeep in mind.\n\n#### Prefer passing a `Int` `DrawableRes` or URL as parameters into your composable instead of `Painter`\n\nDue to the complexities of dealing with images (for example, writing an equals\nfunction for `Bitmaps` would be computationally expensive), the `Painter` API is\nexplicitly not marked as a [Stable](https://medium.com/androiddevelopers/jetpack-compose-stability-explained-79c10db270c8) class. Unstable classes can\nlead to unnecessary recompositions because the compiler cannot easily infer if\nthe data has changed.\n\nTherefore, it is preferable to pass a URL or drawable resource ID as parameters\nto your composable, instead of passing a `Painter` as a parameter. \n\n // Prefer this:\n @Composable\n fun MyImage(url: String) {\n\n }\n // Over this:\n @Composable\n fun MyImage(painter: Painter) {\n\n }\n\nDon't store a bitmap in memory longer than you need it\n------------------------------------------------------\n\nThe more bitmaps you load into memory, the more likely it is that you could run\nout of memory on the device. For instance, if loading a large list of Image\ncomposables on screen, use `LazyColumn` or `LazyRow` to ensure that memory is\nfreed up when scrolling a large list.\n\nDon't package large images with your AAB/APK file\n-------------------------------------------------\n\nOne of the top causes for large app download size is due to graphics that are\npackaged inside the AAB or APK file. Use the [APK analyzer](/studio/debug/apk-analyzer) tool to ensure\nthat you aren't packaging larger than required image files. Reduce the sizes or\nconsider placing the images on a server and only downloading them when required.\n\nRecommended for you\n-------------------\n\n- Note: link text is displayed when JavaScript is off\n- [ImageBitmap vs ImageVector {:#bitmap-vs-vector}](/develop/ui/compose/graphics/images/compare)\n- [Save UI state in Compose](/develop/ui/compose/state-saving)\n- [Jetpack Compose Phases](/develop/ui/compose/phases)"]]