Daum에서 제공하는 주소찾기 서비스로 주소는 저장했는데,
이를 저장해두었다가 kakao map에 띄우기 위해서는 위도값과 경도값이 필요하다.
오늘은 이 내용에 대해서 써보려고 한다!
우선 이것을 구현하기 전에 미리 알고있어야 하는 것은
'주소찾기 api'와 '지도에 표시 및 위도경도 찾기 api'가 별개라는 것이다. 주소찾기 서비스에서는 위도경도를 함께 반환해주지 않는다 ㅠㅠ
주소찾기 api === 다음 지도찾기 서비스
지도에 표시 및 위도경도 찾기 api === 카카오 맵 api
두가지 모두 사용해야함!
그럼 시작해보자!
우선은 주소 찾기 서비스를 구현해보자.
주소를 그냥 input으로 입력받지 않고 주소찾기 api를 사용하는 이유는 뭐 당연하다.. 그냥 input 사용 시 입력에 사용자의 오류가 엄청 많아 데이터가 매우 뒤죽박죽 될 것이다.
참고 문서
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
new daum.Postcode({
oncomplete: function(data) {
// data는 사용자가 선택한 주소 정보를 모두 담고 있는 객체이다.
// 시,군,구, 도로명주소, 우편번호, 빌딩이름, 영어주소이름 등등 다 있음!
}
});
그래서 다음과 같이 주소찾기 팝업 컴포넌트를 작성했다.
import { useEffect, useRef } from 'react';
interface P {
isOpen: boolean;
handleAddressChange: (mainAddress: string) => void;
close: () => void;
}
const PostcodePopup = ({ isOpen, handleAddressChange, close }: P) => {
const ref = useRef<HTMLDivElement>(null);
const handlePostcode = () => {
new daum.Postcode({
submitMode: false,
oncomplete: (data: Oncomplete) => {
let mainAddress = '';
let zipCode = '';
mainAddress = data.roadAddress || data.jibunAddress;
zipCode = data.zonecode;
handleAddressChange(mainAddress);
close();
},
width: '100%',
height: '100%',
}).embed(ref.current);
};
useEffect(() => {
if (isOpen) {
handlePostcode();
}
}, [isOpen]);
return (
<Container>
<Header>
<div>우편번호 검색</div>
<button onClick={() => close()}>닫기</button>
</Header>
<div ref={ref} />
</Container>
);
};
export default PostcodePopup;
declare global {
interface Window {}
var daum: any;
}
여기서 부터는 약간 단계가 더 많다! 단계가 많다고 복잡한 것은 아님 ㅠㅠ
카카오 맵 api 사이트에서 app key를 발급 받는다.
마찬가지로 script src에 app key를 포함한 url 넣어주고
<script src=`//dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.NEXT_PUBLIC_KAKAO_APP_JS_KEY}&libraries=services,clusterer&autoload=false`></script>
addressSearch
이다.참고 문서
https://apis.map.kakao.com/web/documentation/#services_Geocoder_addressSearch
addressSearch() method에 대한 간단한 사용법은 아래와 같다.
1) geocoder 생성자
const geoCoder = new kakao.maps.services.Geocoder();
2) 주소찾기에서 클릭하여 얻은 string을 파라미터로 받는 함수를 만든다.
참고로 coords는 coordinates의 줄임말로, 좌표(위도와 경도)를 말함!
그리고 진짜 너무 헷갈리는데 (나만 헷갈릴 수도 있음)
X : latitude 위도
Y : longitude 경도
const getAddressCoords = (address: string) => {
return new Promise((resolve, reject) => {
geoCoder.addressSearch(address, (result: any, status: any) => {
if (status === kakao.maps.services.Status.OK) {
const coords = new kakao.maps.LatLng(result[0].x, result[0].y);
resolve(coords);
} else {
reject(status);
}
});
});
};
3) 주소 찾기에서 검색 후, 주소 선택 시 실행되는 oncomplete 함수를 일부 수정한다.
const handlePostcode = async () => {
new daum.Postcode({
submitMode: false,
oncomplete: async (data: Oncomplete) => {
let mainAddress = '';
let zipCode = '';
let x = 0;
let y = 0;
mainAddress = data.roadAddress || data.jibunAddress;
zipCode = data.zonecode;
const coords = await getAddressCoords(mainAddress);
x = coords.getLng();
y = coords.getLat();
handleAddressChange(mainAddress);
handlePosInfoChange(x, y);
close();
},
onresize: (size: { height: string }) => {
if (ref.current) {
ref.current.style.height = size.height + 'px';
}
},
width: '100%',
height: '100%',
}).embed(ref.current);
};
이리하여 완성!
다음 주소 api 및 카카오 api는 이번 프로젝트 뿐만 아니라 정말 자주 사용되는 외부 api이기 때문에 종종 들어와서 셀프 참고용으로 남겨보았다.