공공데이터 api를 활용한 웹앱을 만드는 공모전을 준비하던 중에,
세부페이지에 지도가 들어가서 지도 api를 적용하고자 했다.
3d 지도는 해봤지만 다른 팀원과 같이 했던 터라
2d 지도를 꼭 구현해보고 싶었는데 좋은 기회였다.
그래서 하는 김에 하나로 바로 정하지 않고 다 적용해보고
어떤 api가 제일 좋을지 3가지를 두고 고민해보고자 했다.
이용할 기술스택
react, typescript, styled-components
+세 지도 api 모두 react에 대한 자료는 직접적으로 나오진 않는다.
대신 html과 js 스크립트만 존재한다.
입맛에 알맞게.. 조정해야 한다.
일단 깔끔한 ui에 가이드(https://apis.map.kakao.com/web/guide/)도 알아보기 쉽게 적혀있다.
간단하게 가이드를 따라 지도를 가져올 수 있지만,
각각의 요소가 가끔 정확히 적혀있지 않고, 리액트에 맞게 가져오거나
typescript를 이용하면서 타입 지정에 어려움을 겪었다.
-간단하게 가져오기
1)api 키 발급받기
개발자 사이트(https://developers.kakao.com/)에 들어가
가입 혹은 카카오로그인 후
앱을 등록하고 api 키(rest api 키)를 가져온다.
api 키는 .env로 가져오고 꼭 gitignore에 .env를 등록한다.
공식문서에서는 웹서버 접속이 나와있지만, 간단하게 가져오는 것에서는
skip하고 지도 띄우는 것을 최우선으로 했다.
2)public의 index.html에 스크립트 추가
REACT_APP_API_KEY로 .env에 키를 적어놓았다고 치면,
다른 컴포넌트 및 페이지와 달리 index.html에는 키를 %%안에 REACT_APP_API_KEY로 그대로 적는다.
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=%REACT_APP_API_KEY%></script>
cf)반대로 일반 컴포넌트에서는 process.env를 붙여
process.env.REACT_APP_API_KEY 형식으로 적어야 한다.
3)div 만들기 & useRef
화면에 보여질 컴포넌트에 div를 만든다. 그 전에 div에 접근할 수 있는 메서드를 먼저 만들자.
하지만 공식문서는 바닐라 자바스크립트 기준이기 때문에
//공식문서
var container = document.getElementById('map');
위처럼 getElementById 메서드로 특정 dom을 선택한다.
하지만 여기서는 리액트이므로 useRef를 통해 dom을 선택하여 적용한다.
//리액트로 변형
const mapRef = useRef(null);
div에 useRef를 넣어주면 된다.
//공식문서
<div id="map" style="width:500px;height:400px;"></div>
//리액트로 변형
<div id="map" ref={mapRef} style={{ width: '1143px', height: '594px' }} />
여기서 ref를 넣어줬기 때문에 id="map"을 빼도 오류는 안 난다.
그래도 일단은 넣어준다.
또한 간단히 하기 위해 style을 위처럼 적용했는데,
styled-components를 이용하면 조금 더 깔끔해질 것이다.
//최종 형태
<St.MapStyle ref={mapRef}/>
이렇게 말이다.
4) 지도를 띄우기 위한 코드 작성
//공식문서
var container = document.getElementById('map'); //지도를 담을 영역의 DOM 레퍼런스
var options = { //지도를 생성할 때 필요한 기본 옵션
center: new kakao.maps.LatLng(33.450701, 126.570667), //지도의 중심좌표.
level: 3 //지도의 레벨(확대, 축소 정도)
};
var map = new kakao.maps.Map(container, options); //지도 생성 및 객체 리턴
위처럼 적용하면 참 편할텐데,
일단 eslint를 적용했기 때문에 var를 빼고,
useRef를 적용했으니 컨테이너도 뺀다.
또한 kakao에 대해 타입 및 변수 선언도 해줘야 오류가 나지 않는다.
//리액트로 변형
//eslint의 오류 일단은 막기
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
//간단히 적용하기 위해 any로 타입 지정 -추후 변경예정
declare global {
interface Window {
kakao: any;
}
}
const { kakao } = window;
useEffect(()=>{
const options = {
center: new kakao.maps.LatLng(33.450701, 126.570667), //보여질 지도 좌표.
level: 3 //지도의 레벨(확대, 축소 정도)
}
const map = new window.kakao.maps.Map(mapRef.current, options);
},[]);
return (
<div>
<div id="map" ref={mapRef} style={{ width: '1143px', height: '594px' }} />
</div>
);
안녕하세요~ 지도 3개 비교하는 부분 잘 봤습니다~!! 혹시 세개중 어떤것을 선택하셨나요~~~???