웹 개발자를 위한 WebView 애플리케이션

게시일: 2014년 2월 28일

새 Android 프로젝트를 만들고, WebView를 추가하고, 원격 URL을 로드하고, 로컬 HTML 페이지를 로드하는 방법을 알아봅니다.

이 튜토리얼에서는 Android 개발 환경에 대한 경험이 제한적이거나 전혀 없지만 Kotlin에 대한 경험이 있는 개발자를 대상으로 합니다. 이미 Android 프로그래밍에 익숙한 경우 Android 개발자 사이트에서 WebView에서 웹 앱 빌드를 읽어보세요.

Android 스튜디오 설치

이 튜토리얼에서는 Android용 설계 및 빌드 IDE인 Android 스튜디오를 사용합니다.

새 Android 프로젝트 만들기

Android 스튜디오가 설치되면 설정 마법사가 실행됩니다.

새 프로젝트를 만들려면 다음과 같이 합니다.

  1. 새 프로젝트를 클릭합니다.
  2. Empty Activity 템플릿을 클릭하여 프로젝트에 선택합니다. 템플릿은 프로젝트의 구조와 Android 스튜디오에서 프로젝트를 빌드하는 데 필요한 파일을 만듭니다.
  3. 다음을 클릭하여 새 프로젝트 대화상자를 엽니다.
  4. 프로젝트를 구성합니다. 애플리케이션 이름, 패키지 이름, 타겟 SDK를 입력합니다. 그런 다음 Next를 클릭합니다.
  5. 최소 필수 SDK를 API 24: Android 7.0 (Nougat)으로 설정합니다.
  6. 마침을 클릭합니다.

Android 스튜디오에서 새 프로젝트가 열립니다.

프로젝트 구조

Android 스튜디오에서 만든 초기 프로젝트에는 애플리케이션을 설정하는 템플릿 코드가 있습니다. 몇 가지 더 중요한 폴더는 다음과 같습니다.

  • src/main/java. Android Java 소스 코드
  • src/main/res. 애플리케이션에서 사용하는 리소스입니다.
  • src/main/res/drawable: 애플리케이션에서 사용하는 이미지 리소스입니다.
  • src/main/res/xml. UI 구성요소의 구조를 정의하는 XML 레이아웃 파일입니다.
  • src/main/res/values. 애플리케이션에 하드코딩하고 싶지 않은 크기, 문자열, 기타 값입니다.
  • src/main/AndroidManifest.xml. 매니페스트 파일은 활동, 권한, 테마와 같이 애플리케이션에 포함된 항목을 정의합니다.

WebView 추가

