사용자의 위치 정보를 Geolocation API를 사용하여 위도, 경도를 받아오고 이를 네이버 API를 활용해 도로명 주소를 가져오는 방법입니다.
useAddress 훅 구현우선, 사용자의 위치 정보를 가져오는 훅을 만들어보겠습니다. 이 훅은 navigator.geolocation API를 사용하여 사용자의 현재 위치를 얻고, 이를 상태로 관리합니다.
import { useState, useEffect } from 'react';
export interface ILocation {
latitude?: number;
longitude?: number;
}
export const useGeoLocation = (options = {}) => {
const [location, setLocation] = useState<ILocation>({
longitude: 0,
latitude: 0,
});
const [error, setError] = useState('');
// 위치 정보를 성공적으로 가져왔을 때 실행되는 함수
const handleSuccess = (pos: GeolocationPosition) => {
const { longitude, latitude } = pos.coords;
setLocation({
longitude,
latitude,
});
};
// 위치 정보를 가져오는 데 실패했을 때 실행되는 함수
const handleError = (err: GeolocationPositionError) => {
setError(err.message);
};
useEffect(() => {
const { geolocation } = navigator;
if (!geolocation) {
setError('Geolocation is not supported.');
return;
}
geolocation.getCurrentPosition(handleSuccess, handleError, options);
}, [options]);
const getLocation = () => {
const { geolocation } = navigator;
if (!geolocation) {
setError('Geolocation is not supported.');
return;
}
geolocation.getCurrentPosition(handleSuccess, handleError, options);
};
return { location, getLocation, error };
};
위 코드에서 useGeoLocation 이라는 커스텀 훅을 만들었습니다. 이 훅은 사용자 위치를 가져오는 getLocation 함수와 현재 위치 정보를 담은 location 상태, 그리고 오류 메시지를 반환하는 error 상태를 관리합니다.
useAddress 훅 구현다음으로, 위에서 만든 useGeoLocation 훅을 활용하여 사용자의 위치를 기반으로 도로명 주소를 가져오는 useAddress 훅을 만들어 보겠습니다.
import { useState, useEffect } from 'react';
import { getAddress } from '@/app/services/address';
import { useGeoLocation } from './useGeoLocation';
const geolocationOptions = {
enableHighAccuracy: true,
timeout: 1000 * 10,
maximumAge: 1000 * 3600,
};
export const useAddress = () => {
const { location, getLocation, error } = useGeoLocation(geolocationOptions);
const [address, setAddress] = useState<any>(null);
useEffect(() => {
const fetchAddress = async () => {
if (location.longitude !== 0 && location.latitude !== 0) {
const result = await getAddress(location);
setAddress(result);
}
};
fetchAddress();
}, [location]);
return { location, address, getLocation, error };
};
useAddress 훅은 useGeoLocation 훅을 사용해 사용자의 현재 위치를 얻은 후, getAddress 함수를 호출하여 해당 위치의 도로명 주소를 가져옵니다. 이 훅은 위치 정보, 도로명 주소, 위치 정보를 갱신하는 함수, 그리고 오류 메시지를 반환합니다.
getAddress 함수 구현마지막으로, 네이버 클라우드 플랫폼의 GeoCoding API를 활용하여 위도와 경도를 도로명 주소로 변환하는 getAddress 함수를 구현해보겠습니다.
import { ILocation } from '../hooks/useGeoLocation';
export const getAddress = async ({ longitude, latitude }: ILocation) => {
try {
const res = await fetch(
`/v2/gc?coords=${longitude},${latitude}&output=json&orders=addr`,
{
method: 'GET',
headers: {
'X-NCP-APIGW-API-KEY-ID': process.env
.NEXT_PUBLIC_NAVER_NCLOUD_ACCESS_KEY_ID as string,
'X-NCP-APIGW-API-KEY': process.env
.NEXT_PUBLIC_NAVER_NCLOUD_SECRET_KEY as string,
},
next: { revalidate: 600 },
},
);
if (!res.ok) throw new Error('Failed to fetch data');
const data = await res.json();
return data;
} catch (error) {
return error;
}
};
이 함수는 getAddress라는 이름의 비동기 함수로, ILocation 타입의 객체를 매개변수로 받습니다. 이 객체에는 longitude(경도)와 latitude(위도) 속성이 포함되어 있습니다.
다음으로, fetch 함수를 사용하여 네이버 클라우드 플랫폼의 GeoCoding API에 GET 요청을 보냅니다. URL에는 경도와 위도가 포함되며, JSON 형식의 출력과 주소 정보를 요청합니다.
API 요청 헤더에 네이버 클라우드 플랫폼의 인증 키를 포함시킵니다. 이 키들은 환경 변수에서 가져오며, 보안을 위해 직접 코드에 하드코딩하지 않습니다.
구현된 getAddress 함수는 위도와 경도 정보를 받아 해당 위치의 주소 정보를 반환합니다.
이번 포스트에서는 React(Next.js)에서 사용자의 위치 정보를 얻고, 이를 바탕으로 도로명 주소를 가져오는 방법을 알아보았습니다. useGeoLocation과 useAddress 커스텀 훅을 사용하면 사용자의 위치 기반 서비스를 손쉽게 구현할 수 있습니다.
다만, 구현 후 깨달은 중요한 점은 getAddress 함수가 프론트엔드보다는 백엔드에서 구현되어야 했다는 것입니다. 초기에는 네이버 OPEN API를 직접 사용하여 주소 변환을 하는 것이 더 효율적이라고 판단했습니다. 백엔드를 거쳐 위도와 경도를 보내고 다시 도로명 주소로 변환하여 받는 과정이 불필요해 보였기 때문입니다.
그러나 실제 구현 후, API 키의 보안 문제, CORS 에러 해결의 어려움, 그리고 클라이언트의 부하 증가 등의 문제점을 직면하게 되었습니다. 이로 인해 이러한 기능은 백엔드에서 처리하는 것이 더 적절하다는 것을 깨달았습니다.
이 경험을 통해 기능 구현 위치의 중요성과 전체적인 아키텍처 설계의 필요성을 다시 한번 인식하게 되었습니다. 앞으로는 이러한 결정을 내릴 때 더 신중하고 종합적인 고려가 필요하다는 교훈을 얻었습니다.