React에서 leaflet으로 대한민국 카카오맵 불러오기

2022. 4. 26. 16:03[개발] 지식/GIS

아래 명령어로 react 기본 프로젝트를 생성하고 진행하였다.

$ npm init react-app <프로젝트 이름>

개발 목표는 카카오맵으로 대한민국 지도를 표현하는 가장 기본적인 형태의 react + leaflet 템플릿이다.

packages

아래 3개 패키지를 추가로 설치한다.

  • leaflet
  • react-leaflet
  • proj4leaflet

예시

$ npm install leaflet --save

Sources

import React, { useState, useMemo } from 'react';
import { MapContainer, LayersControl, TileLayer, Marker, Popup } from 'react-leaflet';
import "proj4"
import "proj4leaflet"
import L, { CRS, bounds } from 'leaflet';

const Maps = () => {

    // 좌표계 정의
    const EPSG5181 = new L.Proj.CRS(
        'EPSG:5181',
        '+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=500000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs',
        {
        resolutions: [2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5, 0.25],
        origin: [-30000, -60000],
        bounds: L.bounds([-30000-Math.pow(2,19)*4, -60000], [-30000+Math.pow(2,19)*5, -60000+Math.pow(2,19)*5])
        }          
     );

    const [map, setMap] = useState(null);
    const [mapStat, setMapStat] = useState({
        center: { lat: 37.142803, lng: 128.18161 },
        zoom: 1,
        crs: EPSG5181,
        minZoom: 0,
        maxZoom: 13
    });

    const displayMap = useMemo(() => (
            <MapContainer id="map"
                style={{ height: '100%'}}
                // center={[mapStat.center.lat, mapStat.center.lng]}
                center={mapStat.center}
                zoom={mapStat.zoom}
                crs={mapStat.crs}
                zoomControl={false}
                whenCreated={setMap}
                preferCanvas={true}
                worldCopyJump={false}
                >
                    <LayersControl position="topleft">
                        <LayersControl.BaseLayer checked={true} name={'지도'}>
                            <TileLayer
                                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                                // url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
                                url='http://map{s}.daumcdn.net/map_2d/1807hsm/L{z}/{y}/{x}.png'
                                minZoom={0}
                                maxZoom={13}
                                zoomReverse={true}
                                zoomOffset={1}
                                subdomains='0123'
                                continuousWorld={true}
                                tms={true}
                            />
                        </LayersControl.BaseLayer>
                    </LayersControl>

            </MapContainer>

    ));

    return (
        <div class='map-container'>
            {displayMap}
        </div>
    )

}

export default Maps;

Maps 컴포넌트를 먼저 아래와 같이 작성한다. 카카오맵은 EPSG:5181 좌표계를 사용하므로, 별도로 정의하였다(leaflet 기본 좌표계에는 없음). 그리고 MapContainerTileLayer 컴포넌트를 가지고 카카오맵을 표현했다. map-container 클래스는 단순히 height 100%를 승계받기 위해 만든 스타일이므로 큰 의미는 없다.

import './App.css';
import Maps from './Maps';

function App() {
  return (
    <div id='app'>
      <Maps></Maps>
    </div>
  );
}

export default App;

이것도 큰 의미 없다. 기본형을 거의 그대로 사용했다. Maps 컴포넌트만 추가해서 불러왔을 뿐이다.

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

html,body{
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

#root,#app {
  width: 100%;
  height: 100%;
}

.leaflet-container {
  width: 100%;
  height: 100%;
}

.map-container{
  width: 100%;
  height: 100%;
}

html, body에 height: 100% 옵션을 주었고, 이를 Maps 컴포넌트의 카카오맵 dom에 적용시키고자 하였다. 개선이 필요하지만 개발 목적을 봤을 때 중요하지 않으므로 일단 넘겨두었다.

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Maps from './Maps';

import './index.css';
import 'leaflet/dist/leaflet.css'

ReactDOM.render(
  <React.StrictMode>
    <Maps />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

leaflet.css 를 import 하는 부분이 중요하다. 이것을 처리하지 않으면 map 배열이 이상하게 보인다. 처음에 지도가 이상하게 보였는데, 원인을 못찾고 상당한 시간을 허비했었다..

결과

대한민국 카카오맵이 정상적으로 보인다. zoom 레벨과 중심 좌표만 조금 조절하면 더 나을 것 같다. 카카오맵을 불러오는게 중요하므로 일단 임무는 완수했다고 봐야할듯 하다.

Reference

[React.js] Leaflet으로 지도 그리기

Proj4Leaflet

React Leaflet | React Leaflet

Leaflet 맛보기 Chapter. 4. Leaflet Daum Map

<