프로그래밍/안드로이드

안드로이드 웹뷰(Webview)의 이해와 성능 최적화 방안

Terry Cho 2015. 9. 16. 00:11

간단한 웹뷰 컴포넌트의 이해와 최적화

조대협(http://bcho.tistory.com)


들어가기에 앞서서


이글은 안드로이드 프로그래밍 개발을 공부하면서 공부한 내용을 정리한 글입니다. 제가 아직 안드로이드에는 전문성이 없는 초보자 수준이기 때문에, 수준이 높지 않으니, 내용을 참고만 하시기를 바라며, 더 나은 프로그래밍 방법등이 있음을 미리 알려드립니다.


Webview(웹뷰) 컴포넌트에 대해서


웹뷰는 안드로이드 프레임웍에 내장된 웹 브라우져 컴포넌트로 뷰(View)형태로 앱에 임베딩이 가능하다. 비교해서 생각하자면, 안드로이드 앱안에, HTML iframe을 넣어놓은 것이라고나 할까?

단순하게, 웹 페이지를 보기위해도 사용하지만, 안드로이드 앱 안에서 HTML을 호출하여 앱을 구현하는 하이브리드 형태의 앱을 개발하는데에도 많이 사용된다. 이러한 하이브리드 앱은 안드로이드 네이티브 앱 개발에 비해서 개발이 비교적 쉽고, 특히나 기기간의 호환성을 해결하기가 상대적으로 편하다는 장점을 가지고 있으나, HTML 기반인 만큼 상대적으로 반응성이 약하고, 애니메이션등의 다양한 UI 효과를 넣기 어렵다는 단점을 가지고 있다.

그럼에도 불구하고 SNS나 기타 서비스 앱에서는 타 웹사이트 링크로 가는 기능등을 지원하기 위해서 많이 사용되고 있다.

웹 뷰에 사용되는 브라우져 컴포넌트는 우리가 일반적으로 생각하는 웹브라우져 수준으로 생각하면 곤란하다. 일반적인 웹 브라우져를 안드로이드 OS에 맞게 일부 기능들을 제외하고 작게 만든 웹브라우져라고 생각하면 되고 그렇기 때문에 HTML5 호환성등 기능의 제약을 많이 가지고 있다.



기본적인 웹뷰 사용방법


이해를 돕기 위해서 웹뷰를 이용한 간단한 애플리케이션을 만들어보자. 이 애플리케이션은 URL을 입력 받고 Go 버튼을 누르면 웹뷰에 해당 URL을 접속하여 보여주고, 해당 URL이 로딩되는데 까지 걸린 시간을 millisecond 로 표시해주는 애플리케이션이다.




먼저 안드로이드 스튜디오에서, MainActivity하나만 있는 심플한 앱 프로젝트를 생성한 후에, MainActivity의 레이아웃을 다음과 같이 디자인하자




위의 레이아웃의 XML 코드를 보면 다음과 같다.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity"
android:weightSum="1">


<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<EditText
android:layout_width="252dp"
android:layout_height="wrap_content"
android:id="@+id/txtURL"
android:text="http://www.naver.com" />

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Go"
android:id="@+id/btnGo"
android:onClick="goURL" />
</LinearLayout>

<WebView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/webView"
android:layout_weight="0.83" />

<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.13">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Elapsed time :"
android:id="@+id/tvElapsedTime" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="sec"
android:id="@+id/tvSec" />
</LinearLayout>

</LinearLayout>

레이아웃이 디자인 되었으면, [GO]버튼을 눌렀을때, 웹뷰에 URL을 표시하도록 goURL(View)라는 메소드를 다음과 같이 구현하자


public void goURL(View view){
TextView tvURL = (TextView)findViewById(R.id.txtURL);
String url = tvURL.getText().toString();
Log.i("URL","Opening URL :"+url);

WebView webView = (WebView)findViewById(R.id.webView);
webView.setWebViewClient(new WebViewClient()); // 이걸 안해주면 새창이 뜸
webView.loadUrl(url);

}


사용법은 의외로 간단한데, Webview객체를 얻어와서 loadURL로 url을 로딩하면 된다. 이때 주의할점은 setWebViewClient()  메서드를 사용해야 하는데, 안드로이드에서는 디폴트로, 다른 링크로 이동하고자 할때는 안드로이드의 디폴트 외부 웹 브라우져를 통해서 이동하도록 하고 있다. 그래서 만약 setWebViewClient로 내부 웹뷰 클라이언트를 지정해주지 않으면 별도의 브라우져가 뜨는 것을 볼 수 있다.

그리고 이 애플리케이션은 외부 인터넷을 억세스하기 때문에, AndroidManifest.xml에서INTERNET 퍼미션을 추가해줘야 한다.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.terry.simplewebview" >
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:hardwareAccelerated="true"> // 하드웨어 가속 사용
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>


주목해서 봐야할점중 하나는 android:hardwareAccelerated  라는 필드인데, 웹 페이지를 렌더링 하는데 하드웨어 가속 기능을 사용하도록 하는 옵션으로, 이 옵션 사용 여부에 따라서 성능차이가 꽤 있기 때문에, 가급적이면 사용하도록 한다.


여기서 약간 개량을 해서, 해당 URL이 다 뜨고 나면 로딩하는데 걸리는 시간을 측정하는 로직을 추가해보자


public void goURL(View view){
TextView tvURL = (TextView)findViewById(R.id.txtURL);
String url = tvURL.getText().toString();
Log.i("URL", "Opening URL with WebView :" + url);

final long startTime = System.currentTimeMillis();
WebView webView = (WebView)findViewById(R.id.webView);

// 하드웨어 가속
// 캐쉬 끄기
//webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
long elapsedTime = System.currentTimeMillis()-startTime;
TextView tvSec = (TextView) findViewById(R.id.tvSec);
tvSec.setText(String.valueOf(elapsedTime));
}
});
webView.loadUrl(url);

}


