note11g / flutter_naver_map

Naver Mobile Dynamic Map SDK for Flutter (unofficial)
BSD 3-Clause "New" or "Revised" License
143 stars 69 forks source link

Add: `NaverMap.onMapLoaded` event #166

Closed note11g closed 10 months ago

note11g commented 10 months ago

Background

지도의 로드가 완료 되었을 때, 감지할 수 있는 방법이 존재하지 않음. 이는 유저의 UX를 해칠 수 있는 가능성이 있음.

How it works

android의 경우, NaverMap.OnLoadListener callback을 사용함.

iOS의 경우, 해당 기능을 별도로 제공하지 않고 있음.

따라서, 여러가지 방식을 시도해보았으나 용량이 아주 작은(0.5\~2.5kb) 메타데이터 http request의 캐싱이 LocalStorage에 이루어질 때를 활용하는 방법이 가장 안정적이었음. 이때, 4\~8회 가량 캐시되면 해당 요청 자체를 요청하지 않는 현상이 발생하여, 강제로 해당 메타데이터만 캐싱하지 않도록 처리함. 이 메타데이터 request의 크기는 매우 작기때문에, 별도의 로드 성능 저하는 체감되지 않음.

이외에도 전체 캐시 데이터의 초기화나, 지도 타일(부분적 타일)을 활용하여 캐시맵을 만드는 등의 방안을 검토하였으나, 로드 성능 저하 혹은 캐시히트가 맞지 않는 문제로(내부적으로 캐싱을 처리하는 부분이 더 있는 것으로 추정됨) 정확한 로드 타이밍 계산이 어려워짐에 따라, 활용하기 힘들 것으로 판단함.

How to Use (now)

  1. 해당 브랜치 소스를 활용하기 위해, pubspec.yaml에 라이브러리를 다음과 같이 추가합니다.
flutter_naver_map:
  git:
    url: https://github.com/note11g/flutter_naver_map.git
    ref: onMapLoaded
  1. NaverMap위젯의 파라미터로 onMapLoaded 콜백을 전달합니다. 이때, 콜백의 타입은 dynamic Function() 입니다.
NaverMap(
  onMapLoaded: () {
    print("onMapLoaded!!");
  },
)

Test

android는 정상 작동 확인하였으며, navermap android sdk에서 지원하는 기능이므로 추가 테스트가 필수적이지는 않습니다.

iOS도 정상 작동 확인하였으나, 별도로 우회하여 구현하였으므로 테스트가 필요합니다. 따라서, 일부 테스트 케이스를 자동화한 integration test를 1/14 오전에 커밋하겠습니다. 해당 테스트가 다섯 분 이상의 기기에서 통과하면, 해당 PR을 Merge하겠습니다.

integration test로는 모든 케이스를 커버할 수 없기에, 별도로 아래 케이스들을 테스트해주시면 감사드리겠습니다.

Test Cases

  1. 앱 첫 실행시 작동여부
  2. 앱 다회차 실행시 작동여부 (NaverMapViewOptions.initialCameraPosition이 다를 때)
  3. 앱 다회차 실행시 작동여부 (NaverMapViewOptions.initialCameraPosition이 같을 때)
  4. NaverMapViewOptions.initialCameraPosition같을 때, 지도위젯을 최소 6회 이상 새로 로드하였을 때 모두 작동하는지 여부.
  5. NaverMapViewOptions.initialCameraPosition다를 때, 지도위젯을 최소 6회 이상 새로 로드하였을 때 모두 작동하는지 여부. (지도 타일이 겹치지 않는 범위에서 로드해야 합니다. zoom=14 기준으로, 위도/경도는 0.1 이상 차이나면 겹쳐지지 않는 것으로 보여짐)

다른 카메라 위치 테스트를 위한 배열 코드 공유드립니다.

static const testCameraPositions = [
    NCameraPosition(target: NLatLng(37.55, 126.914), zoom: 15),
    NCameraPosition(target: NLatLng(37.5, 127.028), zoom: 16),
    NCameraPosition(target: NLatLng(37.5, 127.035), zoom: 17),
    NCameraPosition(target: NLatLng(37.45, 126.944), zoom: 10),
    NCameraPosition(target: NLatLng(36.487, 127.26), zoom: 14),
    NCameraPosition(target: NLatLng(35.16, 129.058), zoom: 13),
    NCameraPosition(target: NLatLng(33.49, 126.496), zoom: 16),
];

// 랜덤 포지션 얻기 함수 예제. 순차적으로 가져가도 상관 없습니다.
NCameraPosition get randomCameraPosition =>
      testCameraPositions[Random().nextInt(testCameraPositions.length)];