본 게시물에서는 지도에서 특정 위치를 클릭하여 좌표를 가져온 후, 좌표에서 주소로 변환하는 작업을 기록하였다.
오픈 API를 적용해보면 알겠지만, 블로그만 보고 코드를 복사 붙혀넣기 하거나 대충 메서드의 역할만 파악하고 코드를 치면 안된다. 카카오 지도 API 문서에는 내가 사용하고 싶었던 기능을 친절하게 샘플과 코드 예시로 보여주지만, 무턱대고 복사 붙여넣기 하면 이 API를 30%도 제대로 사용하지 못 할 것이다.(잘못하면 한 주를 낭비한다.) 만약 이런 오픈 API를 사용하는 방법을 잘 모른다면 "나는 시간이 없으니 필요한 것만 딱 뽑아서 봐야지" 라는 생각은 접어두면 좋다.
항상 차근차근 API의 시작단계부터 공부하는 것을 추천한다. 카카오 지도의 시작단계는 지도 생성하기 이기 때문에 꼭 지도를 생성하는 메서드를 본 후 샘플을 보기 바란다.
지도 생성하기 API로 생성된 지도 위에서 클릭을 하여 주소를 가져오고 싶거나, 지도를 이동시켜 범위 밖에 있던 마커를 나타내주고 싶다면 이벤트를 걸어주면 된다.
click 이벤트는 지도를 클릭하면 발생한다.
Map - events - clickkakao.maps.event.addListener(target, 'eventName', listener);
이벤트 리스너의 첫번째 인자로는 클릭 대상, 두번째 인자로는 이벤트 이름, 세번째로는 지도에서 이벤트가 발생하였을 때 실행될 콜백 함수를 넣어준다. 지도의 이벤트는 클릭을 제외하고도 이동 이벤드, 확대 이벤트, 영역 변경 이벤트 등이 있다.
클릭 이벤트의 listener를 담당하는 콜백함수에는 mouseEvent라는 인자가 하나 들어오는데 이 인자로 지도 좌표(latLng) 및 화면 좌표(point)를 가져올 수 있다.
kakao.maps.event.addListener(map, 'click', function(mouseEvent: any) { console.log(mouseEvent.latLng) })
더알아보기 - 카카오 지도 문서 MouseEvent
Geocoder constructor는 주소-좌표간 변환 서비스 객체를 생성한다.
let geocoder = new kakao.maps.services.Geocoder();
constructor이기 때문에 새로운 생성자로 만들어 준 다음, 주소 - 좌표간 변환 메서드를 사용할 수 있다.
카카오 지도 문서 Geocoder Method
let geocoder = new kakao.maps.services.Geocoder(); geocoder.coord2Address(x, y, callback, options)
const coords = mouseEvent.latLng
const callback = (result: {[key:string]: any}, status: any) => {
if(status === kakao.maps.services.Status.OK) {
console.log(result);
}
}
coords2Address(coords.getLat(), coords.getLng(), callback)
지도 위에 주소를 띄우기 위해 해야 할 일은, 클릭한 지점 위에 주소를 표시해줄 인포윈도우(infoWindow) 나 커스텀 오버레이(CustomOverlay)위에 주소를 넣어주는 것이다. 인포윈도우보다 커스텀 오버레이가 더 폼나보이지만 심플해보이는 인포윈도우로 우선 주소를 띄워보겠다.
주어진 객체로 인포윈도우를 생성한다.
지도 뿐만 아니라 로드뷰 위에도 올릴 수 있다.let infowindow = new kakao.maps.InfoWindow(options);
하나의 객체이며 new 키워드로 생성하여 메서드를 사용할 수 있다.
// 도로명이 있다면 도로명을, 없다면 지번주소를 인포윈도우에 띄워준다.
const address = result[0].road_address
? result[0].road_address.address_name
: result[0].address.address_name;
// 인포윈도우를 생성해준다.
const infowindow = new kakao.maps.InfoWindow({
map,
position: new kakao.maps.LatLng(coords.getLat(), coords.getLng()),
content: '<div>' + address + '</div>',
});
infowindow.open(map);
여기까지 인포윈도우를 생성하는 과정이였다. 하지만 여기서 끝내면 클릭하는 곳마다 인포윈도우가 생겨나고 여러개의 인포윈도우가 겹칠 것이다. 인포윈도우를 열기만 하고 닫지를 않았기 때문이다.
카카오 지도 API에는 지도에 표시되어 있는 모든 인포윈도우를 삭제해버리는 메서드는 따로 없기 때문에 다른 방법을 사용해야한다.
배열을 임의로 만들어 인포윈도우를 배열 안에 넣고 하나하나 돌면서 지도에 보이지 않게 숨겨주어야 한다.
먼저, 배열을 선언 및 초기화할 때에는 선언하는 위치를 잘 확인해야 한다. 아래 예제에서는 가독성을 위해 인포윈도우를 생성하기 바로 전에 초기화하지만, 코드 구조에 따라 초기화를 잘 해주어야 한다. 인포윈도우를 지도에서 지우기도 전에 빈배열로 초기화 시켜버리면 모든 인포윈도우가 남아있을 것이다.
인포윈도우를 생성하고 지도에 표시 할 때마다 infos 배열에 인포윈도우 객체를 넣어준다.
let infos: any = [];
// 인포윈도우 생성
const infowindow = new kakao.maps.InfoWindow({
map,
position: new kakao.maps.LatLng(coords.getLat(), coords.getLng()),
content: '<div>' + address + '</div>',
});
// 인포윈도우 지도에 표시
infowindow.open()
infos.push(infowindow);
배열에 인포윈도우가 잘 들어갔는지 확인 한 다음, 인포윈도우를 숨겨주는 removeInfos 함수를 만든다. 이 함수는 infos배열안에 들어있는 인포윈도우를 하나하나 돌아가면서 API에서 제공해주는 메서드인 infowindow.close()를 사용해 인포윈도우를 전부 닫아주는 함수이다. 다 닫았으면 배열도 초기화 해준다.
const removeInfos = () => {
infos.forEach((info: any) => info.close());
infos = [];
}
let infos: any = [];
const removeInfos = () => {
infos.forEach((info: any) => info.close());
infos = [];
}
const infowindow = new kakao.maps.InfoWindow({
map,
position: new kakao.maps.LatLng(coords.getLat(), coords.getLng()),
content: '<div>' + address + '</div>',
});
// 인포윈도우 하나 띄우기 전에 이전에 있던 인포윈도우 숨기기
removeInfos()
infos.push(infowindow);
infowindow.open()
다음 게시물에서는 키워드 검색으로 관련된 장소들을 마커를 표시하고, 마커 클릭 시 인포윈도우를 띄우는 과정을 정리해보겠다.