지도 로딩시 UX 개선을 위한 작은 트릭

HR·2022년 10월 18일
0

오동동

목록 보기
2/7
post-thumbnail

현재 오동동 서비스의 첫 화면은, 카카오 맵이 나타난다.
그 외에도,

  • 맵의 가운데는 유저의 현재 위치로 설정한다.
  • 주변 화장실의 위치를 마커로 표시한다.

등등의 과정을 초기 화면의 렌더링 시에 수행하고 있다.

하지만 위의 과정들을 비동기로 처리하는 과정에서 오류가 생기게 되었다.

1. Ionic capacitor plugin에서 제공하는 Geolocation의 속도

오동동의 프론트는 Ionic으로 구성되어 있다. Ionic의 다양한 기능을 포함하고 있는 Capacitor를 이용하여 웹앱을 만들고 있다.

현재 위치를 가져오는 과정에서 capacitor의 플러그인 중 하나인 Geolocation을 사용하고 있는데, 해당 플러그인에서 현재 위치를 가져오는 속도가 천차만별이다. 문제는 이 때 발생한다.

지도가 로드 되고,
지도의 센터를 설정하기 전에 geolocation이 완료되지 않을 경우,
null 값을 읽어오기 때문에 지도의 센터를 설정하는 부분에서 에러가 발생한다.

초기 개발 시에는 해당 에러를 정확하게 인지하지 못하고, 그냥 정상적으로 실행될 때까지 새로고침을 해 요행(?)을 바라는 방식으로 넘어갔다.

하지만 기능이 추가되고 첫 배포가 앞으로 다가오면서, 해당 기능이 발생하는 빈도가 높아졌고, 해결을 해야한다고 판단했다.

처음에 했던 생각은 아래와 같다.

💡 "현재 위치를 가져올 때까지 로딩을 걸고, geolocation에서 현재 위치를 읽어오면 해당 좌표를 중심으로 지도를 보여주자"

하지만 현재 위치를 읽어오는 시간은 길면 10초 이상이 걸리는 경우도 있었고, 그럴 경우의 user experience에 심각한 악영향을 줄 수 있겠다고 판단했다.

따라서 아래와 같은 프로세스를 통해 UX에 부정적인 영향을 최소화 하며, 에러가 발생하지 않는 방법으로 문제를 해결하였다.

  1. 우선 default 중심 좌표 값을 임의로 설정하고, 초기 지도의 렌더링 시에는 해당 좌표로 지도를 나타내준다.
  2. Geolocation의 응답을 기다리고, geolocation이 완료되어 현재 위치를 가져오게 되면 해당 위치로 지도의 중심좌표를 이동시킨다.

아래는 위의 로직을 구현한 코드이다.

kakao.maps.load(() => {
  //임의의 값으로 정해진 initLatitude, initLongitude를 중심으로 우선 지도를 띄운다.
  const options = {
      center: new kakao.maps.LatLng(this.initLatitude, this.initLongitude),
      level: this.mapLevel,
  };

  const mapRef = document.getElementById('map');
  this.map = new kakao.maps.Map(mapRef, options);
});

//Geolocation을 통해 현재 위치를 가져온다.
async getCurrentLocation() {
    const coordinates = await Geolocation.getCurrentPosition(
      {
        enableHighAccuracy: true
      }
    );

    if(coordinates.timestamp > 0) {
      this.setLatLng(coordinates.coords);
    } else {
      await this.failGetLocationAlert();
    }
}

//현재 위치를 가져온 경우 변수에 값들을 할당한다.
async setLatLng(coord: any) {
    this.currentLat = coord.latitude;
    this.currentLng = coord.longitude;
  	moveToCurrentLocation(this.currentLat, this.currentLng);
}

//그 후 지도의 중심을 변경하고, 내 위치를 나타내는 마커를 만든 뒤, 카메라를 이동시킨다.
moveToCurrentLocation(lat: number, lng: number) {
    const currentLocation = new kakao.maps.LatLng(lat, lng);
    this.addMyLocationMarker(currentLocation);
    this.map.panTo(currentLocation);
}

2. 서버와의 통신을 통해 화장실을 받아오는 과정

위의 과정 후 서버에서 화장실 목록을 가져와야 하는데, 위의 과정을 모두 완료한 뒤 서버에서 화장실 목록을 가져오고, 해당하는 위치에 마커를 찍게 되면 또 아래와 같은 문제를 일으킬 수 있다.

현재 위치를 설정하고, 지도의 중심 좌표를 다시 설정하고 카메라를 이동했는데
아직 서버에서 데이터를 읽어오지 못해
잠깐동안 화면에 아무런 마커도 표시되지 않을 수 있다.

네트워크 환경이 좋지 않을 경우, 위의 딜레이는 더욱 더 커질 수 있고, 사용자 경험에 부정적인 영향을 끼칠 가능성이 높다.

이를 위해 기존의 로직을 아래와 같이 조금 수정하였다.

  1. 우선 default 중심 좌표 값을 임의로 설정하고, 초기 지도의 렌더링 시에는 해당 좌표로 지도를 나타내준다.
  2. Geolocation의 응답을 기다리고, geolocation이 완료되어 현재 위치를 가져오게 되면 서버에 요청을 보낸다.
  3. 서버에서 요청까지 받아오면, 중심 좌표를 이동시킨다.

최종적으로, 아래와 같이 코드를 작성하였다.

kakao.maps.load(() => {
  //임의의 값으로 정해진 initLatitude, initLongitude를 중심으로 우선 지도를 띄운다.
  const options = {
      center: new kakao.maps.LatLng(this.initLatitude, this.initLongitude),
      level: this.mapLevel,
  };

  const mapRef = document.getElementById('map');
  this.map = new kakao.maps.Map(mapRef, options);
});

//Geolocation을 통해 현재 위치를 가져온다.
async getCurrentLocation() {
    const coordinates = await Geolocation.getCurrentPosition(
      {
        enableHighAccuracy: true
      }
    );

    if(coordinates.timestamp > 0) {
      this.setLatLng(coordinates.coords);
    } else {
      await this.failGetLocationAlert();
    }
}

//서버와 통신
async getBathroomList() {
    const response = await this.bathroomService.getBathroomList(this.currentLat, this.currentLng);
    if(성공시) {
      this.bathroomList = response.data.result;            
      
      //성공 시 지도의 중심 좌표를 설정하고, 카메라를 이동한다.
      this.moveToCurrentLocation(this.currentLat, this.currentLng);

      //마커들을 추가한다.
      this.addMarkers();  
    } else {
      await this.failToGetBathroomList();
    }
}


moveToCurrentLocation(lat: number, lng: number) {
    const currentLocation = new kakao.maps.LatLng(lat, lng);
    this.addMyLocationMarker(currentLocation);
    this.map.panTo(currentLocation);
}

0개의 댓글