캡스톤2를 진행하며 공공데이터를 전처리하고 난 후, 장소마다 위도와 경도만 존재하고 정확한 도로명 주소는 프론트 측에서 변환해야 했었다.
그때 사용했던 기능 중 하나인 [위도, 경도 값을 도로명 주소로 바꾸는 법]에 대해 정리해보려고 한다.
geocoding(지오코딩)이란 보통 도로명주소를 가지고 위도, 경도로 변환하는 것을 의미한다.
이번에 하려는 것은 그와 반대로, 위경도 값을 이용해 도로명주소로 변환할 것이기 때문에 Reverse geocoding이라는 것을 할 것이다.
✨필수 요소✨
나는 custom hook으로 만들어 필요한 곳에 불러와 사용하고 싶었기에 지오코딩 코드를 따로 hook 폴더에 분리하여 작성했다.
지오코딩을 위해 필요한 메소드는 kakao map API services에서 제공하는 Geocoder()
메소드, 주소 변환을 위한 coord2Address
메소드가 필요하다.
아 참고로 kakao map의 services를 사용하려면, 카카오 script 소스를 등록할 때 libraries에 services를 작성해야 한다!
<script
type="text/javascript"
src="//dapi.kakao.com/v2/maps/sdk.js?appkey=%본인 카카오맵 키%&autoload=false&libraries=services"
>
</script>
[useReverseGeoCoding.ts] hook 코드
import { useEffect, useRef, useState } from 'react';
interface ReverseGeoCodingProps {
latitude: string;
longitude: string;
placeId: number;
}
export default function useReverseGeoCoding({
latitude,
longitude,
placeId,
}: ReverseGeoCodingProps) {
const [address, setAddress] = useState('');
const latestRequestIdRef = useRef<number | null>(null);
useEffect(() => {
// 최신 요청임을 구분하기 위한 변수
const requestId = Date.now();
latestRequestIdRef.current = requestId;
window.kakao.maps.load(() => {
const geocoder = new window.kakao.maps.services.Geocoder(); // geocoder 설정
// 2. coord2Address가 실행되며 콜백으로 실행시킬 reverseGeocoding 함수
// geoding 돌릴 함수 -> 파라미터에는 응답으로 받아올 것들의 타입넣기
const reverseGeocoding = async (res: GeolocationAddress[], status: boolean) => {
if (status === window.kakao.maps.services.Status.OK) {
if (latestRequestIdRef.current === requestId) {
// 통신 상태, 최신 요청임을 모두 만족할 때 주소값 상태변경
await setAddress(res[0].address.address_name);
}
} else {
console.error('주소 변환 실패!');
}
};
// 1. 위도, 경도 모두 잘 넘어왔을 때 coord2Address 실행!
if (latitude !== undefined && longitude !== undefined) {
geocoder.coord2Address(Number(longitude), Number(latitude), reverseGeocoding);
}
});
}, [placeId]);
return { address };
}
hook인 만큼 불러오는 곳에서 위도와 경도를 넘겨줄 수 있도록 latitude, longitude 타입을 설정하여 파라미터에 넣었다.
그리고 나는 해당 hook을 장소 상세 페이지에서 사용할 예정이었기 때문에, 장소 상세 Id값이 달라질 때만 지오코딩 함수가 실행되도록 placeId도 받아와 useEffect의 dependency에 넣어주었다.
coord2Address : 좌표를 주소로 변환하는 메소드
첫 번째 인수: 경도값 | 두 번째 인수: 위도값 | 세 번째 인수: 콜백함수
도로명 주소값을 찾기 위해 콘솔로 확인한 결과, res[0].address.address_name
로 값을 받아오면 된다는 것을 알았다.
이제 필요한 페이지에 만들어둔 리버스 지오코딩 훅을 불러오려고 한다.
const ExplainPage = () => {
const { isLoading, data } = useGetInfoByPlaceId(Number(location.pathname.match(/\/place\/(\d+)/)?.[1]));
const placeInfo = data.data.result as PlaceType;
const address = useReverseGeoCoding({
latitude: placeInfo?.latitude,
longitude: placeInfo?.longitude,
placeId: placeInfo?.id,
});
return (
<ExplainPageWrap>
{isLoading ? (
<Loading />
) : (
/* 생략 */
<DefaultExplain placeInfo={placeInfo} address={address.address} />
/* 생략 */
)}
{toast && <Toast>찜 기능은 로그인 후 이용해주세요!</Toast>}
</ExplainPageWrap>
)
}
해당 컴포넌트에서 useReverseGeoCoding 훅을 불러와 필요한 파라미터 값에 따라 인수를 전달한다.
hook에서는 address string 상태값을 반환하기 때문에 필요한 컴포넌트에 바로 전달할 수 있게 된다!
빨간 선을 보면, 위도 경도를 이용해 도로명주소로 변환된 한 장소를 볼 수 있다~!