이제 Android 11 개발자 프리뷰를 사용할 수 있습니다. 테스트해 보고 의견을 공유하세요.

중복 다운로드 방지

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

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

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

로컬에서 파일 캐시

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

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

캐싱 때문에 앱에 오래된 데이터가 표시되지 않게 하려면 요청된 콘텐츠가 마지막으로 업데이트된 시간과 만료된 시간을 HTTP 응답 헤더에서 추출해야 합니다. 이러한 방식으로 관련 콘텐츠를 새로고침할 시기를 결정할 수 있습니다.

Kotlin

    val conn: HttpsURLConnection = url.openConnection() as HttpsURLConnection
    val currentTime: Long = System.currentTimeMillis()
    val expires: Long = conn.getHeaderFieldDate("Expires", currentTime)
    val lastModified: Long = conn.getHeaderFieldDate("Last-Modified", currentTime)
    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 expires = conn.getHeaderFieldDate("Expires", currentTime);
    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;
    }
    

또한, 이 접근 방식을 사용하면 애플리케이션이 오래된 정보를 표시하지 않도록 하면서 동적 콘텐츠를 효과적으로 캐시할 수 있습니다.

Context#getExternalCacheDir()을 통해 얻은 외부의 비관리 캐시 디렉터리에 민감하지 않은 데이터를 캐시할 수 있습니다.

또는 Context#getCacheDir()를 통해 얻은 안전하게 관리되는 애플리케이션 캐시를 사용할 수도 있습니다. 이 내부 캐시는 시스템의 사용 가능한 저장용량이 부족하면 플러시될 수 있습니다.

참고: 앱이 제거되면 각 캐시 위치에 저장된 파일은 삭제됩니다.

HttpsURLConnection 응답 캐시 사용

Android 4.0에서는 응답 캐시를 HttpsURLConnection에 추가했습니다. 다음과 같이 리플렉션을 사용하여 지원되는 기기에서 HTTP 응답 캐싱을 사용 설정할 수 있습니다.

Kotlin

    private fun enableHttpResponseCache() {
        try {
            val httpCacheSize: Long = 10L * 1024L * 1024L // 10 MiB
            val httpCacheDir = File(cacheDir, "http")
            Class.forName("android.net.http.HttpResponseCache")
                    .getMethod("install", File::class.java, Long::class.javaPrimitiveType)
                    .invoke(null, httpCacheDir, httpCacheSize)
        } catch (httpResponseCacheNotAvailable: Exception) {
            Log.d(TAG, "HTTP response cache is unavailable.")
        }
    }
    

자바

    private void enableHttpResponseCache() {
      try {
        long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
        File httpCacheDir = new File(getCacheDir(), "http");
        Class.forName("android.net.http.HttpResponseCache")
             .getMethod("install", File.class, long.class)
             .invoke(null, httpCacheDir, httpCacheSize);
      } catch (Exception httpResponseCacheNotAvailable) {
        Log.d(TAG, "HTTP response cache is unavailable.");
      }
    }
    

이 샘플 코드는 Android 4.0 이상의 기기에서 응답 캐시를 사용하고 그 이전에 출시된 버전에는 영향을 주지 않습니다.

캐시가 설치되면 완전히 캐시된 HTTP 요청은 로컬 저장소에서 직접 제공되며 네트워크 연결을 하지 않아도 됩니다. 조건부로 캐시된 응답은 서버에서 최신 상태인지 확인하여 다운로드와 관련된 대역폭 비용을 없앨 수 있습니다.

캐시되지 않은 응답은 이후 발생할 요청을 위해 응답 캐시에 저장됩니다.