일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 안드로이드 레트로핏 crud
- 안드로이드 유닛테스트란
- ar vr 차이
- jvm 작동 원리
- 플러터 설치 2022
- Rxjava Observable
- rxjava hot observable
- 안드로이드 유닛 테스트 예시
- android ar 개발
- 자바 다형성
- 스택 자바 코드
- 클래스
- 스택 큐 차이
- rxjava cold observable
- 안드로이드 라이선스 종류
- 안드로이드 레트로핏 사용법
- android retrofit login
- 객체
- 큐 자바 코드
- 2022 플러터 설치
- 서비스 쓰레드 차이
- 서비스 vs 쓰레드
- 안드로이드 os 구조
- 안드로이드 유닛 테스트
- ANR이란
- 멤버변수
- 안드로이드 라이선스
- 2022 플러터 안드로이드 스튜디오
- rxjava disposable
- jvm이란
- Today
- Total
나만을 위한 블로그
[Android] WebView Cache 전략 설정 방법 본문
이전 포스팅에서 캐시에 대해 확인했다.
https://onlyfor-me-blog.tistory.com/825
이제 안드로이드 웹뷰에서 캐시 전략을 어떻게 설정하는지 확인한다.
먼저 간단한 기본 코드를 준비한다.
<?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
위와 같이 설정한 후 실행하면 모바일 네이버 홈 화면이 전체 화면 웹뷰로 표시된다.
아직 캐시 전략은 설정되지 않았으니 이제 설정을 시작해 본다. 그 전에 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
이는 기본 웹뷰 내부 캐시와 아무 상관없다. AppCache는 인터넷 연결 없이 웹 사이트를 실행할 수 있게 해주는 완전히 다른 기능이다. viewer.getSettings.setCacheMode(WebSettings.LOAD_DEFAULT)면 충분하다
참고로 setAppCacheEnabled()는 웹뷰에서 HTML 5 앱 캐시 기능을 (비)활성화하는 데 사용하는 메서드다.
HTML 5 앱 캐시는 웹 앱을 오프라인에서도 실행 가능하게 하는 기능이다. 웹 페이지와 관련된 리소스(이미지, 스크립트, CSS 등)는 한 번 방문하면 로컬에 저장될 수 있고, 이후 네트워크 연결이 끊겨도 해당 리소스를 로컬 캐시에서 불러와 웹 페이지를 사용할 수 있게 해 준다. 이 기능이 필요하다면 true를 넣어서 호출하면 되며, setAppCachePath()를 통해 캐시 데이터를 저장할 경로도 지정해주면 된다. 그러나 현재는 deprecated된 상태고 캐시 API나 Service Workers로 대체되고 있다고 한다.
하이브리드 앱을 만든다면 웹뷰의 기본 설정은 중요한 작업이다. 캐시도 네이티브 앱에서 사용 전략을 어떻게 설정하느냐에 따라 작동 방식이 생각한 것과 달라질 수 있기 때문에, 캐시 전략을 비롯한 다른 커스텀 가능한 부분들은 상세하게 논의한 후 설정하자.
'Android' 카테고리의 다른 글
[Android] UseCase에서 invoke를 사용하는 이유 (with 클린 아키텍처) (0) | 2023.11.12 |
---|---|
[Android] 폴더블 기기 펼침 여부 확인하는 방법 (Jetpack WindowManager) (0) | 2023.11.08 |
[Android] 리사이클러뷰 UI test 작성하기 (0) | 2023.09.24 |
[Android] UI test에서 TedBottomPicker 사용하는 법 (0) | 2023.09.21 |
[Android] CameraX 코드랩 뜯어보기 - 4 - (完) (0) | 2023.09.19 |