지난 프로젝트에서 geolocation API를 이용하여 디바이스의 현 위치를 받아와 그 주위 장소 목록을 반환했다.
오늘은 이 API를 어떻게 이용할 수 있는지에 대해 포스팅 해볼 예정이다.
참고문서: Geolocation API MDN, Geolocation API 사용 예제 MDN
Geolocation API는 사용 시 사용자의 브라우저가 위치 데이터에 엑세스 할 수 있도록 권한을 요청하게 된다.
사용자가 허용 시 웹 어플리케이션에 자신의 위치를 제공할 수 있게 된다!
주로 사용하게 될 인터페이스는 다음과 같다.
Geolocation : 이 기본 클래스는 사용자의 현재 위치를 검색하고, 위치 변경을 감시하면서 이전에 설정된 감시를 지우는 메소드를 가지고 있다.
GeolocationPosition : 사용자의 위치를 나타내며 성공 콜백 내부에 포함된 메소드 중 하나에 대한 성공적인 호출에 의해 반환되는 인스턴스다. Geolocation 타임스탬프와 GeolocationCoordinates 객체 인스턴스를 가지고 있다.
GeolocationCoordinates : 사용자 위치의 좌표를 나타낸다. 대표적으로 위도, 경도가 있으며 기타 중요한 관련 정보를 갖고 있다.
GeolocationPositionError : 해당 인스턴스는 Geolocation 내부 메소드 중 실패한 호출 결과를 에러 메세지와 코드로 반환해준다.
그리고 다른 인터페이스로의 확장이 가능한 방법이 하나 있다.
참고로 나는 현 위치를 받아오는 코드를 작성할 때 이를 활용했다.
Navigator.geolocation
API를 사용할 수 있는 진입점으로, geolocation 객체 인스턴스를 반환하여, 다른 기능들에 접근이 가능하다!
사용자의 위치를 파악하여 좌표를 반환해주는 기능을 hook으로 따로 분리하여 사용했다.
import { useEffect, useState } from 'react';
export default function useGeoLocation(options: { timeout: number }) {
const [location, setLocation] = useState<GeolocationType>({
latitude: null,
longitude: null,
isLoading: true,
});
const [error, setError] = useState('');
const handleSuccess = (pos: GeolocationPosition) => {
const { latitude, longitude } = pos.coords;
setLocation({
latitude,
longitude,
isLoading: false,
});
};
const handleError = (err: GeolocationPositionError) => {
setError(err.message);
};
}
우선, 현 위치를 받아와 어디인지 마커를 표시해야 했기 때문에 필수적으로 위도와 경도 그리고 로딩 여부가 필요했다.
그리고 3가지의 상태값을 받을 수 있는 location 이란 상태값을 설정했다.
위도와 경도를 처음 null로 설정한 이유는 위도와 경도를 다른 숫자로 줘버리면 아예 이상한 지역으로 핑이 찍힐 수 있을 것 같았다. 그래서 아예 빈 값으로 초깃값을 설정해둔 것이다.
성공시의 콜백함수에는 GeolocationPosition 타입을 가진 pos라는 파라미터를 받는 것으로 설정해두었다.
그리고 그 pos의 coords가 가진 객체인 latitude, longitude를 받아와 location 상태값에 저장했다.
참고로 위도와 경도값이 새로 들어온다면 로딩은 모두 다 된것으로 판단하여 isLoading은 false 값으로 변경해주었다.

GeolocationPosition 타입에는 읽기 전용의 coords와 timestamp 객체를 갖고 있음을 라이브러리 파일을 통해 알 수 있다.
이는 위 인터페이스 설명에서 작성했기 때문에 다시 위로 올라가 GeolocationPosition 파트를 읽어보면 알 수 있을 것이다!
위치 변환이 잘 되지 않았을 때는 에러 메세지를 에러 전용 상태값에 저장하도록 했다.
useEffect(() => {
const { geolocation } = navigator;
if (!geolocation) {
setError('Geolocation을 사용할 수 없어요!');
return;
}
geolocation.getCurrentPosition(handleSuccess, handleError, options);
}, [options]);
return { location, error };
위 상태값 설정과 콜백함수들을 만들고나서 useEffect 코드까지 작성해야 현 위치를 받아올 수 있는 hook이 완성된다.
나는 확장가능한 인터페이스 사용을 위해
const { geolocation } = navigator;
navigator가 가진 geolocation 객체를 분해할당하여 불러와 geolocation이 가진 API를 사용할 수 있도록 했다.
만약 geolocation 객체가 인식되지 않는다면 에러 전용 상태값에 해당 API를 사용할 수 없다는 문자를 상태값에 저장했다.
정상적으로 객체가 인식되었다면, getCurrentPosition 메소드를 통해 사용자 디바이스의 현 위치를 받아왔다.
이때 getCurrentPosition 메소드에 넘겨야 하는 인수는 다음과 같다.
이렇게 useEffect 코드 작성까지 마쳤다면 해당 hook이 위도, 경도와 에러 값을 반환할 수 있도록 return 시켜주면 된다.
나는 location에 위도|경도|로딩 error에 에러문이 담겨있기 때문에 2가지의 상태값만 반환하도록 했다.
import { useEffect } from 'react';
const geoLocationOptions = {
timeout: 6000,
}
const Map = () => {
const { location } = useGeolocation(geoLocationOptions);
const currentLocation = {
latitude: location.latitude,
longitude: location.longitude,
}
useEffect(() => {
// 우리가 hook 파일의 location 상태값으로 설정해두었던 로딩여부!
if (!location.isLoading) {
window.kakao.maps.load(async () => {
// 지도 기본 설정
const mapConatiner = document.getElementById('map');
const mapOption = {
center: new window.kakao.maps.LatLng(
currentLocation.latitude,
currentLocation.longitude,
),
level: 3,
}
const map = new window.kakao.maps.Map(mapContainer, mapOption);
// 마커 표시용
const coords = new window.kakao.maps.LatLng(
currentLocation.latitude,
currentLocation.longitude,
);
const myLocationImageInfo = {
imageSrc: 본인의 마커 이미지 파일,
imageSize: new window.kakao.maps.Size(26, 26);
};
const myLocationImage = new window.kakao.maps.MarkerImage(
myLocationImageInfo.imageSrc,
myLocationImageInfo.imageSize,
null,
);
const marker = new window.kakao.maps.Marker({
position: coords,
image: myLocationImage
});
marker.setMap(map);
})
}
}, [location])
return location.isLoading? (
<Loading />
) : (
<>
<MapWrap id="map" />
</>
)
}
지도 컴포넌트에서 useGeolocation 파일을 불러와 location을 받아왔다.
우리가 hook 내부에서 만들었던 location 상태값에는 latitude, longitude, isLoading 3가지였고, 필요한 것을 추출하여 kakao map API에 적용시켰다.
그리고 사용자의 현 위치를 담은 지도를 표시할 수 있었다.
이렇게 hook으로 만들어 필요한 상태값을 가져와 사용할 수 있기 때문에 본인의 프로젝트 스타일대로 필요한 값을 추가하여 불러와 사용할 수 있다.

원래는 geolocation API를 사용하기 전, 사용자의 엑세스 권한 허용에 대해 먼저 띄워지고 허용 시 API가 실행된다.
그러나 해당 영상에서는 내가 이미 허용해놓고 여러가지를 촬영했던 영상이라 생략되었다.

원래는 이렇게 위치 허용에 대한 알림이 먼저 뜨고 API 통신이 시작된다😊