window
에 kakao
객체가 추가된다.window.kakao
객체를 통해 카카오맵의 원하는 기능을 사용할 수 있다. (예 : 마커 띄우기, 주소 검색 등)공식 가이드를 토대로, Next.js 환경에 맞게 카카오맵 API를 적용해봅시다.
1) Kakao Developers에 애플리케이션 등록하기
애플리케이션을 등록하면 아래와 같이 APP KEY가 표시됩니다.
이 중에서 JavaScript 키가 이후에 필요합니다.
2) 지도를 담을 영역 만들기
경우에 따라 필요한 구역에 원하는 크기를 가진 div 태그를 추가해줍니다.
추가한 div 태그에는 JS 코드에서 참조할 수 있도록 id를 붙여줍니다.
export default function Map() {
return <MapArea id="map" />;
}
// 화면에 꽉 채우기 위해 너비와 높이를 지정하였습니다.
const MapArea = styled.div`
width: 100vw;
height: 100vh;
`
3) 실제 지도를 그리는 JS API 불러오기
공식 가이드에서는 아래와 같이 HTML 문서에 Script 태그를 추가하는 방식으로 설명되어 있습니다.
CSR 방식의 CRA앱의 경우 index.html
을 제공하기에 해당 파일에 추가하면 되지만, Next.js에서는 해당 파일이 제공되지 않습니다.
그렇기에 Next.js에서는 아래와 같은 방법으로 script 엘리먼트를 추가해줍니다.
여기서 useEffect
를 사용하는데, CSR 상태의 전역 객체 window
를 사용하기 위함입니다.
환경 변수 파일(.env
)에 1번에서 확인했던 JavaScript APP KEY를 저장하고, 아래처럼 참조해줍니다. 여기서 환경 변수 파일은 보안을 위해 .gitignore
에 추가해주어야 합니다.
이렇게 하면 window
전역 객체에 kakao
가 추가됩니다.
useEffect(() => {
const mapScript = document.createElement('script');
mapScript.async = true;
mapScript.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.NEXT_PUBLIC_KAKAOMAP_APPKEY}`;
document.head.appendChild(mapScript);
}, [])
4) 지도를 띄우는 코드 작성
마찬가지로 useEffect
내부에 작성합니다. (3번과 별도로 작성해도 문제없습니다.)
windows.kakao
는 스크립트가 로드가 되기 전에 참조하면 에러가 발생하므로, 스크립트 로딩이 끝나기 전에 실행되는 load 메서드 내부에 작성합니다.
useEffect(() => {
const { kakao } = window
kakao.maps.load(() => {
const mapArea = document.getElementById('map');
const options = {
level: 3,
center: new kakao.maps.LatLng(33.450701, 126.570667)
}
const map = new kakao.maps.localMap(mapArea, options)
})
}, [])
1) 줌 레벨이 5 이하인 경우 커스텀 오버레이 띄우기
줌 레벨이 클수록 지도 표시 범위가 넓습니다.
const handleZoomChanged = () => {
// 현재 줌 레벨 불러오기
const level = localMap.getLevel();
if (level <= 5) {
// 오버레이로 띄울 엘리먼트 생성 및 속성 설정
// JSX 코드로는 불가능, innerHTML에 문자열 값 넣어주어야 함 (스타일은 별도 css 파일 사용)
const overlayEle = document.createElement('div');
overlayEle.id = 'overlay';
overlayEle.onclick = () => {/* 오버레이 클릭 시 동작 */};
overlayEle.innerHTML = `
<div>원룸/다가구</div>
<div id="score">★ 3.8</div>
`;
// 커스텀 오버레이 생성 (각각 오버레이 내용, 지도 엘리먼트, 오버레이 위치)
const overlay = new kakao.maps.CustomOverlay({
content: overlayEle,
map: localMap,
position: new kakao.maps.LatLng(33.450701, 126.570667)
});
// 지도 엘리먼트에 오버레이 적용
overlay.setMap(localMap);
// 줌 변경 시 이벤트 : 레벨이 5 초과이면 커스텀 오버레이 지도에서 제거
kakao.maps.event.addListener(localMap, 'zoom_changed', () => {
const level = localMap.getLevel();
level > 5 && overlay.setMap(null);
});
}
// 줌 레벨 변경 시 실행 이벤트
kakao.maps.event.addListener(localMap, 'zoom_changed', handleZoomChanged);
}, [])
2) 문자열로 주소 검색
// 주소-좌표간 변환 서비스 Geocoder 객체 생성
const geocoder = new kakao.maps.services.Geocoder();
// 문자열로 주소를 검색하는 메소드 addressSearch(검색 문자열, (검색결과 "좌표(x, y)"들이 들어있는 배열, 검색 성공 여부) => {})
geocoder.addressSearch(e.target.value, (res: IAutoComplete[], status: string) => {
if (status === kakao.maps.services.Status.OK) {
// 검색이 성공적으로 이루어졌을 경우
} else {
// 검색이 실패했을 경우
}
});
3) 특정 좌표로 위치 이동 (지도 정중앙 위치 설정)
// 좌표
const coords = new kakao.maps.LatLng(33.450701, 126.570667);
// 지도 정중앙 위치 설정
localMap.setCenter(coords);