setWebViewClient를 만들때, WebViewClient에 onPageFinished라는 메서드를 오버라이딩해서 종료 시간을 구할 수 있다. 이 메서드는 해당 URL이 모두 로딩되었을때 호출되는 메서드이다.


웹뷰의 개념 이해를 돕기 위해서 가장 간단한 예제를 통해서 설명하였는데, HTML 안에서 Javascript 를 사용하려면 별도의 옵션이 필요하고, 또한 javascript를 사용할때는 Javascript의 메서드를 실행하면, 안드로이드 애플리케이션내에 정의된 메서드를 수행할 수 있도록도 할 수 있다. 

기타 자세한 내용은 http://developer.android.com/guide/webapps/webview.html 를 참고하기 바란다.


웹뷰의 성능 향상과 확장


웹뷰에 대한 성능 관련 자료를 찾아보니, 성능이 안나오는 문제가 많아서 하이브리드 앱을 개발하는 쪽에는 다양한 솔루션이 제시되고 있다. 써드 파티 웹뷰 라이브러리를 이용하는 방법이나 또는 웹뷰를 커스터마이징 해서 WebSocket의 기능을 추가하거나 Canvas 성능을 개선하는 작업등이 있는데 (http://deview.kr/2013/detail.nhn?topicSeq=14) 성능 부분에 대해서는 조금 더 공부가 필요할듯 하고, 아래는 성능 관련해서 검색을 했을때 주로 많이 소개되는 내용을 정리하였다.


크롬뷰 사용


안드로이드 4.4 (API level 19)부터는 웹뷰에 대한 성능 개선의 일환으로 Chromium (http://www.chromium.org/Home

) 이라는 오픈소스( 브라우져가 사용되었는데, 별도의 설정없이도, 이 브라우져 기반의 웹뷰가 사용이 가능하다. Chromium 기반의 웹뷰는 성능 향상뿐만 아니라, HTML 호환성 개선도 같이 이루어졌다. 

https://www.google.co.kr/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=webview+performance+android&newwindow=1&start=10


일반적인 튜닝 옵션


일반적으로 웹뷰 성능 튜닝 관련 내용을 검색하면 단골로 나오는 3가지 튜닝 옵션들이 있는데 다음과 같다

  • 캐쉬 사용하지 않기 : webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);로 브라우져 캐쉬를 끄는 방법이 언급되는데, 사실 캐쉬를 쓰는데 왜 성능이 올라가는지는 잘 모르겠다. 이 부분은 조금 더 살펴봐야할것으로 보이고
  • 하드웨어 가속 기능 사용하기 :렌더링에 대해서 하드웨어 가속 기능을 사용할지 여부인데, 3.0 부터 지원이 되기 시작했고, 디폴트는 false이며, 4.0부터는 default가 true이다. 앞의 예제에서와 같이 AndroidManifest.xml에서, android:hardwareAccelrated를  true로 설정해주면 된다.
  • 렌더링 우선 순위 높이기 : 강제적으로 렌더링 기능에 대한 우선 순위를 높이는 방법이다. webView.getSettings().setRenderPriority(RenderPriority.HIGH)로 설정해주면 되는데, API Level 18부터는 deprecated 되었기 때문에 하위 버전에만 적용될 수 있도록 한다.

외부 라이브러리를 이용한 웹뷰의 성능 향상


다른 성능 향상 방법으로는 써드 파티 라이브러리를 찾아봤는데, 가장 많이 사용되는 라이브러리로 크로스워크(crosswalk)라는 오픈 소스 라이브러리가 있다. https://crosswalk-project.org/documentation/getting_started.html

성능 향상은 물론이거니와, HTML5에 대한 호환성 지원도 매우 높고, 안드로이드뿐만 아니라, iOS,Tizen등 다양한 OS를 지원하기 때문에 하이브리드 앱을 개발한다면 탑재를 고려해볼만하지만, 이러한 호환성이나 성능을 높이기 위해서 렌더링 관련 기능을 모두 자체 구현하였기 때문에 앱 사이즈가 대략 30~40MB정도 커지기 때문에, 앱 크기에 대한 부담과 dex 사이즈에 대한 부담 (안드로이드 실행 파일인 dex는 메서드수가 65535개로 제한이 되어 있다.)

http://monaca.mobi/en/blog/crosswalk-performance/ 는 HTML5에 대한 호환성을 Crosswalk와 기본 웹뷰 사이에 수치를 비교한것인데, 일반 웹뷰는 278, 크로스워크는 호환성 부분에서 493 포인트를 낸것을 확인할 수 있다.


게임이나 일반 애플리케이션의 경우는 네이티브 앱 개발이 아무래도 대세가 되겠지만, SNS나 미디어성 컨텐츠는 개발의 용이성과 호환성 그리고 다양한 컨텐츠 포맷을 지원하는 점에서 HTML5 기술이 지원되는 웹뷰는 아무래도 필수적인 기술이 되지 않을까 싶다.