본문 바로가기
Flutter

[Flutter & kakao_map] "Uncaught ReferenceError: init is not defined

by Banlim 2020. 9. 24.

[삽질의 기록]

 

 

 

kakao map api를 이용하여 flutter의 webview에 지도를 보여주는 프로젝트를 진행했다. 실제로 지도는 javascript에서 그리며, flutter에서 javascript에 있는 init(lat, lng); 함수를 호출하면서 지도가 나타나기 시작한다. kakao map은 임의의 위치를 기준으로 지도를 그리기 때문에, 위치가 주어지지 않으면 지도가 그려지지 않고 흰색 화면만 보이는 현상이 나타난다.

 

이 때, 위와 같은 에러가 발생하며 지도가 뜨지 않고 흰색 화면만 나타나는 현상이 3번 중 1번 꼴로 발생했다. 원인을 분석한 결과, kakao map을 그리는 javascript page가 다 load 되기도 전에 device(flutter)에서 init(lat, lng);를 요청해서 생기는 것이다. init(lat, lng)를 호출하고 보니까 그 page가 다 load 되지 않았으니 당연히 init이 정의되지 않은 것이다.

 

해당 Issue를 해결하기 위해 여러가지 방법을 고민하고 적용해보았다.

init(lat, lng) 함수는 아래와 같다.

function init(lat, lng){
	isCurSearch = false;
	var locPosition = new kakao.maps.LatLng(lat, lng);	
	this.locPosition = locPosition
	drawMarker(locPosition);
}

 

case 1 : html 파일의 <body> 에 <body onload="init(lat, lng)">를 삽입한다.

case 2 : init() 함수의 호출 flag 변수를 두어, flag == false이면, init(lat, lng); 한다.

 

: : case 1, 2의 경우 코드 한줄로 간단하게 해결할 수 있으나, load가 성공적으로 될 경우, 사전에 정의된 좌표로 지도를 그렸다가 현 위치로 돌아가는 새로운 버그가 발생한다는 문제가 있다. 

 

case 3 : flutter에서 onWebViewCreated()에서 init()을 호출하지 말고, Webview가 로드된 다음, 즉 onPageFinished()에서 호출하도록 처리한다.

 

: : case 3의 경우 case 1, 2에서 생기는 버그는 잡을 수 있었다. 또한 흰색 화면만 나타나는 현상은 없어지긴 했다. 하지만, 간혹 타이밍이 맞지 않으면, Uncaught ReferenceError가 뜨면서 화면이 깜빡이는 현상이 나타난다. Uncaught ReferenceError를 해결하는 것 또한 중요한 문제였기 때문에 다른 방법을 고민해보았다.

 

case 4 : case 3과 동일하나, flutter의 _getCurrentPosition() 함수가 끝난 다음 javascript의 init()을 호출하기 전 2초정도 delay를 걸어주고, init(lat, lng)를 호출한다.

 

: : case 4의 경우, case 1, 2, 3에 비해 부드럽고 유연하게 대응한다는 것을 발견했다. 하지만, 깔끔하게 처리할 수 있는 방법을 해당 프로젝트에 적용하기 위해 조언을 구했다.

 

case 5 : case 4와 흡사하나, flutter에서 webviewController.evaluateJavascript를 통해 init()을 호출한 후 .then((value) ~~ ) 를 사용하여 init에서 넘어온 return 값이 null일 경우 고정된 위치를 넣어 지도를 띄우도록 했고, 아닐 경우 현 위치로 반환하여 그리는 것으로 수정했다.

 

: : 기존 init() 함수에는 return값을 따로 반환하지 않았다. case 5를 적용하기 위해 init() 함수에

function init(lat, lng){
    . . .
    return true;
}

라인을 추가하여 init()이 실행되면 true값을 반환하도록 설정했다. case 4를 적용했을 때에는 catchError에서 고정된 위치를 주도록 구현했는데, 이 방법은 case 5에 비해 코드가 깔끔하지 못했다는 점이 존재하였다. case 5는 case 4 대비 효율적으로 코드를 작성할 수 있었고, Uncaught ReferenceError를 해결할 수 있었다.

 

다음은 case 5를 적용하여 flutter에서 javascript의 init()을 호출하는 코드이다.

_webViewController.evaluateJavascript(
	'init(${lat}, ${lng})').then((value) {
     	setState(() {
        	if(value == null){
        	// 서울고속터미널 좌표
          		_webViewController
              		.evaluateJavascript('init(${37.505037}, ${127.004945})');
       	}
        _isGetCurrentPosition = true;
   });
});