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

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

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

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

HTTP 응답 캐시

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

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

캐싱으로 인해 앱이 오래된 데이터를 표시하지 않도록 하려면 ETagLast-Modified 헤더와 같은 적절한 HTTP 상태 코드 및 헤더를 사용하세요. 이렇게 하면 연결된 콘텐츠를 새로고침해야 하는 시기를 결정할 수 있습니다. 예:

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
}

Java

// 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()

Java

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 추상화를 제공하는 저장소라고 하는 커스텀 클래스를 만드는 작업이 포함됩니다. 저장소는 처음에는 원격 웹 서비스와 같은 다양한 소스에서 데이터를 가져올 수 있지만 후속 호출에서 호출자에게 캐시된 버전의 데이터를 제공합니다. 이 간접 레이어를 사용하면 앱에 맞는 강력한 캐싱 전략을 제공할 수 있습니다. 앱 내에서 저장소 패턴을 사용하는 방법에 관한 자세한 내용은 앱 아키텍처 가이드를 참고하세요.