일부 앱 사용자는 인터넷에 간헐적으로 액세스하거나 기기에 다운로드할 수 있는 정보의 양이 제한되어 있습니다. 앱이 다운로드해야 하는 데이터의 양을 줄이면 사용자가 앱과 더 자주 상호작용하도록 할 수 있습니다.
다운로드를 줄이는 가장 기본적인 방법은 필요한 것만 다운로드하는 것입니다. 데이터 측면에서 이는 매개변수(예: 마지막 업데이트 시간)를 사용하여 반환되는 데이터를 제한하는 쿼리 기준을 지정할 수 있는 REST API를 구현하는 것을 의미합니다.
마찬가지로 이미지를 다운로드할 때 클라이언트에서 줄어든 원본 크기 이미지를 다운로드하는 것보다 서버 측에서 이미지의 크기를 줄이는 것이 좋습니다.
HTTP 응답 캐시
또 다른 중요한 기술은 중복된 데이터를 다운로드하지 않는 것입니다. 캐싱을 사용하면 동일한 데이터를 반복적으로 다운로드할 가능성을 줄일 수 있습니다. 앱의 데이터와 리소스를 캐시하여 앱이 참조해야 할 정보의 로컬 복사본을 만듭니다. 앱이 짧은 기간에 동일한 정보를 여러 번 액세스해야 한다면 그 정보를 캐시에 한 번만 다운로드하면 됩니다.
다운로드할 전체 데이터양을 줄이려면 최대한 많이 캐시하는 것이 중요합니다. 원본 크기의 이미지와 같은 주문형 다운로드를 비롯한 정적 리소스는 항상 최대한 오래 캐시하세요. 주문형 캐시를 정기적으로 플러시하여 캐시 크기를 관리할 수 있도록 주문형 리소스는 별도로 저장해야 합니다.
캐싱으로 인해 앱에 오래된 데이터가 표시되지 않도록 하려면 적절한 HTTP 상태 코드 및 헤더(예: ETag
및 Last-Modified
헤더)를 사용하세요. 이를 통해 관련 콘텐츠를 새로고침할 시기를 결정할 수 있습니다. 예를 들면 다음과 같습니다.
Kotlin
// url represents the website containing the content to place into the cache. val conn: HttpsURLConnection = url.openConnection() as HttpsURLConnection val currentTime: Long = System.currentTimeMillis() val lastModified: Long = conn.getHeaderFieldDate("Last-Modified", currentTime) // lastUpdateTime represents when the cache was last updated. if (lastModified < lastUpdateTime) { // Skip update } else { // Parse update lastUpdateTime = lastModified }
자바
// url represents the website containing the content to place into the cache. HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); long currentTime = System.currentTimeMillis(); long lastModified = conn.getHeaderFieldDate("Last-Modified", currentTime); // lastUpdateTime represents when the cache was last updated. if (lastModified < lastUpdateTime) { // Skip update } else { // Parse update lastUpdateTime = lastModified; }
이러한 상태 코드와 헤더를 자동으로 준수하도록 일부 네트워킹 라이브러리를 구성할 수 있습니다. 예를 들어 OkHttp를 사용할 때 클라이언트의 캐시 디렉터리와 캐시 크기를 구성하면 다음 코드 샘플과 같이 라이브러리에서 HTTP 캐싱을 사용할 수 있습니다.
Kotlin
val cacheDir = Context.getCacheDir() val cacheSize = 10L * 1024L * 1024L // 10 MiB val client: OkHttpClient = OkHttpClient.Builder() .cache(Cache(cacheDir, cacheSize)) .build()
자바
File cacheDir = Context.getCacheDir(); long cacheSize = 10L * 1024L * 1024L; // 10 MiB OkHttpClient client = new OkHttpClient.Builder() .cache(new Cache(cacheDir, cacheSize)) .build();
캐시를 구성하면 완전히 캐시된 HTTP 요청을 로컬 저장소에서 직접 제공할 수 있으므로 네트워크 연결을 열지 않아도 됩니다. 조건부로 캐시된 응답은 서버에서 최신 상태인지 확인하여 다운로드와 관련된 대역폭 비용을 없앨 수 있습니다. 캐시되지 않은 응답은 향후 요청을 위해 응답 캐시에 저장됩니다.
Context.getExternalCacheDir()
를 사용하여 비관리 외부 캐시 디렉터리에 민감하지 않은 데이터를 캐시할 수 있습니다.
또는 Context.getCacheDir()
를 사용하여 안전하게 관리되는 애플리케이션 캐시에 데이터를 캐시할 수 있습니다.
이 내부 캐시는 시스템의 사용 가능한 저장용량이 부족하면 플러시될 수 있습니다.
저장소 사용
캐싱에 대한 더 정교한 접근 방식을 사용하려면 저장소 디자인 패턴을 고려하세요. 이를 위해서는 저장소라고 하는 맞춤 클래스를 만들어야 합니다. 이 클래스는 특정 데이터 또는 리소스에 관한 API 추상화를 제공합니다. 저장소는 처음에는 원격 웹 서비스와 같은 다양한 소스에서 데이터를 가져올 수 있지만 후속 호출에서는 호출자에게 데이터의 캐시된 버전을 제공합니다. 이 간접 참조 레이어를 사용하면 앱에 맞는 강력한 캐싱 전략을 제공할 수 있습니다. 앱 내에서 저장소 패턴을 사용하는 방법에 관한 자세한 내용은 앱 아키텍처 가이드를 참고하세요.