관리 메뉴

나만을 위한 블로그

[Android] WebView Cache 전략 설정 방법 본문

Android

[Android] WebView Cache 전략 설정 방법

참깨빵위에참깨빵 2023. 10. 22. 00:22
728x90
반응형

이전 포스팅에서 캐시에 대해 확인했다.

 

https://onlyfor-me-blog.tistory.com/825

 

캐시란?

웹뷰를 사용하다 보면 캐시라는 말을 자주 듣는다. 프론트엔드 개발자가 존재한다면 캐시라는 키워드를 더 자주 들을 수 있다. 그런데 도대체 캐시란 게 뭘까? 캐시라는 개념은 안드로이드에서

onlyfor-me-blog.tistory.com

 

이제 안드로이드 웹뷰에서 캐시 전략을 어떻게 설정하는지 확인한다.

먼저 간단한 기본 코드를 준비한다.

 

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".webview.WebViewCacheActivity">

        <WebView
            android:id="@+id/wbTest"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>
class WebViewCacheActivity :
    BaseActivity<ActivityWebViewCacheBinding>(R.layout.activity_web_view_cache) {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setupWebView()
    }

    @SuppressLint("SetJavaScriptEnabled")
    private fun setupWebView() {
        binding.wbTest.apply {
            settings.run {
                javaScriptEnabled = true
                domStorageEnabled = true // 웹 페이지에서 로컬 스토리지, 세션 스토리지를 사용하려면 true로 설정
                mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW // 모든 혼합된 컨텐츠(HTTP 리소스를 HTTPS 페이지에서 로드)를 항상 허용. 기본값 : MIXED_CONTENT_NEVER_ALLOW
                javaScriptCanOpenWindowsAutomatically = true
                webViewClient = WebViewClient()
                webChromeClient = WebChromeClient()
            }
            loadUrl("https://m.naver.com/")
        }
    }

}

 

mixedContentMode가 생소하다면 아래 스택오버플로우 링크의 답변을 확인하면 좋을 것이다.

 

https://stackoverflow.com/a/32875064

 

Android WebView not loading Mixed Content

I'm trying to make a app with WebView, but the website is using https, but the content (ex. mp3 file) uses http, so Android Lollipop won't load it because it is "Mixed Content". I tried to use

stackoverflow.com

 

위와 같이 설정한 후 실행하면 모바일 네이버 홈 화면이 전체 화면 웹뷰로 표시된다.

 

 

아직 캐시 전략은 설정되지 않았으니 이제 설정을 시작해 본다. 그 전에 HTTP Response의 헤더는 어떻게 구성돼 있는지 간단하게 확인한다. 자세하게까진 아니라도 HTTP 응답의 캐시 관련 헤더가 어떻게 구성되는지 알고 있으면 웹 개발자들과의 소통이 더 편리할 것이다. 만약 이미 알고 있거나 관심 없다면 아래로 쭉 내려서 코드로 이동한다.

아래는 HTTP Response 헤더의 구성 예시다. 캐시와 관련된 속성만 확인한다.

 

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=3600, must-revalidate, private
Vary: Accept-Language, User-Agent
Last-Modified: Mon, 19 Oct 2023 17:00:00 GMT
ETag: "2d998-582-5d308880"
Age: 500
...

 

Content-Type 밑의 헤더들이 캐시와 관련된 헤더들이다. 각각 간단하게 확인하면

 

  • Cache-Control : 리소스가 캐시되는 방식, 어디에 캐시되는지, 재검증이 필요하다면 어떻게 되는지 등의 지시어를 포함하는 헤더. "max-age"의 단위는 초(Sec)다.
    위 예시는 리소스가 1시간(3,600초) 동안 캐시될 수 있으며 캐시된 리소스의 유효 기간이 지나면 반드시 서버에 재검증을 요청(must-revalidate)해야 하고, 또한 이 리소스는 개인 캐시(유저가 사용 중인 핸드폰, 컴퓨터 등)에만 저장돼야 하고 공용 프록시(CDN 등)에 저장되서는 안 된다는 의미다
  • Vary : 클라이언트의 "Accept-Encoding" 요청 헤더에 따라 리소스가 달라질 수 있음을 의미한다. 이 헤더를 기반으로 캐시된 리소스의 버전을 결정한다. 위 예시에선 User-Agent와 언어의 각 조합에 대해 캐시된 버전이 존재해야 한다는 의미한다
  • Expires : 해당 리소스는 2023년 10월 21일 20:00:00GMT에 만료됨을 나타낸다. 여기 적힌 캐시의 만료 시간은 Cache-Control의 "max-age"와 일치해야 한다
  • Last-Modified : 리소스가 마지막으로 수정된 날짜, 시간을 나타낸다. 위 예시에선 2023년 10월 19일 17:00:00GMT에 마지막으로 수정됐다는 의미다
  • ETag(Entity Tag) : 리소스의 특정 버전을 나타내는 고유 식별자. Last-Modified와 ETag가 같이 있다면 ETag의 우선순위가 더 높게 설정된다. 특정 URL의 리소스가 변경될 경우 새 ETag가 생성된다. 웹 서버가 이 헤더를 확인한 후 바뀌지 않았다면 웹 서버로 요청을 보내지 않게 되어 효율적으로 캐시를 사용할 수 있게 되고, 대역폭도 아낄 수 있다
  • Age : 캐시된 리소스가 얼마나 오래됐는지 나타내는 값. 위 예시는 500초동안 캐시됐음을 의미한다. 단위는 초(Sec)

 

