일부 앱 사용자는 인터넷에 간헐적으로 액세스하거나 기기에 다운로드할 수 있는 정보의 양이 제한되어 있습니다. 앱이 다운로드해야 하는 데이터의 양을 줄이면 사용자가 앱과 더 자주 상호작용하도록 할 수 있습니다.
다운로드를 줄이는 가장 기본적인 방법은 필요한 것만 다운로드하는 것입니다. 데이터 관점에서 이것은 매개변수(예: 마지막 업데이트 시간)를 사용하여 반환되는 데이터를 제한하는 쿼리 기준을 지정할 수 있는 REST API 구현을 의미합니다.
마찬가지로 이미지를 다운로드할 때 클라이언트 측에서 이미지 전체를 다운로드하여 크기를 줄이는 것보다 서버 측에서 이미지의 크기를 줄이는 것이 좋습니다.
HTTP 응답 캐시
또 다른 중요한 기술은 중복된 데이터를 다운로드하지 않는 것입니다. 캐싱을 사용하면 동일한 데이터를 반복적으로 다운로드할 가능성을 줄일 수 있습니다. 앱의 데이터와 리소스를 캐시하여 앱이 참조해야 할 정보의 로컬 복사본을 만듭니다. 앱이 짧은 기간에 동일한 정보를 여러 번 액세스해야 한다면 그 정보를 캐시에 한 번만 다운로드하면 됩니다.
다운로드할 전체 데이터양을 줄이려면 최대한 많이 캐시하는 것이 중요합니다. 원본 크기의 이미지와 같은 주문형 다운로드를 비롯한 정적 리소스는 항상 최대한 오래 캐시하세요. 주문형 캐시를 정기적으로 플러시하여 캐시 크기를 관리할 수 있도록 주문형 리소스는 별도로 저장해야 합니다.
캐싱 때문에 앱에 오래된 데이터가 표시되지 않게 하려면 ETag 및 Last-Modified 헤더와 같은 적절한 HTTP 상태 코드 및 헤더를 사용하세요. 이렇게 하면 연결된 콘텐츠를 새로고침할 시기를 결정할 수 있습니다. 예를 들면 다음과 같습니다.
Kotlin
// url represents the website containing the content to place into the cache.valconn:HttpsURLConnection=url.openConnection()asHttpsURLConnectionvalcurrentTime:Long=System.currentTimeMillis()vallastModified:Long=conn.getHeaderFieldDate("Last-Modified",currentTime)// lastUpdateTime represents when the cache was last updated.if(lastModified < lastUpdateTime){// Skip update}else{// Parse updatelastUpdateTime=lastModified}
자바
// url represents the website containing the content to place into the cache.HttpsURLConnectionconn=(HttpsURLConnection)url.openConnection();longcurrentTime=System.currentTimeMillis();longlastModified=conn.getHeaderFieldDate("Last-Modified",currentTime);// lastUpdateTime represents when the cache was last updated.if(lastModified < lastUpdateTime){// Skip update}else{// Parse updatelastUpdateTime=lastModified;}
이러한 상태 코드와 헤더를 자동으로 준수하도록 일부 네트워킹 라이브러리를 구성할 수 있습니다. 예를 들어 OkHttp를 사용하는 경우 클라이언트의 캐시 디렉터리와 캐시 크기를 구성하면 라이브러리에서 HTTP 캐싱을 사용할 수 있습니다. 다음 코드 샘플을 참고하세요.
캐시가 구성되면 완전히 캐시된 HTTP 요청은 로컬 저장소에서 직접 제공되며 네트워크 연결을 하지 않아도 됩니다.
조건부로 캐시된 응답은 서버에서 최신 상태인지 확인하여 다운로드와 관련된 대역폭 비용을 없앨 수 있습니다. 캐시되지 않은 응답은 이후 발생할 요청을 위해 응답 캐시에 저장됩니다.
더 정교한 캐싱 접근 방식을 사용하려면 저장소 디자인 패턴을 고려하세요. 여기에는 특정 데이터 또는 리소스에 관해 API 추상화를 제공하는 저장소라는 맞춤 클래스를 만드는 작업이 포함됩니다. 저장소는 처음에는 원격 웹 서비스와 같은 다양한 소스에서 데이터를 가져올 수 있지만 후속 호출에서는 호출자에게 데이터의 캐시된 버전을 제공합니다. 이 간접층을 사용하면 앱에 특화된 강력한 캐싱 전략을 제공할 수 있습니다. 앱 내에서 저장소 패턴을 사용하는 방법에 관한 자세한 내용은 앱 아키텍처 가이드를 참고하세요.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 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,["# Avoid unoptimized downloads\n\nSome of your app's users have intermittent access to the internet or have limits\non the amount of information they can download onto their devices. You can\nencourage users to interact with your app more often by reducing the amount of\ndata that your app needs to download.\n\nThe most fundamental way to reduce your downloads is to download only what you\nneed. In terms of data, that means implementing REST APIs that allow you to\nspecify query criteria that limit the returned data by using parameters such as\nthe time of your last update.\n\nSimilarly, when downloading images, it's good practice to reduce the size of\nimages server-side, rather than downloading full-sized images that are reduced\non the client.\n\nCache HTTP responses\n--------------------\n\nAnother important technique is to avoid downloading duplicate data. You can\nreduce the likelihood of downloading the same piece of data repeatedly by using\ncaching. By caching your app's data and resources, you create a local copy of\nthe information that your app needs to reference. If your app needs to access\nthe same piece of information multiple times over a short time period, you need\nto download it into the cache only once.\n\nIt's important to cache as aggressively as possible in order to reduce the total\namount of data that you download. Always cache static resources, including\non-demand downloads such as full-size images, for as long as reasonably\npossible. On-demand resources should be stored separately to enable you to\nregularly flush your on-demand cache to manage its size.\n\nTo ensure that your caching doesn't result in your app displaying stale data,\nuse the appropriate [HTTP status codes and\nheaders](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#validating_cached_responses_with_etags),\nsuch as the\n[`ETag`](https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.2)\nand\n[`Last-Modified`](https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.1)\nheaders. This allows you to determine when the associated content should be\nrefreshed. For example: \n\n### Kotlin\n\n```kotlin\n// url represents the website containing the content to place into the cache.\nval conn: HttpsURLConnection = url.openConnection() as HttpsURLConnection\nval currentTime: Long = System.currentTimeMillis()\nval lastModified: Long = conn.getHeaderFieldDate(\"Last-Modified\", currentTime)\n\n// lastUpdateTime represents when the cache was last updated.\nif (lastModified \u003c lastUpdateTime) {\n // Skip update\n} else {\n // Parse update\n lastUpdateTime = lastModified\n}\n```\n\n### Java\n\n```java\n// url represents the website containing the content to place into the cache.\nHttpsURLConnection conn = (HttpsURLConnection) url.openConnection();\nlong currentTime = System.currentTimeMillis();\nlong lastModified = conn.getHeaderFieldDate(\"Last-Modified\", currentTime);\n\n// lastUpdateTime represents when the cache was last updated.\nif (lastModified \u003c lastUpdateTime) {\n // Skip update\n} else {\n // Parse update\n lastUpdateTime = lastModified;\n}\n```\n\nYou can configure some networking libraries to respect these status codes and\nheaders automatically. When using\n[OkHttp](https://square.github.io/okhttp/), for example, configuring\na cache directory and cache size for the client will enable the library to use\nHTTP caching, as shown in the following code sample: \n\n### Kotlin\n\n```kotlin\nval cacheDir = Context.getCacheDir()\nval cacheSize = 10L * 1024L * 1024L // 10 MiB\nval client: OkHttpClient = OkHttpClient.Builder()\n .cache(Cache(cacheDir, cacheSize))\n .build()\n```\n\n### Java\n\n```java\nFile cacheDir = Context.getCacheDir();\nlong cacheSize = 10L * 1024L * 1024L; // 10 MiB\nOkHttpClient client = new OkHttpClient.Builder()\n .cache(new Cache(cacheDir, cacheSize))\n .build();\n```\n\nWith the cache configured, you can serve fully-cached HTTP requests directly\nfrom local storage, eliminating the need to open a network connection.\nConditionally-cached responses can validate their freshness from the server,\neliminating the bandwidth cost associated with the download. Uncached responses\nget stored in the response cache for future requests.\n\nYou can cache non-sensitive data in the unmanaged external cache directory by\nusing\n[`Context.getExternalCacheDir()`](/reference/android/content/Context#getExternalCacheDir()).\nAlternatively, you can cache data in the managed, secure application cache by\nusing\n[`Context.getCacheDir()`](/reference/android/content/Context#getCacheDir()).\nNote that this internal cache may be flushed when the system is running low on\navailable storage.\n| **Note:** Files stored in either cache location are erased when the app is uninstalled.\n\nUse a repository\n----------------\n\nFor a more sophisticated approach to caching, consider the Repository design\npattern. This involves creating a custom class, known as a Repository, which\nprovides an API abstraction over some specific data or resource. The repository\nmay initially fetch its data from various sources, such as a remote web service,\nbut provides callers with a cached version of the data in subsequent calls. This\nlayer of indirection allows you to provide a robust caching strategy that's\nspecific to your app. For more information about using the Repository pattern\nwithin your app, see the [Guide to app\narchitecture](/jetpack/guide)."]]