모던 웹을 위한 한국 지도 시각화 geo-korea

MNIII
7 min readJan 23, 2025

--

데이터로 이야기를 전달할 때 지도는 그 자체로 하나의 언어가 됩니다. 특히 지역별 데이터를 다룰 때는 더 그런것 같습니다. 다양한 곳에서 활용도는 많지 않지만 지도를 웹에서 표현하는 것은 흥미롭다고 생각합니다.

지도 시각화 라이브러리 geo-korea를 개발하며 직면한 첫 번째 과제는 지리 데이터를 효율적으로 다루는 것이었습니다. 웹에서 지도를 시각화 할 때 가장 흔히 사용 되는 방식은 GeoJSON인데 몇 가지 문제점이 있었습니다.

  • 시/도 경계가 겹치는 부분의 좌표가 중복되어 파일 크기가 크다.
  • 데이터 복잡도가 높아 줌 인/아웃 할 때 성능이 저하 된다.
  • 데이터를 자세히 표현하기 위해 복잡한 속성 데이터를 포함하고 있어서 지도 데이터 업데이트가 어렵다.

이런 문제들을 해결하기 위해 D3.js와 TopoJSON을 적용했습니다.

TopoJSON은 GeoJSON의 확장형으로, 지리 데이터를 효율적으로 인코딩하여 파일 크기를 크게 줄여줍니다.

// GeoJSON vs TopoJSON 크기 비교
// korea.geojson: 2.8MB
// korea.topojson: 982KB (약 65% 감소)

두 기술을 선택한 주요 이유 :

D3.js

  • SVG 기반의 세밀한 렌더링 제어
  • 강력한 지리 투영 기능과 좌표계 변환
  • 부드러운 줌/패닝 애니메이션 지원

TopoJSON

  • 지역 간 경계선 데이터 중복 제거
  • 효율적인 네트워크 전송 (압축 효율)
  • D3.js와의 뛰어난 호환성

Geo-Korea 라이브러리 지원 기능

  • 지역 하이라이팅과 클릭 이벤트
  • 커스텀 마커와 툴팁
  • 줌/아웃과 지역 포커스
  • 테마 시스템
  • React 컴포넌트 지원
  • TypeScript 타입 정의

JavaScript 기본 사용법

const GeoKoreaRenderer = new GeoKoreaInitializer();
const map = await GeoKoreaRenderer.createMap("map-container");

React 컴포넌트 사용법

const App: React.FC = () => {
const containerRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (containerRef.current) {
const GeoKoreaRenderer = new GeoKoreaInitializer();
const map = GeoKoreaRenderer.createMap(containerRef.current, {
points: [
{
name: "서울 시청",
region: "수도권",
location: "서울",
coordinates: [37.5666805, 126.9784147],
type: "시청",
}
],
onRegionClick: (name) => console.log(`clicked: ${name}`)
});

return () => map.destroy();
}
}, []);

return <div ref={containerRef} />;
};
  • 컨테이너 크기에 맞는 width/height 자동 계산
  • 지도에 맞는 center와 scale 자동 조정

기본 설정

const map = await GeoKoreaRenderer.createMap("map-container", {
width: 800, // 너비 (선택, 기본값: 컨테이너 크기)
height: 600, // 높이 (선택, 기본값: 컨테이너 크기)
center: [128.35, 37.68], // 중심 좌표 [경도, 위도]
scale: 5, // 확대 배율 (0.5 ~ 8)
});

마커와 이벤트

const points = [{
name: "주요 지점", // 마커 이름
type: "landmark", // 마커 유형
region: "서울", // 소속 지역
location: "강남구", // 세부 위치
coordinates: [37.5, 127.0], // [위도, 경도]
radius: 5, // 마커 크기 (선택)
color: "#FF0000" // 마커 색상 (선택)
}];

const options = {
onRegionClick: (name) => console.log(`${name} 클릭됨`),
tooltipRenderer: (point) => `<div>${point.name}</div>`
};

테마 설정

const customColors = {
region: "#2A2D35", // 기본 지역 색상
regionHover: "#3F4046", // 마우스오버 시 색상
point: "#5EEAD4", // 마커 기본 색상
pointHover: "#6366F1", // 마커 마우스오버 색상
selected: "#6366F1", // 선택된 지역 색상
border: "#4A4B50" // 경계선 색상
};

지도 컨트롤 및 설정 업데이트

// 마커 업데이트
map.updatePoints(newPoints);

// 데이터 변경
map.setTopoData(newTopoData, "objectName");

// 리소스 해제
map.destroy();

활용 가능성과 확장 시나리오

공공 데이터 시각화

  • 지역별 예산 집행 현황
  • 인구 통계 및 이동 패턴
  • 대기오염 측정 데이터

부동산/상권 분석

const realEstateMap = new GeoKoreaRenderer.createMap(container, {
points: propertyData,
tooltipRenderer: (point) => `
<div>
<h3>${point.district}</h3>
<p>평균 거래가: ${formatPrice(point.avgPrice)}</p>
<p>전년대비: ${point.yoyChange}%</p>
</div>
`
}

재난/안전 관리

  • 실시간 재난 상황 모니터링
  • 대피소 및 의료시설 위치 표시
  • 기상 특보 지역 하이라이팅

산업/물류

const logisticsMap = await GeoKoreaRenderer.createMap("map", {
points: warehouses,
onRegionClick: (region) => calculateDeliveryOptimization(region)
});

관광/문화

  • 관광지 분포 및 동선 계획
  • 문화재 현황 지도

다양한 활용 시나리오에서 보듯이 geo-korea는 공공데이터 시각화 부터 부동산, 산업, 관광 등 폭넓은 분야에서 활용될 수 있습니다. TypeScript 지원과 React 컴포넌트화를 통해 기존 시스템과의 통합도 용이합니다. 이러한 활용 가능성은 geo-korea의 확장성을 보여 줍니다.

향후 개선 계획

  • 시군구 단위 상세 지도 지원
  • 다양한 커스텀 옵션 제공
  • 실시간 데이터 업데이트
  • 이미지 다운로드 기능
  • 지역 간 비교 분석
  • 시계열 데이터 시각화

geo-korea는 아직 작은 라이브러리 입니다. 하지만 행정구역 통계부터 부동산 분석, 재난 관리까지 다양한 분야에서 활용될 수 있다고 생각합니다. 피드백을 통해 조금씩 성장하는 도구가 되길 희망합니다.

--

--

No responses yet