이제 안드로이드 웹뷰에서 사용할 수 있는 캐시 전략들을 확인한다.

안드로이드 웹뷰 캐시 전략들은 아래와 같이 몇 가지가 있다. LOAD_NORMAL도 있지만 API 13 기준 deprecated됐고 기본 설정값이기 때문에 생략한다.

 

  • LOAD_DEFAULT : 기본 캐시 사용 규칙을 따른다. 즉 HTTP Response 헤더에 따라 캐시가 사용된다
  • LOAD_CACHE_ELSE_NETWORK : 네트워크에 연결돼 있지 않거나 캐시를 쓸 수 있으면 캐시를 쓰고, 캐시가 만료되는 등의 케이스로 쓸 수 없다면 네트워크를 사용한다.
  • LOAD_CACHE_ONLY : 네트워크를 일절 사용하지 않고 캐시만 사용한다
  • LOAD_NO_CACHE : 캐시를 일절 사용하지 않고 네트워크만 사용한다

 

캐시 설정은 아래와 같이 할 수 있다.

 

class WebViewCacheActivity :
    BaseActivity<ActivityWebViewCacheBinding>(R.layout.activity_web_view_cache) {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setupWebView()
    }

    @SuppressLint("SetJavaScriptEnabled")
    private fun setupWebView() {
        binding.wbTest.apply {
            settings.run {
                javaScriptEnabled = true
                domStorageEnabled = true
                mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
                javaScriptCanOpenWindowsAutomatically = true
                webViewClient = WebViewClient()
                webChromeClient = WebChromeClient()
                cacheMode = WebSettings.LOAD_NO_CACHE // 캐시를 일절 사용하지 않고 네트워크만 사용
            }
            loadUrl("https://m.naver.com/")
        }
    }

}

 

그리고 웹뷰 캐시 설정법과 관련된 글을 찾다 보면 아래 메서드를 사용하는 경우가 있다.

 

setAppCacheEnabled(true)

 

이 메서드는 API 13부터 사용할 수 없게 변경된 메서드다. 또한 웹뷰 내부의 캐시와 아무 상관없는 메서드로, 아래의 스택오버플로우에 관련 답변이 있다.

 

https://stackoverflow.com/a/17429301

 

Caching in Android webview

Which one is faster way to load mobile web pages and non mobile web pages in Android webview; loading cache or not loading that at all? And what is recommend style to load that? Right now when I ...

stackoverflow.com

이는 기본 웹뷰 내부 캐시와 아무 상관없다. AppCache는 인터넷 연결 없이 웹 사이트를 실행할 수 있게 해주는 완전히 다른 기능이다. viewer.getSettings.setCacheMode(WebSettings.LOAD_DEFAULT)면 충분하다

 

참고로 setAppCacheEnabled()는 웹뷰에서 HTML 5 앱 캐시 기능을 (비)활성화하는 데 사용하는 메서드다.

HTML 5 앱 캐시는 웹 앱을 오프라인에서도 실행 가능하게 하는 기능이다. 웹 페이지와 관련된 리소스(이미지, 스크립트, CSS 등)는 한 번 방문하면 로컬에 저장될 수 있고, 이후 네트워크 연결이 끊겨도 해당 리소스를 로컬 캐시에서 불러와 웹 페이지를 사용할 수 있게 해 준다. 이 기능이 필요하다면 true를 넣어서 호출하면 되며, setAppCachePath()를 통해 캐시 데이터를 저장할 경로도 지정해주면 된다. 그러나 현재는 deprecated된 상태고 캐시 API나 Service Workers로 대체되고 있다고 한다.

 

하이브리드 앱을 만든다면 웹뷰의 기본 설정은 중요한 작업이다. 캐시도 네이티브 앱에서 사용 전략을 어떻게 설정하느냐에 따라 작동 방식이 생각한 것과 달라질 수 있기 때문에, 캐시 전략을 비롯한 다른 커스텀 가능한 부분들은 상세하게 논의한 후 설정하자.

반응형
Comments