[KakaoMap API] 카카오맵 기본 사용법 w/Next.js

백괴·2022년 8월 18일
0

1. 카카오맵 API 기본 개념

  • 카카오맵 API를 불러오는 스크립트를 HTML에 추가하면, 전역 객체 windowkakao 객체가 추가된다.
    => Server Side에서 렌더링을 진행하는 SSR 방식의 Next.js에 적용하기 위해서는 Client Side에서 렌더링 될 때만 스크립트를 추가하여야 한다. 방법은 2번 참고
  • window.kakao 객체를 통해 카카오맵의 원하는 기능을 사용할 수 있다. (예 : 마커 띄우기, 주소 검색 등)

2. Next.js 환경에서 카카오맵 API 적용하기

공식 가이드를 토대로, 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)
  })
}, [])

3. 직접 사용해 본 몇가지 예제

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);

0개의 댓글