[React+TypeScript] 카카오 맵 이용하기

에구마·2022년 6월 20일
1

FrontEnd

목록 보기
12/25

리액+카맵 삼회차 . .
이번엔 타입스크립트 빠샤


타입스크립트

타입스크립트로 프로젝트를 연다면, 아래와 같이 실행한다.

npx create-react-app --template typescript

자바스크립트로 이미 진행중인 프로젝트에 타입스크립트를 도입하겠다면,

npm install --save typescript @types/node @types/react @types/react-dom

타입스크립트 모듈만 설치해주고
App.js -> App.tsx
index.js -> index.ts 로 변경해준다.

Kakao Developer 등록하기

개발자 어플리케이션 등록하기

앱 키 얻기

'내 어플리케이션 '에서 앱키를 얻을 수있다.
이 중 JavaScript 키를 이용한다.

index.html 중 <head >안에

    <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey={JavaScript 키}&libraries=services"></script>
  • .env에서 관리하려면 ??
    .env파일을 만들고
    REACT_APP_변수명 = 키값 (ex. REACT_APP_JS_KEY=123456789)

  • script src에서 변수 포맷팅
    " ... appkey=%REACT_APP_KEY% "
    변수를 %안에 둔다.

💥 env 설정후에는 꼭 노드를 다시 시작해야 한다. npm start

페이지 주소 등록

내 애플리케이션>앱 설정>플랫폼에 작업하는 페이지 주소를 등록한다.
(localhost주소 등)


코드 구현하기

카카오맵api 타입스크립트 설정

declare global {
  interface Window {
    kakao: any;
  }
}

카카오 맵api 가이드 문서

기본 맵 띄우기

  • App.tsx
import React from 'react';
import MapContainer from './map/MapContainer';

function App() {
  return (
    <div className="App">
      <MapContainer />
    </div>
  );
}

export default App;
  • MapContainer.tsx
import React, { useEffect } from 'react';

declare global {
  interface Window {
    kakao: any;
  }
}

const MapContainer = () => {
    useEffect(() => {

        let container = document.getElementById('map'); //지도를 담을 영역의 DOM 레퍼런스
        let options = { //지도를 생성할 때 필요한 기본 옵션
          center: new window.kakao.maps.LatLng(33.450701, 126.570667), //지도의 중심좌표.
          level: 3 //지도의 레벨(확대, 축소 정도)
        };
    
        let map = new window.kakao.maps.Map(container, options); //지도 생성 및 객체 리턴
    
      }, [])

    return (
        <div id="map" style={{ width: "100vw", height: "100vh" }} />
    );
}

export default MapContainer; 

마커 생성하기

인포윈도우 생성하기

https://apis.map.kakao.com/web/sample/basicInfoWindow/
하나의 인포윈도우만 생성한다면 위의 문서대로 적용하면 된다.
아래는 실제 프로젝트에서 이용할때 데이터를 불러와서 적용하는 경우이다.

프론트단에서만 개발인 상황, 데이터는 dummy.data에서 불러온다.

const MapContainer = () => {
    useEffect(() => {
        let container = document.getElementById('map'); //지도를 담을 영역의 DOM 레퍼런스
        let options = { //지도를 생성할 때 필요한 기본 옵션
          center: new window.kakao.maps.LatLng(37.586272, 127.029005), //지도의 중심좌표
          level: 1 //지도의 레벨(확대, 축소 정도)
        };
        let map = new window.kakao.maps.Map(container, options); //지도 생성 및 객체 리턴
		//---> 기본 맵 container, options, map 설정.

        for (let i=0; i< dummy.data.length; i++){
          displayMarker(dummy.data[i],i);
        }
        
        function displayMarker<T extends {name: string, location_y: number, location_x: number, active: boolean, point:number}>(data: T, i: number) {
          // 인포윈도우 표시될 위치(좌표) 
          let iwPosition  = new window.kakao.maps.LatLng(data.location_y, data.location_x); 

           // 인포윈도우에 표출될 내용. HTML 문자열이나 document element 등이 가능하다.
          var inactiveInfoWindow = `<div class="inactive infowindow""><span>${data.name}</span></div>`;

          //인포윈도우
          let infowindow;

		  infowindow = new window.kakao.maps.InfoWindow({
              zIndex: 1,
              position: iwPosition,
              content: inactiveInfoWindow,
              disableAutoPan: false,
              map: map //map에 해당 인포윈도우를 적용한다.
            });
          } 

		  //중심좌표 재설정
          var position = new window.kakao.maps.LatLng(37.586272, 127.029005);
          map.setCenter(position); 

        }
        
        });
      }, [])

