가까운 순서를 정하기 전에

매장 목록에 “가까운 순”을 붙이려면 먼저 어떤 거리를 보여줄지 정해야 합니다. 두 좌표를 구면 위에서 잇는 거리는 주변 장소를 비교하는 데 쓸 수 있지만, 도로와 횡단보도를 따라 걷는 길이는 알 수 없습니다. 하천 반대편의 매장이 숫자로는 가까워도 실제 방문은 오래 걸릴 수 있습니다.

바쿠오의 로컬 소스 중 demo/src/utils/haversine.ts에서 하버사인 계산을 확인했습니다. 아래 코드는 같은 계산 방식을 설명하기 위해 입력 검사와 수치 범위 보정을 더한 독립 예제입니다. 공개 서비스의 현재 버전이나 측정 성능을 재현한 코드는 아닙니다.

좌표에 이름을 붙이는 이유

위도와 경도는 각도입니다. 위도 차이와 경도 차이를 그대로 피타고라스 공식에 넣으면 위도에 따른 동서 길이 차이를 놓칩니다. 계산 전에 도를 라디안으로 바꾸고 구면 공식에 넣습니다.

배열의 첫 숫자가 무엇인지도 API마다 확인해야 합니다. GeoJSON의 position은 경도·위도 순서지만, Leaflet의 LatLng는 위도·경도 순서를 받습니다. 예제는 { lat, lng }를 사용해 호출부에서 순서를 읽을 수 있게 했습니다. 0은 유효한 좌표이므로 “값이 없다”는 검사로 걸러서는 안 됩니다.

직접 실행하는 거리 계산

아래 전체 코드를 최신 브라우저 개발자 도구의 콘솔이나 Node.js에서 실행할 수 있습니다. 좌표는 실제 매장이 아닌 계산 확인용 점입니다. 반지름 6,371km인 구를 가정하며, distanceKm의 반환 단위는 km입니다.

function distanceKm(a, b) {
  for (const point of [a, b]) {
    if (!point || !Number.isFinite(point.lat) || !Number.isFinite(point.lng)) {
      throw new TypeError('Expected numeric lat and lng');
    }
    if (Math.abs(point.lat) > 90 || Math.abs(point.lng) > 180) {
      throw new RangeError('Coordinates outside latitude/longitude range');
    }
  }
  const rad = degrees => degrees * Math.PI / 180;
  const dLat = rad(b.lat - a.lat);
  const dLng = rad(b.lng - a.lng);
  const raw = Math.sin(dLat / 2) ** 2
    + Math.cos(rad(a.lat)) * Math.cos(rad(b.lat))
    * Math.sin(dLng / 2) ** 2;
  const h = Math.min(1, Math.max(0, raw));
  return 6371 * 2 * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h));
}

const a = { lat: 0, lng: 0 };
const b = { lat: 0, lng: 1 };
console.log(distanceKm(a, a)); // 0
console.log(distanceKm(a, b).toFixed(3)); // 111.195

첫 출력은 0, 두 번째는 111.195입니다. 마지막 값은 적도에서 경도 1도 떨어진 두 점에 대해 이 모델이 계산한 결과입니다. 실제 지구의 타원체 거리나 보행 거리를 검증한 값으로 쓰면 안 됩니다.

정상 입력과 오류 입력 확인하기

  1. 두 인수를 같은 점으로 주면 0인지 확인합니다.
  2. a와 b의 순서를 바꿔도 같은 거리가 나오는지 확인합니다.
  3. { lat: "0", lng: 1 }은 숫자 대신 문자열이므로 TypeError가 나야 합니다.
  4. { lat: 127, lng: 37 }은 위도 범위를 벗어나므로 RangeError가 나야 합니다.

두 좌표가 모두 숫자이고 범위 안에 있어도 올바른 매장을 가리킨다는 보장은 없습니다. 위도·경도 뒤집힘이 범위 검사에 걸리지 않는 지역도 있습니다. 입력 형식 검사는 출처 좌표를 검증하는 일을 대신하지 않습니다.

지도에서 이동 경로 확인하기

목록에는 “직선거리”처럼 계산의 의미를 적고, 상세 방문 경로는 지도 서비스에서 확인하게 하는 편이 명확합니다. 예상 이동시간을 이 숫자에 임의 배수를 곱해 만들어 표시하지 않습니다. 실제 길찾기는 이동 수단과 도로망을 아는 서비스가 처리해야 합니다.

좌표가 없는 매장은 0km로 보여주지 말고 “거리 정보 없음”으로 구분해야 합니다. 반대로 원점과 같은 좌표를 가진 매장은 유효한 0km일 수 있습니다. 외부 지도 링크를 만드는 글에서는 좌표를 목적지로 전달할 때 확인할 내용을 이어서 설명합니다.

바쿠오 · 사용 안내 →