그런 다음 기본 활동의 레이아웃에 WebView를 추가합니다.

  1. src/main/res/xml 디렉터리의 activity_main.xml 파일이 아직 열려 있지 않으면 엽니다. fragment_main.xml 파일도 표시될 수 있습니다. 이 튜토리얼에서는 필요하지 않으므로 무시해도 됩니다.

    activity_main.xml 편집기 하단에서 Text 탭을 선택하여 XML 마크업을 확인합니다.

    이 파일은 기본 활동의 레이아웃을 정의하며 미리보기 창에는 활동의 미리보기가 표시됩니다. 빈 활동 레이아웃에는 하위 요소가 포함되지 않습니다. WebView를 추가해야 합니다.

  2. XML 창에서 FrameLayout 요소의 끝에서 자체 닫기 슬래시를 삭제하고 다음과 같이 <WebView> 요소와 새 닫기 태그를 추가합니다.

    <FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
        xmlns:tools="https://schemas.android.com/tools"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        tools:ignore="MergeRootFrame">
    
        <WebView
          android:id="@+id/activity_main_webview"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />
    </FrameLayout>
    
  3. WebView를 사용하려면 Activity에서 참조해야 합니다. src/main/java/<PackageName> 디렉터리에서 기본 활동의 Java 소스 파일인 MainActivity.java를 엽니다.

    굵게 표시된 줄을 추가합니다.

    public class MainActivity extends Activity {
    
        private WebView mWebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mWebView = (WebView) findViewById(R.id.activity_main_webview);
    

    onCreate 메서드의 기존 코드는 Activity를 레이아웃에 연결하는 작업을 실행합니다. 추가된 줄은 웹 뷰를 참조하는 새 멤버 변수 mWebView를 만듭니다.

    다음 코드를 삭제합니다.

    if (savedInstanceState == null) {
      getSupportFragmentManager().beginTransaction()
        .add(R.id.container, new PlaceholderFragment())
        .commit();
    }
    

    WebView는 레이아웃 파일의 이 줄에 지정된 리소스 ID로 식별됩니다.

    android:id="@+id/activity_main_webview"
    

    코드를 추가하면 편집기의 여백에 경고 메시지가 표시됩니다. WebView에 적절한 클래스를 가져오지 않았기 때문입니다. 다행히 Android 스튜디오를 사용하면 누락된 클래스를 채울 수 있습니다. 가장 쉬운 방법은 알 수 없는 클래스 이름을 클릭하고 마우스를 가져간 다음 '빠른 수정'을 보여주는 모듈이 표시될 때까지 기다리는 것입니다. 이 경우 WebView 클래스에 import 문을 추가합니다.

    Alt + Enter (Mac의 경우 Option + Enter)를 눌러 빠른 수정을 수락합니다.

    WebView를 준비했으면 이제 WebView를 설정하고 흥미로운 웹 콘텐츠를 로드해 보겠습니다.

자바스크립트 사용

WebView는 기본적으로 JavaScript를 허용하지 않습니다. WebView에서 웹 애플리케이션을 실행하려면 onCreate 메서드에 다음 줄을 추가하여 JavaScript를 명시적으로 사용 설정해야 합니다.

// Enable Javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

원격 URL 로드

원격 URL에서 데이터를 로드하려면 애플리케이션에 인터넷에 액세스할 수 있는 권한이 필요합니다. 이 권한은 애플리케이션의 매니페스트 파일에 추가해야 합니다.

  1. src/res 디렉터리에서 AndroidManifest.xml 파일을 엽니다. 닫는 </manifest> 태그 앞에 굵은 줄을 추가합니다.

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ...>
    ...
     
      </application>
      <uses-permission android:name="android.permission.INTERNET" />
    </manifest>
    
  2. 다음 단계는 WebView에서 loadUrl 메서드를 호출하는 것입니다. onCreate 메서드 끝에 다음 줄을 추가합니다.

    mWebView.loadUrl("[https://beta.html5test.com/][8]");
    

    이제 프로젝트를 실행해 봅니다. 기기가 없다면 Tools > Android > AVD Manager로 이동하여 에뮬레이터 (AVD 또는 Android Virtual Device)를 만들 수 있습니다.

탐색 처리

로드하는 URL을 https://www.css-tricks.com/로 변경하고 애플리케이션을 다시 실행해 보세요. 이상한 점이 눈에 띌 것입니다.

이제 css-tricks.com와 같은 리디렉션이 있는 사이트를 사용하여 애플리케이션을 실행하면 앱이 WebView가 아닌 기기의 브라우저에서 사이트를 열게 됩니다. 이는 예상한 결과가 아닙니다. 이는 WebView에서 탐색 이벤트를 처리하는 방식 때문입니다.

다음은 이벤트 순서입니다.

  1. WebView가 원격 서버에서 원래 URL을 로드하려고 시도하고 새 URL로 리디렉션됩니다.
  2. WebView는 시스템이 URL의 뷰 인텐트를 처리할 수 있는지 확인합니다. 시스템이 처리할 수 있는 경우 시스템이 URL 탐색을 처리하고, 그렇지 않으면 WebView가 내부적으로 탐색합니다 (예: 사용자의 기기에 브라우저가 설치되어 있지 않은 경우).
  3. 시스템은 https:// URL 스키마를 처리하기 위해 사용자가 선호하는 애플리케이션(즉, 사용자의 기본 브라우저)을 선택합니다. 브라우저가 두 개 이상 설치된 경우 이 시점에 대화상자가 표시될 수 있습니다.

Android 애플리케이션 내에서 WebView를 사용하여 콘텐츠 (예: 도움말 페이지)를 표시하는 경우 이 방법이 가장 적합할 수 있습니다. 하지만 더 정교한 애플리케이션의 경우 탐색 링크를 직접 처리하는 것이 좋습니다.

WebView 내에서 탐색을 처리하려면 WebView에서 생성된 다양한 이벤트를 처리하는 WebView의 WebViewClient를 재정의해야 합니다. 이를 사용하여 WebView가 링크 클릭 및 페이지 리디렉션을 처리하는 방식을 제어할 수 있습니다.

WebViewClient의 기본 구현은 WebView에서 모든 URL을 엽니다.

// Force links and redirects to open in the WebView instead of in a browser
mWebView.setWebViewClient(new WebViewClient());

이는 좋은 출발이지만 브라우저에서 다른 URL을 열면서 사이트의 링크만 처리하려면 어떻게 해야 하나요?

이렇게 하려면 WebViewClient 클래스를 확장하고 shouldOverrideUrlLoading 메서드를 구현해야 합니다. 이 메서드는 WebView가 다른 URL로 이동하려고 할 때마다 호출됩니다. false를 반환하면 WebView에서 URL 자체를 엽니다. 기본 구현은 항상 false를 반환하므로 이전 예에서 작동합니다.

새 클래스를 만듭니다.

  1. 앱의 패키지 이름을 마우스 오른쪽 버튼으로 클릭하고 새로 만들기 > Java 클래스를 선택합니다.
  2. 클래스 이름으로 MyAppWebViewClient를 입력하고 OK를 클릭합니다.
  3. MyAppWebViewClient.java 파일에 다음 코드를 추가합니다 (변경사항은 굵게 표시됨).

    public class MyAppWebViewClient extends WebViewClient {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if(Uri.parse(url).getHost().endsWith("css-tricks.com")) {
          return false;
        }
                   
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        view.getContext().startActivity(intent);
        return true;
      }
    }
    

    새 코드는 MyAppWebViewClientWebViewClient의 서브클래스로 정의하고 shouldOverrideUrlLoading 메서드를 구현합니다.

    shouldOverrideUrlLoading 메서드는 WebView가 URL을 로드하려고 할 때마다 호출됩니다. 이 구현은 URL의 호스트 이름 끝에 있는 문자열 'css-tricks.com'을 확인합니다. 문자열이 있으면 메서드는 false를 반환하여 플랫폼에 URL을 재정의하지 않고 WebView에 로드하도록 지시합니다.

    다른 호스트 이름의 경우 메서드는 시스템에 URL을 열도록 요청합니다. 새 Android 인텐트를 만들고 이를 사용하여 새 활동을 시작합니다. 메서드 끝에서 true를 반환하면 URL이 WebView에 로드되지 않습니다.

  4. 새 맞춤 WebViewClient를 사용하려면 MainActivity 클래스에 다음 줄을 추가합니다.

    // Stop local links and redirects from opening in browser instead of WebView
    mWebView.setWebViewClient(new MyAppWebViewClient());
    

    이제 사용자는 CSS Tricks 링크를 클릭하고 앱 내에서 계속 머물 수 있지만 외부 사이트 링크는 브라우저에서 열립니다.

