D3.js로 인터랙티브 세계 지도 만들기
D3.js는 지리 데이터 시각화에도 뛰어난 도구입니다. 이 튜토리얼에서는 GeoJSON 데이터를 사용하여 세계 지도를 단계별로 발전시켜 나갑니다.
Step 1: 기본 지도
가장 기본적인 세계 지도입니다. TopoJSON 데이터를 불러와 SVG로 렌더링합니다.
// 기본 투영법과 경로 생성기
const projection = d3.geoNaturalEarth1()
.scale(width / 5.5)
.translate([width / 2, height / 2]);
const path = d3.geoPath().projection(projection);
// 국가 경로 그리기
svg.selectAll("path")
.data(geojson.features)
.join("path")
.attr("d", path);
Step 2: 스타일링
색상과 테두리를 추가하여 지도를 더 보기 좋게 만듭니다. 격자선(graticule)도 추가합니다.
// 격자선 추가
const graticule = d3.geoGraticule();
g.append("path")
.datum(graticule())
.attr("d", path)
.attr("fill", "none")
.attr("stroke", "#ccc");
// 국가 스타일링
g.selectAll("path.country")
.attr("fill", "#69b3a2")
.attr("stroke", "#fff")
.attr("stroke-width", 0.5);
Step 3: 호버 인터랙션
마우스를 국가 위에 올리면 하이라이트되고 툴팁이 표시됩니다.
// 호버 이벤트
.on("mouseover", function(event, d) {
d3.select(this).attr("fill", "#3d8b6e");
tooltip.style("opacity", 1)
.html(d.properties.name);
})
.on("mouseout", function() {
d3.select(this).attr("fill", "#69b3a2");
tooltip.style("opacity", 0);
});
Step 4: 줌 & 팬
마우스 휠로 줌, 드래그로 팬이 가능합니다. 특정 지역을 자세히 살펴볼 수 있습니다.
// 줌 동작 설정
const zoom = d3.zoom()
.scaleExtent([1, 8]) // 1x ~ 8x 줌
.on("zoom", (event) => {
g.attr("transform", event.transform);
});
svg.call(zoom);
Step 5: Choropleth (단계구분도)
데이터에 따라 국가별로 다른 색상을 적용합니다. 여기서는 임의의 값을 사용합니다.
// 색상 스케일
const colorScale = d3.scaleSequential()
.domain([0, 100])
.interpolator(d3.interpolateBlues);
// 데이터 기반 색상 적용
.attr("fill", d => {
const value = getData(d.id); // 실제 데이터에서 가져옴
return colorScale(value);
});
정리
이 튜토리얼에서 다룬 내용:
- 기본 지도: TopoJSON 로드, 투영법, 경로 생성
- 스타일링: 색상, 테두리, 격자선
- 인터랙션: 호버 효과, 툴팁
- 줌 & 팬: d3.zoom() 활용
- Choropleth: 데이터 기반 색상 매핑
다음 단계로는 실제 데이터(인구, GDP 등)를 연결하거나, 마커/포인트를 추가하거나, 애니메이션을 적용할 수 있습니다.