본문 바로가기
안드로이드

Glide를 활용한 WebView 이미지 로드 속도 높이기

by 디지털노마더 2021. 6. 15.

최근에 회사 프로젝트를 진행하면서 한 가지 이슈에 봉착했었습니다.

 

* 이슈 : WebView 내에서 여러 이미지를 Load 할 때 지연되거나 일부 절반만 불러오는 현상.

이미지 Load가 지연된 WebView

웹 브라우저에서는 동일한 URL을 호출했을 때, 빠른 속도로 이미지가 Load 되고 형광펜 후처리까지 정상적이었습니다.

해당 증상은 Android/iOS 모두 동일했습니다.

 

모바일에서 제공하는 WebView의 성능이 여러 이미지를 한꺼번에 Load할 정도로 우수하지 않다는 사실을 인지했습니다. 

 

구글링하던 중, Glide 라이브러리를 이용해서 WebView에 이미지 로딩성능을 높이는 방법을 확인했습니다.

 

1. Glide 라이브러리 추가

implementation ‘com.github.bumptech.glide:glide:4.11.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.11.0’

Glide를 활용하기 위해서 build.gradle에 라이브러리를 implementaion 시켜줍니다.

 

2. WebView의 shouldInterceptRequest() 를 재정의

 구글개발자 사이트에서 WebView를 검색하면 리소스를 요청하는 모든 프로세스를 중간에서 가로채는 역할의 함수가 있습니다.  

 

shouldInterceptRequest()를 Override 받아서 WebViewClinet() 내에서 재정의합니다.

 

<Kotlin 코드>

override fun shouldInterceptRequest(view: WebView?, url: String?): WebResourceResponse? {
            if(url == null) {
                return super.shouldInterceptRequest(view, url as String)
            }

            return if(url.toLowerCase(Locale.ROOT).contains(".jpg") || url.toLowerCase(Locale.ROOT).contains(".jpeg")){
                val bitmap = Glide.with(webview).asBitmap().diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get()
                WebResourceResponse("image/jpg", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.JPEG))
            }else if(url.toLowerCase(Locale.ROOT).contains(".png")){
                val bitmap = Glide.with(webview).asBitmap().diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get()
                WebResourceResponse("image/png", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.PNG))
            }else if(url.toLowerCase(Locale.ROOT).contains(".webp")){
                val bitmap = Glide.with(webview).asBitmap().diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get()
                WebResourceResponse("image/webp", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.WEBP))
            }else{
                super.shouldInterceptRequest(view, url)
            }
        }
        
        private fun getBitmapInputStream(bitmap: Bitmap, compressFormat: Bitmap.CompressFormat): InputStream {
            val byteArrayOutputStream = ByteArrayOutputStream()
            bitmap.compress(compressFormat, 80, byteArrayOutputStream)
            val bitmapData: ByteArray = byteArrayOutputStream.toByteArray()
            return ByteArrayInputStream(bitmapData)
        }
    }

 

<Java 코드>

        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            WebResourceResponse webResourceResponse = null;
            String url = request.getUrl().toString();
            if(url == null) {
                return super.shouldInterceptRequest(view, request);
            }

            // Glide를 이용하여 이미지 로드속도 향상
            try {
                if(url.toLowerCase(Locale.ROOT).contains(".jpg") || url.toLowerCase(Locale.ROOT).contains(".jpeg")){
                    Bitmap bitmap = Glide.with(binding.viewer).asBitmap().diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get();
                    webResourceResponse = new WebResourceResponse("image/jpg", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.JPEG));
                }else if(url.toLowerCase(Locale.ROOT).contains(".png")){
                    Bitmap bitmap = Glide.with(binding.viewer).asBitmap().diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get();
                    webResourceResponse =  new WebResourceResponse("image/png", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.PNG));
                }else if(url.toLowerCase(Locale.ROOT).contains(".webp")){
                    Bitmap bitmap = Glide.with(binding.viewer).asBitmap().diskCacheStrategy(DiskCacheStrategy.ALL).load(url).submit().get();
                    webResourceResponse =  new WebResourceResponse("image/webp", "UTF-8",getBitmapInputStream(bitmap,Bitmap.CompressFormat.WEBP));
                }else{
                    return super.shouldInterceptRequest(view, request);
                }

            }catch (Exception e) {
                e.printStackTrace();
            }

            return webResourceResponse;
        }

        private InputStream getBitmapInputStream(Bitmap bitmap, Bitmap.CompressFormat compressFormat) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            bitmap.compress(compressFormat, 80, byteArrayOutputStream);
            byte[] bitmapData = byteArrayOutputStream.toByteArray();
            return new ByteArrayInputStream(bitmapData);
        }

 

추가로 WebView의 javascriptEnabled = true 설정

<느낀점>

 안드로이드 WebView를 활용하는 것은 외부링크를 단순히 보는 용도로 사용하는 것은 적절하다.

 하지만 접속하는 Web에 다수의 이미지를 불러오거나 javascript 후처리가 이루어지는 경우, 웹 브라우저와 보이는 차이가 있을 수 있다.

 

 Glide를 사용해도 완전히 빠른 편은 아니지만, 이미지를 모두 불러왔을 때는 <img> 영역에 정상적으로 배치되는 결과를 확인할 수 있었다.

 

정상 Load된 WebView

 

혹시 이웃님들 중에, Android WebView 이미지 불러오기 성능향상에 

더 좋은 방법을 알고 계신 분이 있으시다면 댓글로 코멘트 부탁드립니다.

 

 

# 출처 

https://proandroiddev.com/enhance-android-webview-performance-using-glide-aba4bbc41bc7

https://medium.com/myntra-engineering/leveraging-native-power-in-webview-105d248fe71

댓글