Trouble Shooting/Android

하이브리드앱(Android-Javascript) 간 인터페이스 방법

Gradler 2022. 6. 20. 14:33

Android WebView에서 Local/Remote 환경에 있는 Javascript와 인터페이스 하는 방식에 대해 간략히 살펴보겠습니다.

유사한 내용을 정리한 글은 찾아보면 많이 있지만 대부분 한 쪽 측면(웹 또는 네이티브)으로 작성되어 있다보니 웹 프론트 사이드에서 해야 할 일, 네이티브 사이드에서 해야 할 일을 분명하게 명시해서 어떤 지점에서 인터페이스 규약을 서로 맞춰야 하는지에 대한 관점을 우선으로 정리해봤습니다. 

 

Android > Javascript

안드로이드에서 Javascript 소스를 호출하는 방법은 두가지 방식이 있습니다. 웹프론트가 어떤 방식으로 개발됐는지에 따라 적용 가능한 방법이 다를 수 있으니 유의해주세요.

 

방법1

React.js, Vue.js와 같이 컴포넌트 기반의 SPA 방식으로 개발된 웹프론트에서 컴포넌트 라이프 사이클에 맞춰 이벤트 수신 리스너를 추가/삭제 하는 방식

 

1. (front side) 네이티브에서 호출하기 위한 함수를 CustomEvent로 만들고 window.함수명으로 할당합니다.

useEffect(() => {
    window.sayHello = new CustomEvent("NativeEvent");
    const nativeEventCallback = (event) => {
      alert(`event receive from Native`);
    };
    
    window.addEventListener("NativeEvent", nativeEventCallback);

    // event listener clean up
    return () => {
      window.removeEventListener("NativeEvent", nativeEventCallback);
    };
 }, []);

2. (native side) 네이티브에서는 webView가 제공하는 evaluateJavascript 함수로 아래와 같이 window.dispatchEvent로 웹에 생성한 함수를 호출할 수 있습니다..

webView.evaulateJavascript("window.dispatchEvent(sayHello)")

방법2

전역 scope로 생성된 함수 호출

1. (front side) 네이티브에서 호출하기 위한 모듈을 정의하고, 전역 scope에 해당하는 모듈 또는 파일에 import 시킵니다.

window.NativeInterface = {
  helloWorld: () => {
    // your javascript code
  },
  ...
}

2. (native side) 네이티브에서는 webView가 제공하는 evaluateJavascript 또는 loadUrl을 이용하여 웹에 생성된 함수를 호출할 수 있습니다. 

webView.evaluateJavascript("window.NativeInterface.helloWorld()")
// or
webView.loadUrl("javascript:window.NativeInterface.helloWorld()")

 

더보기

웹에 미리 선언된 함수만 호출할 수 있는 것은 아닙니다. 웹소스를 로드한 이후 evaluateJavascript함수로 새로운 스크립트코드를 삽입할 수도 있으며, 삽입했던 스크립트를 필요한 시점에 실행하는 것도 가능합니다. 이 말은 보안에 취약할 수 있다는 뜻입니다.

Javascript > Android

1. (native side) 웹에서 호출하기 위한 함수들을 하나의 클래스로 만듭니다. 웹에서 호출하려는 함수에는 반드시 @JavascriptInterface 어노테이션을 붙여줘야 합니다.

class JSInterface(private val context: Context) {
	@JavascriptInterface
	fun showToast(message: String) {
		// your native code
		Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
	}
	...
}

2. (native side) 1번 과정에서 만든 클래스를 webView에 연결합니다.

webView.addJavascriptInterface(JSInterface(applicationContext), "InterfaceName")

3. (front side) 웹에서는 window.클래스명.함수명과 같은 방법으로 Native에 선언된 함수를 호출할 수 있습니다.

window.InterfaceName.showToast("Hello Android")

 

이상으로 Android <-> Javascript 간 인터페이스 하는 방법에 대해 알아봤습니다.

잘못된 점이나 추가로 궁금하신 내용이 있다면 댓글로 남겨주세요.

 

iOS에서 Javascript와 인터페이스 하는 방법은 Android와 유사한 면도 있지만 조금 다른 지점도 있습니다.

웹 프론트 개발자는 플랫폼 OS별로 다르게 호출하는 부분을 모두 알고 있어야 하기 때문에 해당 글을 참고하시기 바랍니다.