공공데이터 api를 활용한 웹앱을 만드는 공모전을 준비하던 중에,
세부페이지에 지도가 들어가서 지도 api를 적용하고자 했다.
3d 지도는 해봤지만 다른 팀원과 같이 했던 터라
2d 지도를 꼭 구현해보고 싶었는데 좋은 기회였다.
그래서 하는 김에 하나로 바로 정하지 않고 다 적용해보고
어떤 api가 제일 좋을지 3가지를 두고 고민해보고자 했다.
react, typescript, styled-components
사이트 : https://sgis.kostat.go.kr/developer/html/main.html
통계청에서 제공하는 지도 API로 공공데이터를 이용하는 만큼
국가 산하가 제공하는 지도 API도 경험해보고 싶어서 적용해볼 예정이다.
1) API 키 신청
지도 API에서 API 키를 먼저 신청한다.
2)index.html에 script 적용
.env에 키를 넣고 gitignore에 .env를 적고
vscode를 껐다 켜서 재부팅 한다.
<script
type="text/javascript"
src="https://sgisapi.kostat.go.kr/OpenAPI3/auth/javascriptAuth?consumer_key=%REACT_APP_SGIS_JS_KEY%">
</script>
3) 리액트 코드로 변환하기
바닐라 자바스크립트로 이루어진 공식문서 코드를
리액트에 맞게 코드를 변환한다.
//원본
<body>
<div id="map" style="width:500px; height:500px;"></div>
<script type="text/javascript">
var map = sop.map('map');
map.setView(sop.utmk(953820, 1953437), 9);
</script>
</body>
//리액트 코드로 변환
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
//타입을 지정해주되, 간단하게 코드를 구성하여 일단 any로 한다.
//아래 pdf에 타입이 잘 지정되어 있으므로 참고.
declare global {
interface Window {
sop: any;
}
}
const Map = () => {
//getElement 메서드 대신 useRef를 쓴다.
const mapRef = useRef(null);
const { sop } = window;
//의존성 배열을 아래처럼 채우지 않으면 컨테이너가 초기화된다는 오류가 뜬다.
//의존성 배열 및 클린업 함수를 넣어줬다.
useEffect(() => {
const map = sop.map(mapRef.current);
map.setView(sop.utmk(953820, 1953437), 9);
return () => {
map.remove();
};
}, [sop, mapRef.current]);
return (
<div>
<div id ="map" ref={mapRef} style={{ width: '1143px', height: '594px' }} />
</div>
);
};
export default Map;
pdf :https://sgis.kostat.go.kr/developer/upload/doc/JavascriptMapAPI-definition.pdf
리액트 코드로 작성하는 중에 Map container is already initialized. 라는 코드가 떴다. 그래서 https://github.com/Leaflet/Leaflet/issues/3962 를 참고했다.
if (map != undefined) { map.remove(); }
이 코드를 클린업 함수에 넣으면 해결되긴 하지만
제대로 된 해결법이 아니였기에 초기화되지 않도록 고민했고,
map을 구성하는 변수를 의존성 배열에 넣어 해결했다.
const map = sop.map(mapRef.current);에서
sop과 mapRef.current를 의존성 배열에 넣어 위 코드처럼 구성했다.
4) 최종 결과