React.js 에서 행정구역 지도 띄우기 (feat.kkt map)

강정우·2023년 1월 26일
0

자습

목록 보기
4/11
post-thumbnail

0. 소개

  • 우선 카카오 지도 api같은 경우는 naver나 google 처럼 react 전용 의존성이 없기에 그냥 JS상에서 돌려주어야 한다.
    따라서 더 불편하고 굳이 react 프로젝트에서 카카오 지도 api를 사용할 필요는 없다.

  • 하지만 google에 비해 너무 잘 되어있는 sample code들 또 naver에 비해 버전 상관없이 쉽게 사용할 수 있다는 장점이 있다.
    또한 지도가 대한민국 친화적이고 layout도 다양하고 훨씬 깔끔하다는 장점이 있다.
    다만 앞서 언급했듯 react 전용 의존성이 없기에 여러 훅으로 커버해야한다.

1. 설치 및 기본 지도 띄우기

index.html

  • index.html 내부에 <script> 형식으로 위치하면 된다.
    이때 <script> 위치도 중요하기 때문에 반드시 body태그 내부 root div 밑에 위치하여야 한다.
                                                       ...
  </head>
  <body>
    <div id="overlay-root"></div>
    <div id="root"></div>
    <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=키"></script>
  </body>
</html>

Map.js

import ...

const {kakao} = window;

const Map = props => {
  
  필요한 훅 정의
  
  useEffect(()=>{
    1. polygon Area객체를 먼저 만듦
    2. 지도를 출력하는 코드 작성
    3. polygon Area를 setMap하는 코드 작성
    4. polygon Area를 setMap하는 함수 정의
    
  }, [])
  return(
          <Fragment>
            {isModal&&<Modal onClose={hideModalTrigger}>{isLoading&&<img src={loading}/>}</Modal>}
            <div className={classes.mapCntnr} id="map">
            </div>
          </Fragment>
)
}

expoer default Map;

2. 전체 코드

import {Fragment, useContext, useEffect, useState} from "react";
import classes from "./Map.module.css";
import waterMap from "../assets/watermap.json";
import Modal from "./UI/Modal";
import ChartContext from "../store/chart-context";
import loading from "../assets/loading.gif";

const { kakao } = window;

const Map = props => {
  
    let waterMapPolygon = JSON.parse(JSON.stringify(waterMap));
    const [isModal, setIsModal] = useState(false);
    const chartCtx = useContext(ChartContext);
    const [isLoading, setIsLoading] = useState(false);

    const hideModalTrigger = () => {
        setIsModal(false);
    }


    useEffect(() => {
        1. polygon Area객체를 먼저 만듦
        var areas = [];
        // 각 물 지도 구역 (0~73)
        for(let i=0; i<waterMapPolygon.features.length;i++){
            // 각 구역별 (0~73) lat, lng 뽑아내기
            const areaInfo = new Object({name:"",path:[]});
            if(waterMapPolygon.features[i].geometry.coordinates.length === 1){
                areaInfo.name = waterMapPolygon.features[i].properties.SBSNNM;
                const sectionWaterMap = [];
                for(let j=0; j<waterMapPolygon.features[i].geometry.coordinates[0].length; j++){
                    sectionWaterMap.push(new kakao.maps.LatLng(waterMapPolygon.features[i].geometry.coordinates[0][j][1], waterMapPolygon.features[i].geometry.coordinates[0][j][0]));
                }
                areaInfo.path = sectionWaterMap;
                areas.push(areaInfo);
            }
        }

		2. 지도를 출력하는 코드 작성
        let container = document.getElementById("map");
        let options = {
            center: new kakao.maps.LatLng(35.1359, 127.2531),
            level: 10,
        };
        let map = new kakao.maps.Map(container, options);
        let customOverlay = new kakao.maps.CustomOverlay({});

        3. polygon Area를 setMap하는 코드 작성
        for (var i = 0, len = areas.length; i < len; i++) {
            displayArea(areas[i]);
        }
      
      	4. polygon Area를 setMap하는 함수 정의
        function displayArea (area) {
            var polygon = new kakao.maps.Polygon({
                map:map,
                path:area.path,
                strokeWeight: 2,
                strokeColor: '#004c80',
                strokeOpacity: 0.8,
                fillColor: '#fff',
                fillOpacity: 0.7
            });
            kakao.maps.event.addListener(polygon, 'mouseover', function(mouseEvent) {
                polygon.setOptions({fillColor: '#09f'});
                customOverlay.setContent('<div class="area">' + area.name + '</div>');
                customOverlay.setPosition(mouseEvent.latLng);
                customOverlay.setMap(map);
            });
            kakao.maps.event.addListener(polygon, 'mousemove', function(mouseEvent) {
                customOverlay.setPosition(mouseEvent.latLng);
            });
            kakao.maps.event.addListener(polygon, 'mouseout', function() {
                polygon.setOptions({fillColor: '#fff'});
                customOverlay.setMap(null);
            });
            kakao.maps.event.addListener(polygon, 'click', function(mouseEvent) {
                setIsLoading(true);
                fetch(``
                ).then(res=>{
                    return res.json();
                }).then(data=>{
                })
                setIsModal(true);
                chartCtx.name = area.name;
                setIsLoading(false);
            });
        }
    }, [chartCtx]);

    return(
        <Fragment>
            {isModal&&<Modal onClose={hideModalTrigger}>{isLoading&&<img src={loading}/>}</Modal>}
            <div className={classes.mapCntnr} id="map">
            </div>
        </Fragment>
    )
}
export default Map;

2-1. polygon Area객체를 먼저 만듦

  • 여러 반복문 중 (단순 for문, foreach, map, .reduce, $.each) 역시 가장 빠른 것은 단순 for문이고
    단순히 검색하는 것이 아닌 계산 조건이 추가된다면 1.for, 2.reduce, 3.foreach 4.map 순이다.
    따라서 가장 성능이 좋은 단순 반복문으로 사용하였고 위 식을 거치면 다음과 같은 결과가 나온다.

  • 각 polygon의 명칭과 해당 polygon을 나타낼 좌표들이다.

2-2. 지도를 출력하는 코드 작성

  • 여타 다른 지도 api들과는 다르게 react 전용 의존성이 없기에 window단에 존재하는 kakao객체를 불러와서 사용해야한다.
  • 중심과 지도 레벨을 설정하면 된다.

2-3. polygon Area를 setMap하는 코드 작성

  • 및에 선언될 function을 hoisting하여 사용할 것이고 매개변수로는 1번에서 작업한 area 객체가 들어가 지도상에 그려지게 설정하였다.

2-4. polygon Area를 setMap하는 함수 정의

  • 이 코드는 kkt map api의 공식홈페이지의 sample 코드에서 얻을 수 있고 개인 입맛에 따라 코드를 조금 수정해주면 된다.
  • 필자는 "click" 이벤트에만 따로 나누어 해당 name을 modal로 표기하도록 작성하였다.

profile
智(지)! 德(덕)! 體(체)!

0개의 댓글