HTML5 Geolocation API의 정확도 한계와 위치 오차를 다루는 방법
웹사이트에서 "위치 정보 사용을 허용하시겠습니까?"라는 창을 본 적이 있을 것입니다. 허용하면 사이트는 브라우저의 Geolocation API를 통해 현재 위치의 위도·경도를 받습니다. 그런데 같은 자리에 있어도 어떤 때는 몇 미터 이내로 정확하고, 어떤 때는 몇 킬로미터 떨어진 동네가 표시되기도 합니다. 이 글에서는 브라우저가 위치를 얻는 방식, 결과에 포함된 정확도 값을 읽는 법, 그리고 개발할 때 자주 하는 실수를 정리합니다.
1. 브라우저는 위치를 어떻게 알아낼까
W3C Geolocation 명세는 위치를 어떤 방법으로 구할지 정하지 않습니다. 명세는 API가 위치 정보의 출처와 무관하며, 반환된 위치가 기기의 실제 위치라고 보장하지 않는다고 설명합니다. 실제 측정은 브라우저와 운영체제가 사용할 수 있는 수단을 조합해 처리하며, 일반적으로 다음과 같은 정보가 쓰입니다.
- 위성 신호(GPS 등): 하늘이 트인 실외에서는 정확도가 높은 편이지만, 실내나 고층 건물 사이에서는 신호가 약해지거나 반사되어 오차가 커질 수 있고, 첫 위치를 잡는 데 시간이 걸리기도 합니다.
- 주변 Wi-Fi 정보: 주변 무선 공유기의 식별 정보와 신호 세기를 위치 데이터베이스와 대조해 위치를 추정합니다. 공유기가 많은 도심 실내에서 유용합니다.
- 이동통신 기지국 정보: 연결된 기지국을 기준으로 대략적인 위치를 추정합니다. 기지국 간격에 따라 오차가 수백 미터 이상으로 커질 수 있습니다.
- IP 주소: 데스크톱처럼 다른 정보가 없을 때 쓰일 수 있으며, 도시나 지역 수준의 대략적인 위치만 알 수 있는 경우가 많습니다.
어떤 수단이 쓰였는지는 API가 알려 주지 않습니다. 대신 결과와 함께 제공되는 accuracy 값으로 결과를 얼마나 믿을 수 있는지 판단할 수 있습니다.
2. 기본 사용법과 옵션
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude, accuracy } = position.coords;
showLocation(latitude, longitude, accuracy);
},
(error) => {
// error.code: 1 PERMISSION_DENIED, 2 POSITION_UNAVAILABLE, 3 TIMEOUT
showLocationError(error.code);
},
{
enableHighAccuracy: true, // 가능하면 더 정확한 위치를 원한다는 "힌트"
timeout: 10000, // 10초 안에 못 받으면 TIMEOUT 오류
maximumAge: 60000, // 1분 이내에 얻은 위치면 캐시 재사용 허용
}
);
- enableHighAccuracy: 명세상 힌트일 뿐이라 브라우저가 무시할 수 있습니다. 켜면 응답이 느려지거나 배터리를 더 쓸 수 있습니다.
- timeout: 기본값은 사실상 무제한이므로, 직접 지정하지 않으면 응답을 오래 기다릴 수 있습니다.
- maximumAge: 기본값은 0이라 항상 새 위치를 요청합니다. 날씨처럼 몇 분 전 위치로도 충분한 서비스라면 값을 늘려 응답 속도를 높일 수 있습니다.
3. accuracy 값 읽는 법
accuracy는 미터 단위이며, 명세는 이를 95% 신뢰 수준의 값으로 정의합니다. 예를 들어 위도 37.5665, 경도 126.9780, accuracy 1500이 반환되었다면 "실제 위치가 이 점을 중심으로 반지름 약 1.5km 원 안에 있을 가능성이 95% 정도"라는 뜻입니다. 이 경우 표시된 좌표 자체보다 원의 크기가 더 중요한 정보입니다.
좌표 숫자로 감 잡기 (서울 부근)
- 위도 0.001° 차이: 약 111m
- 경도 0.001° 차이: 약 88m (위도가 높을수록 짧아집니다)
- 따라서 소수점 넷째 자리 정도의 변화는 수 미터 수준의 흔들림일 수 있습니다.
4. 흔들리는 위치를 다루는 방법
watchPosition()으로 위치를 계속 받으면, 가만히 있어도 좌표가 조금씩 바뀝니다. 이를 그대로 반영하면 화면이 불필요하게 자주 갱신됩니다. 일반적으로 다음과 같은 방법을 씁니다.
- 정확도 기준 적용:
accuracy가 서비스에 필요한 수준보다 크면 결과를 사용하되 "대략적인 위치"라고 안내하거나, 더 나은 결과를 잠시 기다립니다. - 이동 거리 기준 적용: 이전 위치와 새 위치 사이의 거리를 계산해 일정 거리 이상 움직였을 때만 갱신합니다.
위치를 계속 받을 필요가 없어지면 watchPosition()이 돌려준 번호로 navigator.geolocation.clearWatch(id)를 호출해 감시를 멈춰야 배터리 소모를 줄일 수 있습니다.
두 지점 사이의 거리는 지구를 구로 가정한 하버사인(Haversine) 공식으로 계산할 수 있습니다. 짧은 거리에서는 오차가 작아 이런 용도에 충분합니다.
function haversineDistance(lat1, lon1, lat2, lon2) {
const R = 6371e3; // 지구 평균 반지름(m)
const toRad = (deg) => (deg * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a =
Math.sin(dLat / 2) ** 2 +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;
return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
haversineDistance(37.5665, 126.978, 37.5675, 126.978); // 약 111m
5. 자주 하는 실수
- HTTP 페이지에서 호출하기: Geolocation API는 보안 컨텍스트(HTTPS, 개발 중의 localhost 등)에서만 동작합니다. HTTP 페이지에서는 권한 거부 오류로 처리됩니다.
- 페이지를 열자마자 권한 요청하기: 이유를 모르는 사용자는 거부하기 쉽습니다. "내 위치 날씨 보기" 버튼처럼 사용자의 동작에 맞춰 요청하는 편이 좋습니다.
- 오류 콜백 생략: 권한 거부, 위치 불가, 시간 초과는 흔히 일어납니다. 지역을 직접 선택하는 대체 수단을 준비해 둡니다.
- accuracy를 무시하기: 좌표만 보고 동네를 단정하면, IP 기반처럼 오차가 큰 결과에서 엉뚱한 지역이 표시될 수 있습니다.
- 위치 데이터 과도한 저장: 위치는 민감한 개인정보입니다. 필요한 정밀도와 기간만큼만 다루는 것이 원칙입니다.
6. 정리
Geolocation API는 위치를 구하는 방법을 정하지 않으며, 결과의 신뢰도는 accuracy(95% 신뢰 반경, 미터)로 판단해야 합니다. HTTPS 환경, 명확한 권한 요청, 오류 처리, 정확도와 이동 거리 기준을 갖추면 위치 기반 기능을 훨씬 안정적으로 만들 수 있습니다.
HereWeather도 위치 권한을 허용하면 현재 위치의 행정동을 표시하고 그 위치의 예보를 불러옵니다. 실내나 고층 건물 사이에서는 표시된 동네가 실제와 다를 수 있으니 먼저 확인하는 것이 좋습니다. 받은 위도·경도가 어떤 좌표계인지는 WGS84와 UTM-K 비교에서 설명합니다.