Android 뒤로 버튼 처리

CSS Tricks 도움말을 둘러보고 탐색하기 시작하면 Android에서 뒤로 버튼을 클릭하면 애플리케이션이 종료됩니다.

WebView 메서드 canGoBack는 페이지 스택에 팝할 수 있는 항목이 있는지 알려줍니다. 뒤로 버튼 누르기를 감지하고 WebView의 기록을 통해 뒤로 이동해야 하는지 또는 플랫폼에서 올바른 동작을 결정하도록 허용해야 하는지 결정하려면 MainActivityonBackPressed() 메서드를 추가합니다.

public class MainActivity extends Activity {

 private WebView mWebView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     ...
 }

    @Override
    public void onBackPressed() {
      if(mWebView.canGoBack()) {
        mWebView.goBack();
      } else {
        super.onBackPressed();
      }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
       ...
    }
}

파일 시스템에서 HTML 로드

설치 가능한 애플리케이션 내에서 WebView를 사용하는 큰 이점 중 하나는 앱 내에 애셋을 저장할 수 있다는 것입니다. 이렇게 하면 WebView가 로컬 파일 시스템에서 애셋을 직접 가져올 수 있으므로 앱이 오프라인으로 작동하고 로드 시간이 개선됩니다.

HTML, JavaScript, CSS를 비롯한 파일을 로컬에 저장하려면 애셋 디렉터리에 저장합니다. Android에서 원시 파일에 사용하는 예약된 디렉터리입니다. 앱이 특정 파일을 최소화하거나 압축해야 할 수 있으므로 이 디렉터리에 액세스해야 합니다.

  1. 기본 (src/main/assets/www)에 assets/www 디렉터리를 만듭니다.

    • 웹 파일은 /assets의 하위 디렉터리에 두는 것이 좋습니다.
  2. 모든 파일을 디렉터리에 업로드합니다.

  3. 적절한 파일을 로드합니다.

    mWebView.loadUrl("file:///android_asset/www/index.html");
    
  4. 로컬이 아닌 페이지의 브라우저를 열도록 shouldOverrideUrlLoading 메서드를 업데이트합니다.

    public class MyAppWebViewClient extends WebViewClient {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if(Uri.parse(url).getHost().length() == 0) {
          return false;
        }
    
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        view.getContext().startActivity(intent);
        return true;
      }
    }
    

이제 멋진 WebView 앱을 빌드할 준비가 되었습니다.

시각적 요소를 적절하게 표시하는 방법에 관한 도움말은 WebView의 Pixel-Perfect UI를 참고하세요.

문제가 발생하면 Chrome DevTools를 사용하세요. 시작하려면 Android에서의 원격 디버깅을 참고하세요.