안녕하세요! 이번에 공부하실 내용은 웹 개발을 하면서 정말 재미있게 활용할 수 있는 Geolocation API (위치 정보 API) 입니다. 포트폴리오에 지도 기반의 기능이나 사용자 위치 맞춤형 서비스를 넣고 싶을 때 반드시 알아야 하는 필수 개념이죠!
문서의 모든 내용을 빠짐없이, 이해하기 쉬운 구어체로 번역해 드리고 실무에서 쓰이는 팁도 팍팍 얹어드리겠습니다. 시작해 볼까요?
[Baseline: Widely available (널리 사용 가능)]
이 기능은 이미 기술적으로 잘 자리 잡았으며 수많은 기기와 브라우저 버전에서 동작합니다. 2015년 7월부터 최신 브라우저 전반에서 사용할 수 있게 되었습니다.
🔒 보안 컨텍스트 (Secure context): 이 기능은 일부 또는 전체 지원 브라우저에서 안전한 컨텍스트(HTTPS)에서만 사용할 수 있습니다.
💡 강사의 실무 팁:
처음 프론트엔드 개발을 공부할 때 내 컴퓨터 로컬 환경(localhost나127.0.0.1)에서는 HTTP 환경이어도 이 API가 작동합니다. 하지만 나중에 완성한 프로젝트를 Vercel이나 Netlify 등을 통해 실제 웹으로 배포할 때는 반드시 HTTPS 환경이어야만 위치 정보를 가져올 수 있어요! 에러가 나면 당황하지 말고 주소창이https://인지 꼭 확인하세요.
Geolocation API는 사용자가 원할 경우 웹 애플리케이션에 자신의 위치 정보를 제공할 수 있게 해주는 API입니다. 개인정보 보호라는 아주 중요한 문제 때문에, 브라우저는 이 위치 정보를 보고하기 전에 반드시 사용자에게 접근 권한을 허용할 것인지 묻습니다.
Geolocation 객체를 사용하고자 하는 WebExtensions(브라우저 확장 프로그램)는 매니페스트(manifest) 파일에 "geolocation" 권한을 반드시 추가해야 합니다. 위치 정보 접근이 처음 요청될 때, 사용자의 운영 체제는 사용자에게 위치 접근을 허용할지 묻는 프롬프트를 띄우게 됩니다.
참고: >
<geolocation>HTML 요소는 Geolocation API의 몇 가지 단점을 해결해 주는, 위치 데이터에 접근하고 처리하는 대안적인 메커니즘을 제공합니다. 이 요소는 일관된 사용자 인터페이스(UI)와 훨씬 더 직관적인 권한 관리 프로세스를 제공합니다.
웹 앱을 만들다 보면 사용자의 위치 정보를 가져오고 싶을 때가 자주 생길 거예요. 예를 들면 지도 위에 사용자의 현재 위치를 점으로 찍어주거나, 사용자의 위치와 관련된 맞춤형 정보(주변 맛집이나 날씨 등)를 보여주기 위해서죠.
Geolocation API는 navigator.geolocation을 호출하여 접근합니다. 이 코드가 실행되면 사용자의 브라우저는 위치 데이터 접근 권한을 묻는 알림창을 띄우게 됩니다. 사용자가 수락하면, 브라우저는 기기에서 사용 가능한 가장 좋은 기능(예를 들면 GPS 등)을 활용해 이 정보에 접근합니다.
개발자는 크게 두 가지 방법으로 이 위치 정보에 접근할 수 있어요:
Geolocation.getCurrentPosition(): 기기의 현재 위치를 한 번만 가져옵니다.Geolocation.watchPosition(): 기기의 위치가 바뀔 때마다 자동으로 호출될 핸들러 함수를 등록하여, 업데이트된 위치를 계속해서 반환받습니다. (마치 네비게이션처럼 사용자가 이동하는 걸 추적할 때 씁니다.)이 두 메서드 모두 최대 3개의 인자(arguments)를 받습니다:
GeolocationPosition 객체를 유일한 매개변수(parameter)로 받습니다.GeolocationPositionError 객체를 매개변수로 받습니다.💡 강사의 실무 팁:
React나 Next.js 환경에서 포트폴리오를 만드실 때, 이 API를 그냥 쓰기보다는useGeolocation이라는 커스텀 훅(Custom Hook)으로 만들어서 빼두는 것을 강력히 추천합니다! 위도(latitude), 경도(longitude), 로딩 상태(isLoading), 그리고 에러 메시지(error)를 Zustand 같은 상태 관리 라이브러리에 저장해서 전역적으로 관리하면 지도 컴포넌트를 그릴 때 코드가 훨씬 깔끔해져요.
Geolocation 사용법에 대한 더 자세한 정보는 Geolocation API 사용하기 (Using the Geolocation API) 문서를 읽어보세요.
Geolocation
: 이 API의 메인 클래스입니다. 사용자의 현재 위치를 가져오거나, 위치 변화를 감지(watch)하거나, 이전에 설정한 감지를 취소(clear)하는 메서드들을 포함하고 있습니다.
GeolocationPosition
: 사용자의 위치를 나타냅니다. GeolocationPosition 인스턴스는 Geolocation 객체 안에 있는 메서드 호출이 성공했을 때 성공 콜백 안으로 반환되며, 타임스탬프(시간 정보)와 함께 GeolocationCoordinates 객체 인스턴스를 포함하고 있습니다.
GeolocationCoordinates
: 사용자 위치의 좌표를 나타냅니다. GeolocationCoordinates 인스턴스는 위도(latitude), 경도(longitude) 및 기타 중요한 관련 정보들을 담고 있습니다.
GeolocationPositionError
: GeolocationPositionError는 Geolocation 객체 안의 메서드 호출이 실패했을 때 에러 콜백 안으로 반환되며, 에러 코드와 에러 메시지를 포함하고 있습니다.
Navigator.geolocation
: 이 API로 진입하는 관문(Entry point)입니다. 다른 모든 기능에 접근할 수 있는 출발점이 되는 Geolocation 객체의 인스턴스를 반환합니다.
Geolocation API는 안전한 컨텍스트(HTTPS) 내에서만 프로그래밍 방식으로 위치 정보에 접근할 수 있게 해줍니다.
접근 권한은 Permissions Policy(권한 정책) 지시어인 geolocation을 통해 한층 더 제어될 수 있습니다.
geolocation의 기본 허용 목록(allowlist)은 self로 지정되어 있어서, 나와 출처(origin)가 같은 동일 출처의 중첩 프레임(same-origin nested frames)에서만 위치 정보에 접근할 수 있습니다.
제3자(서드파티) 도메인에서 이를 사용하려면 Permissions-Policy 응답 헤더를 설정해서 특정 제3자 출처에 권한을 명시적으로 부여해야 합니다:
Permissions-Policy: geolocation=(self b.example.com)
그런 다음, 해당 출처의 소스를 사용하는 iframe 요소에 allow="geolocation" 속성을 반드시 추가해야 합니다:
<iframe src="[https://b.example.com](https://b.example.com)" allow="geolocation"></iframe>
위치 데이터는 기기 소유자가 남들에게 공유하고 싶지 않은 민감한 정보를 노출할 수 있습니다.
따라서, 사용자의 권한 상태가 이미 granted(허용됨)이거나 denied(거부됨) 상태가 아닌 이상, Geolocation.getCurrentPosition()이나 Geolocation.watchPosition()이 호출될 때 프롬프트를 통해 사용자로부터 명시적인 권한을 부여받아야만 합니다.
한 번 부여된 권한이 유지되는 기간은 브라우저(사용자 에이전트)에 따라 다르며, 시간에 따라 만료되거나 세션 기반으로 유지될 수도 있고, 영구적으로 유지될 수도 있습니다.
Permissions API (권한 API)의 geolocation 권한을 사용하면 위치 정보 접근 권한이 granted(허용됨), denied(거부됨), 또는 prompt(사용자의 프롬프트 확인 필요) 상태인지 미리 테스트해 볼 수 있습니다.
예제 코드를 보시려면 Geolocation API 사용하기 (Using the Geolocation API)의 Examples 섹션을 참고하세요.
| Specification (명세) |
|---|
| Geolocation # geolocation_interface |
아래 표는 다양한 데스크톱 및 모바일 브라우저 환경에서 Geolocation API와 그 하위 메서드들이 언제부터 완전히 지원되기 시작했는지 보여줍니다. (대부분의 브라우저에서 초창기부터 지원되어 호환성이 매우 뛰어납니다!)
| 기능 (Feature) | 데스크톱 브라우저 (Desktop) | 모바일 브라우저 (Mobile) |
|---|---|---|
Geolocation (기본 객체) | Chrome (5), Edge (12), Firefox (3.5), Opera (10.6), Safari (5) | Chrome Android (18), Firefox for Android (4), Opera Android (11), Safari on iOS (3), Samsung Internet (1), WebView Android (4.4), WebView iOS (3) |
clearWatch | Chrome (5), Edge (12), Firefox (3.5), Opera (10.6), Safari (5) | Chrome Android (18), Firefox for Android (4), Opera Android (11), Safari on iOS (3), Samsung Internet (1), WebView Android (4.4), WebView iOS (3) |
getCurrentPosition | Chrome (5), Edge (12), Firefox (3.5), Opera (10.6), Safari (5) | Chrome Android (18), Firefox for Android (4), Opera Android (11), Safari on iOS (3), Samsung Internet (1), WebView Android (4.4), WebView iOS (3) |
| Secure context required (보안 컨텍스트 필수 요건 추가 시점) | Chrome (50), Edge (79), Firefox (55), Opera (37), Safari (10) | Chrome Android (50), Firefox for Android (55), Opera Android (37), Safari on iOS (10), Samsung Internet (5), WebView Android (51), WebView iOS (10) |
watchPosition | Chrome (5), Edge (12), Firefox (3.5), Opera (10.6), Safari (5) | Chrome Android (18), Firefox for Android (4), Opera Android (11), Safari on iOS (3), Samsung Internet (1), WebView Android (4.4), WebView iOS (3) |
Tip: Firefox나 WebView Android 등 일부 브라우저에서는 세부적인 구현 노트(Implementation notes)가 존재할 수 있으니 특수한 상황에선 원본 호환성 표를 꼼꼼히 체크해 주세요.
Wi-Fi 기반의 위치 정보 탐색은 구글(Google)에 의해 제공되는 경우가 많기 때문에, 중국에서는 순수(vanilla) Geolocation API를 사용할 수 없을 수 있습니다. 이럴 때는 Baidu (바이두), Autonavi (고덕지도), 또는 Tencent (텐센트)와 같은 현지의 타사(third-party) 제공업체를 사용해야 할 수도 있습니다. 이러한 서비스들은 사용자의 IP 주소나 로컬 앱을 사용하여 더 향상된 위치 파악 기능을 제공합니다.
안녕하세요! 예비 프론트엔드 개발자 여러분. 오늘 함께 정복해 볼 MDN 공식 문서는 지도나 위치 기반 서비스를 만들 때 절대 빠질 수 없는 핵심 기능, 바로 'Geolocation API 사용하기(Using the Geolocation API)' 입니다.
공식 문서가 영어로 되어 있어서 처음엔 조금 낯설 수 있지만, 걱정하지 마세요. 제가 옆에서 대화하듯 편안하게 번역해 드리고, 실무에서 겪었던 팁과 부연 설명도 아낌없이 팍팍 퍼드릴 테니까요. 자, 그럼 힘차게 시작해 볼까요?
Geolocation API는 사용자의 위치를 가져오는 데 사용됩니다. 이렇게 가져온 위치 정보는 예를 들어 지도 API를 사용해 사용자의 현재 위치를 화면에 표시하는 데 활용할 수 있죠. 이 문서에서는 Geolocation API를 사용하는 가장 기초적인 방법들을 설명합니다.
Geolocation API는 navigator.geolocation 객체를 통해 접근할 수 있습니다.
이 객체가 존재한다면, 해당 브라우저에서 위치 정보 서비스를 사용할 수 있다는 뜻입니다. 다음과 같은 코드로 위치 정보 서비스의 존재 여부를 테스트해 볼 수 있습니다:
if ("geolocation" in navigator) {
/* 위치 정보 서비스를 사용할 수 있음 */
} else {
/* 위치 정보 서비스를 사용할 수 없음 */
}
💡 강사님의 실무 팁!
"최신 브라우저들은 대부분 Geolocation을 지원하지만, 사용자의 기기에 GPS 장치가 없거나 구형 브라우저일 수 있습니다. 따라서 이if문 방어 코드는 무조건 작성하는 습관을 들이는 것이 좋습니다. 참고로, 보안상의 이유로 HTTPS 환경이 아니면 이 API가 제대로 동작하지 않는 경우가 많으니 로컬 환경에서 테스트할 때 유의하세요!"
사용자의 현재 위치를 얻으려면 getCurrentPosition() 메서드를 호출하면 됩니다. 이 메서드는 사용자의 위치를 감지하기 위해 비동기 요청을 시작하고, 위치 지정 하드웨어(GPS 등)에 질의하여 최신 정보를 가져옵니다.
위치가 성공적으로 결정되면 정의해 둔 콜백 함수가 실행됩니다. 선택적으로 두 번째 콜백 함수를 제공하여 에러가 발생했을 때 실행되게 할 수도 있습니다. 세 번째로 전달할 수 있는 선택적 매개변수는 옵션(options) 객체인데, 여기서 반환되는 위치 정보의 최대 수명(캐시 된 데이터 사용 여부), 요청을 기다릴 시간(타임아웃), 그리고 위치 정보에 대해 높은 정확도를 요구할지 여부를 설정할 수 있습니다.
📝 참고 (Note):
기본적으로,getCurrentPosition()은 정확도가 조금 떨어지더라도 최대한 빠르게 응답하려고 시도합니다. 정확도와 상관없이 빠른 답변이 필요할 때 유용하죠. 예를 들어 GPS가 장착된 기기라도 GPS 신호를 잡는 데 1분 이상 걸릴 수 있기 때문에,getCurrentPosition()에는 IP 기반 위치나 Wi-Fi를 이용한 덜 정확한 데이터가 먼저 반환될 수 있습니다.
navigator.geolocation.getCurrentPosition((position) => {
doSomething(position.coords.latitude, position.coords.longitude);
});
위의 예제 코드는 위치 정보를 성공적으로 가져왔을 때 doSomething() 함수를 실행하도록 합니다.
💡 강사님의 부연 설명:
"getCurrentPosition()은 말 그대로 일회성으로 현재 위치를 딱 한 번 가져올 때 사용합니다. '내 위치 찾기' 버튼을 눌렀을 때 지도의 중심을 이동시키는 기능 등에 찰떡이죠!"
기기가 이동하거나 더 정확한 위치 정보가 도착하는 등 위치 데이터가 변경될 때마다, 업데이트된 위치 정보를 받아 실행될 콜백 함수를 설정할 수 있습니다. 이 작업은 watchPosition() 함수를 사용하여 수행하며, 입력 매개변수는 getCurrentPosition()과 완전히 동일합니다.
이 콜백 함수는 여러 번 호출될 수 있기 때문에, 브라우저는 여러분이 이동할 때마다 위치를 업데이트해 주거나 위치를 파악하는 다양한 기술이 적용되면서 더 정확해진 위치를 계속해서 제공할 수 있습니다. getCurrentPosition()과 마찬가지로 선택 사항인 에러 콜백 함수 역시 에러가 발생할 때마다 반복적으로 호출될 수 있습니다.
📝 참고 (Note):
처음에getCurrentPosition()을 먼저 호출하지 않더라도, 곧바로watchPosition()을 사용할 수 있습니다.
const watchID = navigator.geolocation.watchPosition((position) => {
doSomething(position.coords.latitude, position.coords.longitude);
});
watchPosition() 메서드는 요청한 위치 감시자(watcher)를 고유하게 식별할 수 있는 ID 번호를 반환합니다. 사용자의 위치 감시를 중단하고 싶을 때는 이 ID 값을 clearWatch() 메서드와 함께 사용하면 됩니다.
navigator.geolocation.clearWatch(watchID);
💡 강사님의 실무 팁!
"러닝 트래커나 내비게이션 앱처럼 실시간으로 핀이 움직여야 하는 기능에는watchPosition()이 필수입니다. 하지만 주의할 점이 있어요! 계속해서 GPS를 사용하면 스마트폰 배터리가 살살 녹습니다. 😅 따라서 리액트(React) 같은 프레임워크를 쓰신다면 컴포넌트가 화면에서 사라질 때(unmount될 때) 반드시clearWatch()를 호출해서 감시를 꺼주세요. 메모리 누수와 배터리 낭비를 막는 핵심입니다."
getCurrentPosition()과 watchPosition() 모두 성공 콜백, 선택적인 에러 콜백, 그리고 선택적인 옵션 객체를 매개변수로 받습니다.
이 옵션 객체를 통해 세 가지를 설정할 수 있습니다.
1. enableHighAccuracy: 높은 정확도를 활성화할 것인지 여부
2. maximumAge: 반환된 위치 값의 최대 수명 (이 시간이 지나기 전까지 동일한 위치를 다시 요청하면 캐시 된 이전 값을 재사용하고, 이 시간이 지나면 브라우저가 신선한 위치 데이터를 새로 요청합니다.)
3. timeout: 브라우저가 위치 데이터를 가져오기 위해 대기할 최대 시간 (이 시간을 넘기면 타임아웃 에러가 발생합니다.)
watchPosition을 호출하는 코드는 다음과 같은 모습일 수 있습니다:
function success(position) {
doSomething(position.coords.latitude, position.coords.longitude);
}
function error() {
alert("Sorry, no position available.");
}
const options = {
enableHighAccuracy: true,
maximumAge: 30000,
timeout: 27000,
};
const watchID = navigator.geolocation.watchPosition(success, error, options);
사용자의 위치는 GeolocationPosition 객체 인스턴스를 사용해 설명되며, 이 객체 내부에는 또다시 GeolocationCoordinates 객체 인스턴스가 포함되어 있습니다.
GeolocationPosition 인스턴스는 딱 두 가지만 담고 있습니다.
GeolocationCoordinates 인스턴스를 담고 있는 coords 속성.timestamp 속성.GeolocationCoordinates 인스턴스는 여러 가지 속성을 가지고 있지만, 여러분이 가장 흔하게 사용할 두 가지는 지도에 위치를 그리기 위해 필요한 latitude(위도) 와 longitude(경도) 입니다. 따라서 위치 정보를 성공적으로 가져왔을 때의 콜백 함수는 대개 꽤 단순하게 생겼습니다:
function success(position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
// 위도와 경도를 가지고 원하는 작업을 수행하세요
}
하지만 GeolocationCoordinates 객체에서는 위도, 경도 외에도 고도(altitude), 속도(speed), 기기가 향하고 있는 방향(방위), 그리고 고도/경도/위도 데이터의 정확도 측정값 등 다른 정보들도 추가로 얻을 수 있습니다.
getCurrentPosition()이나 watchPosition()을 호출할 때 에러 콜백 함수를 제공했다면, 이 함수는 첫 번째 매개변수로 GeolocationPositionError 객체 인스턴스를 받게 됩니다. 이 객체 타입은 두 개의 속성을 포함합니다. 어떤 종류의 에러가 반환되었는지 나타내는 code 와, 그 에러 코드가 무엇을 의미하는지 사람이 읽을 수 있는 형태로 설명해 주는 message 입니다.
에러 콜백은 다음과 같이 사용할 수 있습니다:
function errorCallback(error) {
alert(`ERROR(${error.code}): ${error.message}`);
}
💡 강사님의 중요 팁!
"에러 처리는 선택이 아니라 필수입니다! 특히 스마트폰에서는 사용자가 '위치 정보 제공' 팝업이 떴을 때 '거부'를 누르는 경우가 생각보다 아주 많습니다. 이럴 때 에러 콜백을 제대로 작성해두지 않으면 앱이 먹통이 된 것처럼 보이겠죠? 에러 코드(error.code)가 1번이면 '권한 거부' 상태를 의미하니, 이때는 "위치 정보 권한이 필요합니다. 설정에서 허용해 주세요" 같은 친절한 UI를 보여주는 것이 프론트엔드 개발자의 센스랍니다."
다음 예제에서는 사용자의 위도와 경도를 가져오기 위해 Geolocation API를 사용합니다. 성공적으로 값을 가져오면, 사용자의 위치를 보여주는 openstreetmap.org URL을 생성하여 화면의 하이퍼링크 텍스트를 업데이트합니다.
body {
padding: 20px;
background-color: #ffffc9;
}
button {
margin: 0.5rem 0;
}
<button id="find-me">Show my location</button><br />
<p id="status"></p>
<a id="map-link" href="" target="_blank">Location unknown</a>
function geoFindMe() {
const status = document.querySelector("#status");
const mapLink = document.querySelector("#map-link");
mapLink.href = "";
mapLink.textContent = "";
function success(position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
status.textContent = "";
mapLink.href = `https://www.openstreetmap.org/#map=18/${latitude}/${longitude}`;
mapLink.textContent = `Latitude: ${latitude} °, Longitude: ${longitude} °`;
}
function error() {
status.textContent = "Unable to retrieve your location";
}
if (!navigator.geolocation) {
status.textContent = "Geolocation is not supported by your browser";
} else {
status.textContent = "Locating…";
navigator.geolocation.getCurrentPosition(success, error);
}
}
document.querySelector("#find-me").addEventListener("click", geoFindMe);
(참고: MDN 원문에서는 여기에 라이브 샘플 결과 화면이 표시됩니다.)
<geolocation> 요소 (element)어떠셨나요? 생각보다 코드가 직관적이고 다루기 쉽죠? 이 API를 잘 다루면 내 주변 맛집 찾기, 날씨 앱 등 재미있는 프로젝트를 무궁무진하게 만들 수 있습니다. 배운 내용을 바탕으로 여러분만의 멋진 지도를 한 번 띄워보시길 바랍니다. 화이팅! 🚀