안드로이드 앱(코틀린)에서 웹뷰의 JS를 호출하는 방법

crazy4u2·2020년 9월 11일
0

웹뷰로 만들어진 앱의 경우는 간혹가다 안드로이드 앱(이하 "앱")에서 웹뷰에 존재하는 JS를 호출해야하는 경우가 있다.

보통의 방법

// kotlin 코드
loadUrl("javascript:something()");

안드로이드에서는 loadUrl 이라는 method를 이용하여 미리 약속된 함수의 이름을 바로 호출할 수 있다. 위의 코드의 경우는 something이라는 이름을 가진 js 함수를 호출하여 실행시킨다. 솔직히 method의 이름도 그렇고 문법이 옛날 비표준웹개발 시대의 <a href="javascript:something()"> 하고 너무 똑같다. 그래도 잘 작동은 한다.

원래 loadUrl method 는 이름에서 알 수 있듯이 특정 url 을 불러오는 기능을 한다.

문제가 발생함

JS개발의 고도화

JS개발은 그동안 사실 좀 뭐랄까 근본이 없었다고 평가받는 시절이 있었다. 지금도 타입설정도 안하고 쓰는 근본없는 언어라고 얘기하는 사람도 있다. 이런 JS개발이 고도화 되고 클라이언트 환경이 발전하면서 JS개발은 복잡하게 변화되었다.

트랜스파일, 번들링

원래 컴파일이란 사람이 보기 좋게 되어있는 소스코드를 기계어로 바꿔서 실행가능한 파일로 만드는 작업을 지칭한다. 그래서 인터프리터인 JS의 경우는 소스가 써있는 상태로 곧바로 실행된다. 이게 대규모 개발작업 및 기타 여러문제로 JS에서도 컴파일에 개념에 놓이게 될만한 작업들을 하게 되었다. 그것이 바로 번들링과 트랜스파일 정도가 되겠다.

번들링의 경우는 모듈시스템으로 개발된 JS파일들을 하나로 묶어주고 하는 등의 작업을 하고 트랜스파일은 브라우저에서 쓰기 좋게 JS 파일을 변환하는 과정이다. 이런 경우에서 함수들이나 변수의 이름들이 브라우저에서 쓰기 좋게 쫙 바뀌어버린다. 그래서 보통 함수나 변수가 선언되고 함수를 호출하거나 변수를 사용하는 부분에 이름들이 소스 내에 있으면 알아서 같이 잘 바뀌는데 위의 보통의 방법으로 사용하기 위해 선언만 되어 있는 함수도 이름이 바뀌어버린다. 하지만 어떤 이름으로 바뀌는지 알 방법이 없어서 정해진 이름으로 호출할 수 없는 일이 벌어진다.

리액트

나는 기존에 ejs와 jquery 기반으로 작성된 코드를 react 로 바꾸고 있다. 이런 상황이다보니 번들링 등의 과정을 거치면서 바로 위에서 언급한 문제가 발생되어서 앱에서 약속된 이름으로 함수를 호출해도, 소스에 적어놔도 불러지지가 않는다. 나의 경우는 폰에 있는 뒤로가기 물리키가 눌릴 경우 backKeyPressed 라는 함수를 호출하기로 했지만 되지가 않는다.

해결방법

안드로이드에서는 함수이름을 바로 불러서 사용하는 방법도 있지만 아래와 같이 좀 더 세련되게 사용하는 방법이 있다.

// kotlin code
webView.evaluateJavascript(
  "(function() { window.dispatchEvent(backKeyPressed); })();"
) { }

이렇게 event를 dispatch 해주는 방법으로 JS를 호출할 수 있다. 이러면 웹뷰에서는

window.backKeyPressed = new Event('backKey');
window.addEventListener('backKey',() => {//do something...} , false);

이렇게 받을 수 있다.

걱정되는 문제점

과연 있을지 모르겠지만 이 방식의 문제점은 앱에서 뭔가 파라미터를 같이 담아서 JS함수를 호출해야하는 일이 생길 경우 어떻게 처리해야할지 아직 감이 안온다. 이걸 제외하면 정말 괜찮은 해결방식이다.

profile
야매로 먹고사는 프론트엔드 개발자

0개의 댓글