웹 애플리케이션은 지도를 포함함으로써 사용자에게 귀중한 위치 기반 정보를 제공함으로써 큰 이점을 얻었습니다. 지도는 익숙하지 않은 장소를 탐색하는 것에서부터 근처 식당을 찾는 것까지 우리와 세상과의 상호 작용을 변화시켰습니다. 결과적으로 최근에는 웹사이트에 지도를 통합하는 것이 점점 더 대중화되고 있습니다. 그럼에도 불구하고 기능적이고 사용자 친화적인 지도를 디자인하는 것은 특히 이 분야에 대한 경험이 부족한 사람들에게는 어려울 수 있습니다. 이 글에서는 브라우저 내에서 효과적인 지도를 만드는 방법에 대한 유용한 팁을 공유하겠습니다. 기술 스택 기술에 대해 논의해 봅시다. 지도 작업을 할 때 일반적으로 세 가지 레이어를 사용합니다. 버튼과 양식을 포함하는 사용자 인터페이스를 렌더링합니다. 우리 스택에서는 React가 이 역할을 수행합니다. 지도를 렌더링하고 사용자 상호작용을 활성화합니다. 이를 위해 Mapbox를 사용합니다. 마커 또는 다각형에 대한 정보와 같은 데이터를 서버에서 가져옵니다. 데이터를 검색하기 위해 브라우저에 내장된 가져오기 기능을 사용합니다. 지도 작업 시 기술 스택을 더 잘 이해하기 위해 각 항목을 검토해 보겠습니다. 반응하다 그만큼 라이브러리를 사용하면 페이지 요소를 편리하고 효율적으로 작업할 수 있습니다. 이는 Facebook에서 자체 사용을 위해 개발되었으며 페이지의 버튼, 양식 및 기타 대화형 요소와 같은 수많은 구성 요소를 포함합니다. 예를 들어 Facebook은 다양한 상태를 빠르게 비교할 수 있습니다. 반응하다 조정 알고리즘 페이지의 요소를 변경하는 것은 브라우저에 있어서 가장 비용이 많이 드는 작업이므로 최대한 효율적으로 수행하는 것이 중요합니다. 이 문제를 해결하기 위해 Facebook 엔지니어는 페이지에서 요소를 빠르고 간단하게 변경할 수 있는 React 라이브러리를 개발했습니다. 페이지에서 신속한 상태 변경을 제공하는 것 외에도 React를 사용하면 DOM 요소를 직접 사용하지 않고도 선언적으로 이를 수행할 수 있습니다. 대신에 우리는 일반적으로 추상화를 사용합니다. , 이는 HTML처럼 보입니다. 예를 생각해 봅시다: JSX // It's our state. Is the user our friend or not? // false by default const [isFriend, setIsFriend] = useState(false) // Depending on the state, we show the text on the button const buttonText = isFriend ? 'Your my Friend' : 'Add as Friend' // There is JSX, syntax for UI // In this case, we display a button, when clicked, we change the state return ( <button onClick={() => setIsFriend(true)}>{buttonText}</button> ) 계층 구조의 맨 아래에 있는 양식, 버튼, 입력과 같은 일반 DOM 요소와 구성 요소를 중첩할 수 있습니다. 이러한 간단한 요소를 조합하여 완전한 형태와 같은 더 복잡한 요소를 만들 수 있습니다. const Form = () => ( <form> <input name="Email"/> <input name="Password"/> </form> ) const App = () => ( <main> <h1>My form!</h1> <Form /> </main> ) React는 지도의 맥락에서 우리를 어떻게 지원하나요? 페이지의 지도는 버튼이나 양식과 유사하게 대화형이므로 지도 클릭과 같은 이벤트를 통해 렌더링 및 상호 작용을 최적화하는 것을 목표로 합니다. React는 이러한 최적화를 달성하는 데 도움이 될 수 있습니다. 작동 방식의 예는 다음과 같습니다. // Use React to render the map with different event handlers // and render markers return ( <BaseMap onInitMap={() => console.log('I am alive!')} onClickMap={() => console.log('Click!')} onDestroyMap={() => console.log('Oh no!')} > <ClustersMarkers /> <PostsMarkers /> <ListingsMarkers /> </BaseMap> ) React로 작업할 때 페이지 요소의 효율적인 조작, 빠른 변경, 이벤트를 통한 상호 작용이 가능하다는 점을 기억하는 것이 중요합니다. 이는 HTML과 유사한 추상화를 통해 달성되므로 단순한 구성 요소에서 복잡한 구성 요소를 쉽게 만들 수 있습니다. 맵박스 이제 지도 자체에 대해 논의해 보겠습니다. 지도를 만들고 사용하는 것은 어려울 수 있으며 소수의 제품 회사만이 처음부터 지도를 디자인할 수 있습니다. 일반적으로 대부분의 사람들은 시도와 테스트를 거쳐 사용자 친화적인 API가 포함된 미리 만들어진 라이브러리에 의존합니다. Google Maps, Leaflet, Bing Maps, Mapbox 등 다양한 동적 지도 제공업체를 사용할 수 있습니다. 그러나 우리는 다음에 중점을 둘 것입니다. 광범위한 기능과 공정한 가격 정책으로 인해. 예를 들어 Google 지도에서는 요금이 청구됩니다. 매월 100,000개의 지도 보기가 가능하며 Mapbox는 요금만 청구합니다. . 또한 Mapbox는 매월 최대 50,000개의 지도 보기에 대한 무료 액세스를 제공합니다. 맵박스 $700 $250 Mapbox 제공 , 지도용 Photoshop과 자주 비교되는 도구입니다. 이 도구를 사용하면 디자이너는 사용자 정의 스타일을 만들고, 불필요한 지도 요소를 숨기고, 주택 디스플레이를 제거할 수 있습니다. 그 장점 중 하나는 가시성을 향상시킬 수 있다는 것입니다. . 또 다른 장점은 회사 색상으로 지도 스타일을 실험해 볼 수 있다는 것입니다. 하지만 사용자 경험을 고려하고 푸른 잔디, 푸른 물 등 친숙한 색상 팔레트를 유지하는 것이 중요합니다. Mapbox Studio의 가장 좋은 점은 요구 사항을 개발하고 전송할 필요가 없어 지도 디자인 프로세스를 단순화하고 궁극적으로 지도 작업 비용을 절감한다는 것입니다. 맵박스 스튜디오 가볼만한 곳 또한 Mapbox는 다음을 제공합니다. 주소를 좌표로 또는 그 반대로 변환할 수 있어 지도에서 지점을 찾는 과정이 단순화됩니다. 그러나 도구의 충분하지 않아 특정 프로젝트에 어려움을 겪을 수 있습니다. Mapbox는 다음에서 데이터를 수집합니다. , 정부, OpenStreetMap과 같은 개방형 데이터 이니셔티브, 민간 기업 등이 있습니다. 지오코딩 도구 전 세계적으로 적용 수많은 소스 Mapbox는 다양한 기능을 제공합니다. , 비록 약간의 개선 혜택을 누릴 수 있습니다. 예를 들어 마커 기능을 통합하는 경우 문서보다 예제가 더 많은 정보를 제공할 수 있습니다. 또한 마커 클러스터, 사용자 정의 데이터 로드, 정규화 및 마커 상태 변경과 같은 여러 구성 요소를 병합할 때 문제가 발생할 수 있습니다. 실제 사례 선적 서류 비치 Mapbox 지도를 다시 살펴보겠습니다. 무엇을 하는가? 하다? 맵박스 API 페이지의 HTML 요소에서 지도를 초기화합니다. 지도를 구성하는 이미지를 로드하고 렌더링합니다. GeoJson을 입력 데이터로 사용하여 마커와 같은 추가 요소를 그립니다. 클릭이나 확대/축소 변경과 같은 처리할 수 있는 이벤트를 생성합니다. 각 항목을 자세히 살펴보겠습니다. Mapbox는 타일을 사용한 지도 렌더링을 전문으로 합니다. 타일은 더 큰 지도를 구성하는 작은 정사각형 이미지입니다. 타일의 기본 크기는 512x512픽셀이며 다음 중 하나일 수 있습니다. . 타일은 도로, 건물, 관심 지점(PoI) 등을 표시하는 데 사용됩니다. 동적으로 스타일을 지정할 수 있고 가벼우며 지도와 원활하게 상호 작용할 수 있습니다. 반면에 타일은 위성 이미지를 표시하는 데 사용됩니다. 벡터 또는 래스터 벡터 래스터 아시다시피 Mapbox Studio를 사용하면 지도 타일에 포함하려는 특정 데이터를 선택할 수 있습니다. 그런 다음 이 타일을 다음 위치에 배치합니다. 는 웹에 이미지와 기타 그래픽 요소를 표시하는 브라우저의 특수 DOM 요소입니다. 쉽게 설명하면 Google Docs의 캔버스에 문서가 표시되는 방식과 비슷합니다. 캔버스 <canvas width="100" height="100" /> Mapbox는 타일의 로드, 삽입 및 업데이트를 처리합니다. 우리가 해야 할 일은 지도를 표시할 위치와 확대/축소 수준이나 지도 좌표와 같은 초기 조건을 지정하는 것뿐입니다. Mapbox를 사용하려면 , 이는 Mapbox 계정에서 찾을 수 있는 고유 키입니다. 기본 지도를 설정하려면 다음의 간단한 예를 참조하세요. 자세한 내용은 다음을 확인하세요. 제공됨: 액세스 토큰 링크 mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'; const map = new mapboxgl.Map({ container: 'map', // we can use an Id or an element style: 'mapbox://styles/mapbox/streets-v11', // URL for styles center: [-74.5, 40], // initial coordinates [lng, lat] zoom: 9, // initial zoom }); 그 후에는 ID가 'map'인 요소의 페이지에 지도가 표시됩니다. 사용자에게 지도에 더 많은 정보를 제공하기 위해 당사는 특정 시설의 위치나 특정 지역의 경계를 표시하는 경우가 많습니다. 이를 달성하기 위해 우리는 다음과 같은 특정 데이터 형식을 사용합니다. 이 데이터를 표시하는 방법을 Mapbox에 지시하세요. GeoJSON GeoJSON은 지도에 지리 구조를 저장하기 위한 표준 형식입니다. 주소, 위치, 거리, 고속도로, 국경, 국가, 주 및 이들의 조합(멀티파트)과 같은 지리적 객체를 설명하는 다양한 기본 유형을 저장할 수 있습니다. GeoJSON은 2008년에 도입되었으며 다음과 같이 표현됩니다. { "type": "Feature", // also can be FeatureCollection, it's collection of Feature "geometry": { "type": "Point", // also can be LineString, Polygon, MultiPolygon "coordinates": [125.6, 10.1] // for other types you can use Array with coordinates }, "properties": { // it's metadata, we can you that to show something on the map "name": "Dinagat Islands" } } Mapbox에서 사용되는 좌표계에 대해 이야기해 보겠습니다. 기본적으로 Mapbox는 다음을 사용합니다. , 타일 작업을 위해 지구를 평평한 표면에 투영하는 방법입니다. 이는 Web Mercator로 알려져 있으며 온라인 지도의 표준입니다. 그러나 마커 및 폴리곤에 대한 데이터를 처리할 때는 이라는 다른 좌표계를 사용합니다. . 이 시스템은 위도와 경도를 사용하여 지구의 타원체 좌표를 설명합니다. Mapbox 및 기타 지도 제공업체는 EPSG 4326에서 EPSG 3857로 좌표를 자동으로 변환합니다. , 메소드를 사용할 수 있습니다. EPSG 3857 EPSG 4326 투영 map.setProjection 이제 지도에 GeoJSON을 표시하는 방법에 대해 설명하겠습니다. Mapbox는 도움이 될 두 가지 엔터티를 제공합니다. — 이것이 데이터 시드입니다. GeoJSON 데이터로 새 소스를 생성하고 기능 컬렉션의 각 기능에 대한 ID를 생성하도록 구성할 수 있습니다. 원천 — 이것이 데이터 표현입니다. 경계 표시 등 다양한 방법으로 소스의 데이터를 표시할 수 있습니다. 층 지도에 다각형이나 마커를 표시하려면 서버에서 GeoJson 형식의 데이터를 검색해야 합니다. 그런 다음 소스를 생성하고 데이터를 입력한 후 필요한 레이어에 연결합니다. const geoJsonFeature = { 'type': 'Feature', 'geometry': { 'type': 'Polygon', 'coordinates': [ [-67.13734, 45.13745], [-66.96466, 44.8097], [-68.03252, 44.3252], [-67.13734, 45.13745] ] } } // Create source with our data map.addSource('ourSource', { 'type': 'geojson', 'data': geoJsonFeature }); // Add layer for background map.addLayer({ 'id': 'background', 'type': 'fill', 'source': 'ourSource', // название нашего source 'layout': {}, 'paint': { 'fill-color': '#0080ff', 'fill-opacity': 0.5 } }); // Add layer for border map.addLayer({ 'id': 'border', 'type': 'line', 'source': 'ourSource', 'layout': {}, 'paint': { 'line-color': '#000', 'line-width': 3 } }); 이 코드를 실행하면 다음과 같은 결과를 얻습니다. 이 주제에 대해 자세히 알아보려면 다음을 참조하세요. 맵박스 제공. 이 튜토리얼에서는 지도를 초기화하고 데이터를 표시하는 과정을 다루었습니다. 다음으로 클릭, 드래그, 확대/축소와 같은 이벤트를 처리하는 방법을 살펴보겠습니다. 예를 들어, Mapbox를 사용하여 이벤트를 모니터링하고 사용자가 지도에서 커서를 움직일 때 콘솔에 좌표를 표시할 수 있습니다. 이를 달성하기 위해 DOM 요소를 사용하는 방법과 유사하게 원하는 이벤트 유형으로 메소드를 호출하기만 하면 됩니다. 선적 서류 비치 on map.on('mousemove', (e) => { console.log(JSON.stringify(e.point)); }); // Result: {"x":330,"y":49} 요약하면, 우리가 기억해야 할 것은 무엇입니까? Mapbox를 사용하면 지도를 표시하고 그 위에 데이터를 그리고 지도 이벤트를 처리할 수 있습니다. 동시에 Mapbox는 이미지(타일) 로드 및 표시를 관리합니다. 술책 에 대해 한마디 . 지도에 데이터를 렌더링하는 방법을 이미 살펴보았지만 먼저 서버에서 데이터를 검색해야 합니다. 페이지를 다시 로드하지 않고 백그라운드에서 서버에 동적으로 데이터를 요청할 때 이 접근 방식을 호출합니다. (“ avaScript ML”). Axios 또는 XMLHttpRequest(네이티브)와 같이 서버에서 데이터를 비동기적으로 로드하기 위한 많은 도구가 있습니다. 술책 아약스 동기식 J 및 X 무엇을 기억해야 할까요? 서버에서 데이터를 검색하고 이를 위한 많은 라이브러리가 있지만 가져오기를 사용하겠습니다. 다음으로, 뉘앙스가 있으므로 지도 작업 시 구체적으로 이를 수행하는 방법을 살펴보겠습니다. 반응 + 맵박스 이제 위에 설명된 기술이 어떻게 함께 작동하는지 살펴보겠습니다. 먼저 fetch를 사용하여 다각형을 표시하기 위한 데이터를 검색합니다. 그런 다음 지도 초기화를 선언하고 지도가 로드된 후 지도에 다각형을 추가합니다. 다음 사이트에서도 실제 사례를 찾을 수 있습니다. 제공됩니다. 링크 const useFetch = () => { /* Our data { 'type': 'Feature', 'geometry': { 'type': 'Polygon', 'coordinates': [ [ [-67.13734, 45.13745], [-68.03252, 44.3252], [-68.90478, 47.18479], [-67.13734, 45.13745], ] ] } } */ const [data, setData] = useState(null) useEffect(() => { fetch('https://our-api.com/polygon') .then(response => response.json()) .then(setData) .catch(e => { console.error(e) }) }, [setData]) return { data } } const BaseMap = () => { // Use the hook to fetch data const { data } = useFetch(GET_REGION); // Map instance const map = useRef(null); // DOM element const mapContainer = useRef(null); // Main logic - init the map and add the event useEffect(() => { if (map.current) { return; // initialize map only once } mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'; map.current = new mapboxgl.Map({ container: mapContainer.current, style: 'mapbox://styles/mapbox/light-v10', // style URL (it's Mapbox's core style) center: [-68.137343, 45.137451], // starting position zoom: 5 // starting zoom }); // Handle event map.on('load', () => { const sourceId = 'source-region' // Add a data source containing GeoJSON data map.addSource(sourceId, { 'type': 'geojson', 'data': data.region // our data from Apollo }); // Add a new layer to visualize the polygon map.addLayer({ 'id': 'background', 'type': 'fill', 'source': sourceId, // reference the data source 'paint': { 'fill-color': '#0080ff', // blue color fill 'fill-opacity': 0.5 } }); // Add a black outline around the polygon map.addLayer({ 'id': 'outline', 'type': 'line', 'source': sourceId, 'paint': { 'line-color': '#000', 'line-width': 3 } }); }); }); return <div ref={mapContainer} />; } 결론 우리는 미래 아키텍처를 뒷받침하는 기술 스택을 살펴보았습니다. 다음 기사에서는 지도 아키텍처를 설계하는 데 도움이 되는 원칙, 모듈의 최대 낮은 결합도와 높은 응집도를 달성하는 방법, 확장 가능한 지도 시스템을 유지하고 개발하는 방법에 대해 설명합니다. 많은 관심을 가져주셔서 감사합니다! 좋은 하루 보내세요.