인포윈도우 커스터마이징

인포윈도우 크기, 디자인, 이벤트 커스터마이징 하기


위의 인포윈도우 생성 코드 중

 // 인포윈도우에 표출될 내용. HTML 문자열이나 document element 등이 가능하다.
var inactiveInfoWindow = `<div class="inactive infowindow""><span>${data.name}</span></div>`;

여기서 설정한 것이 인포윈도우에 쓰여질 내용이다.
개발자도구 창에 클릭되어있는 파란부분의 div안에 들어간다.
우리가 코드에서 선언하고 디자인한 내용은 그 안에 들어갈 뿐이다.
하지만, 인포윈도우의 크기, 색깔, 디자인 등은 파란부분div 혹은 그의 부모, 형제 요소들로 조정해얗나다.
다음과 같이 커스터마이징 할 수 있다.

var infoTitle = document.querySelectorAll('.infowindow');
// 코드에 적용한 '인포윈도우에 표출될 내용'을 담은 태그에 적용한 class명(혹은id명)을 선택자를 이용하여 불러온다.
infoTitle.forEach(function(e: any) {
  var w = e.offsetWidth + 10;
  e.parentElement.style.width = w;  
  e.parentElement.style.position = "relative";
  if (e.className.includes('inactive')){
 	 e.parentElement.previousSibling.style.backgroundImage = "url('https://user-images.githubusercontent.com/81412212/174342201-0ec0c927-97f1-49dd-8c23-d6a872d9dfad.png')"; //꼭지
  } else {
 	 e.parentElement.previousSibling.style.backgroundImage = "url('https://user-images.githubusercontent.com/81412212/174341207-bbaa6a46-2d67-4731-8a51-9a429488affa.png')"; //꼭지
  }
  e.parentElement.parentElement.style.display = "flex"; 
  e.parentElement.parentElement.style.background = "none"; 
  e.parentElement.parentElement.style.border = "none";
  e.parentElement.parentElement.style.justifyContent = "center"; 
  e.childNodes[1].style.display = "block";
  e.childNodes[1].style.margin ="-8px";
  e.parentElement.style.top = "-12px";
  e.parentElement.style.top = "3px";
}

.infowindow를 선택하였기 때문에 e는
코드 (var inactiveInfoWindow)에 선언한 최상단 div이다.
e.parendElement는 그의 부모이며 인포윈도우 박스이다.
e.parendElement.previousSibling은 그의 앞쪽형제이고 인포윈도우 꼭지(V모양핀)이다.
e.parendElement.parentElement는 그의 조상이며 인포윈도우 박스+인포윈도우 꼭지(V모양핀부분)를 포함한다.
e.childNodes[n]은 그의 n번째 자식이며 여기선 span요소이다.

스타일은 .style
클릭이벤트는 .onclick 등 으로 설정할 수 있다.

인포윈도우 클릭 이벤트

e.parentElement.parentElement.onclick = handleIwClick //인포윈도우 클릭이벤트

...

function handleIwClick(e: any) {
          console.log(e.target); 
}

에러모음

ERR_ABORTED 401 (Unauthorized)


키워드로 장소검색하기

https://apis.map.kakao.com/web/sample/keywordBasic/


키워드로 장소검색하고 목록으로 표출하기

profile
Life begins at the end of your comfort zone

0개의 댓글