최적화되지 않은 다운로드 방지

일부 앱 사용자는 인터넷에 간헐적으로 액세스하거나 기기에 다운로드할 수 있는 정보의 양이 제한되어 있습니다. 앱이 다운로드해야 하는 데이터의 양을 줄이면 사용자가 앱과 더 자주 상호작용하도록 할 수 있습니다.

다운로드를 줄이는 가장 기본적인 방법은 필요한 것만 다운로드하는 것입니다. 데이터 측면에서 이는 매개변수(예: 마지막 업데이트 시간)를 사용하여 반환되는 데이터를 제한하는 쿼리 기준을 지정할 수 있는 REST API를 구현하는 것을 의미합니다.

마찬가지로 이미지를 다운로드할 때 클라이언트 측에서 이미지 전체를 다운로드하여 크기를 줄이는 것보다 서버 측에서 이미지의 크기를 줄이는 것이 좋습니다.

HTTP 응답 캐시

또 다른 중요한 기술은 중복된 데이터를 다운로드하지 않는 것입니다. 캐싱을 사용하면 동일한 데이터를 반복적으로 다운로드할 가능성을 줄일 수 있습니다. 앱의 데이터와 리소스를 캐시하여 앱이 참조해야 할 정보의 로컬 복사본을 만듭니다. 앱이 짧은 기간에 동일한 정보를 여러 번 액세스해야 한다면 그 정보를 캐시에 한 번만 다운로드하면 됩니다.

다운로드하는 총 데이터 양을 줄이려면 최대한 많이 캐시하는 것이 중요합니다. 원본 크기의 이미지와 같은 주문형 다운로드를 비롯한 정적 리소스는 항상 최대한 오래 캐시하세요. 주문형 캐시를 정기적으로 플러시하여 캐시 크기를 관리할 수 있도록 주문형 리소스는 별도로 저장해야 합니다.

캐싱으로 인해 앱에 오래된 데이터가 표시되지 않도록 하려면 적절한 HTTP 상태 코드 및 헤더(예: ETagLast-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 추상화를 제공합니다. 저장소는 처음에 원격 웹 서비스와 같은 다양한 소스에서 데이터를 가져올 수 있지만 후속 호출에서 호출자에게 캐시된 버전의 데이터를 제공합니다. 이러한 간접 레이어를 사용하면 특정 앱에만 적용되는 강력한 캐싱 전략을 제공할 수 있습니다. 앱 내에서 저장소 패턴을 사용하는 방법에 관한 자세한 내용은 앱 아키텍처 가이드를 참고하세요.