์๋
ํ์ธ์!
์ด๋ฒ ํฌ์คํ
์์๋ Google Maps API๋ฅผ ์ฌ์ฉํด์ ๋ํ๋ฏผ๊ตญ์ ์๋(์์ธ, ๋ถ์ฐ ๋ฑ)๋ฅผ GeoJSON ๋ฐ์ดํฐ ๊ธฐ๋ฐ์ผ๋ก ๋งต์ ๊ทธ๋ฆฌ๊ณ , ๊ฐ ์๋๋ณ๋ก ์๋ก ๋ค๋ฅธ ์์์ ์
ํ๋ณด๋ ๊ณผ์ ์ ์ ๋ฆฌํด๋ณด์์ต๋๋ค.
ํ๋ก ํธ์๋ ๊ธฐ์ ์คํ์ React + TypeScript์ด๋ฉฐ, ์ง๋ ์์ ๋ฐ์ดํฐ๋ฅผ ์๊ฐํํ๋ ๊ฐ๋จํ ์์ ๋ฅผ ๋ง๋ค์ด๋ดค์ต๋๋ค.
npm install @react-google-maps/api
@react-google-maps/api๋ Google Maps๋ฅผ React์์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
GeoJSON์ ๋ค์๊ณผ ๊ฐ์ด ์๊ธด ํํ๋ก, ๊ฐ ์๋๋ณ ๊ฒฝ๊ณ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ด์.
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [...]
},
"properties": {
"CTP_KOR_NM": "๋๊ตฌ๊ด์ญ์",
"CTP_ENG_NM": "Daegu"
}
}
properties.CTP_KOR_NM ์์ฑ์ ํ์ฉํด์ ์์์ ์ง์ ํฉ๋๋ค.
// components/KoreaMap.tsx
import { GoogleMap, LoadScript } from "@react-google-maps/api";
import { useRef } from "react";
const containerStyle = {
width: "100%",
height: "100vh",
};
const center = {
lat: 36.5,
lng: 127.5,
};
const regionColors: Record<string, string> = {
์์ธํน๋ณ์: "#e41a1c",
๋ถ์ฐ๊ด์ญ์: "#377eb8",
๋๊ตฌ๊ด์ญ์: "#4daf4a",
์ธ์ฒ๊ด์ญ์: "#984ea3",
๊ด์ฃผ๊ด์ญ์: "#ff7f00",
๋์ ๊ด์ญ์: "#ffff33",
์ธ์ฐ๊ด์ญ์: "#a65628",
์ธ์ข
ํน๋ณ์์น์: "#f781bf",
๊ฒฝ๊ธฐ๋: "#999999",
๊ฐ์ํน๋ณ์์น๋: "#66c2a5",
์ถฉ์ฒญ๋ถ๋: "#fc8d62",
์ถฉ์ฒญ๋จ๋: "#8da0cb",
์ ๋ผ๋ถ๋: "#e78ac3",
์ ๋ผ๋จ๋: "#a6d854",
๊ฒฝ์๋ถ๋: "#ffd92f",
๊ฒฝ์๋จ๋: "#e5c494",
์ ์ฃผํน๋ณ์์น๋: "#b3b3b3",
};
export default function KoreaMap({ geoJson }: { geoJson: any }) {
const mapRef = useRef<google.maps.Map | null>(null);
const onLoad = (map: google.maps.Map) => {
mapRef.current = map;
map.data.addGeoJson(geoJson);
map.data.setStyle((feature) => {
const name = feature.getProperty("CTP_KOR_NM");
const fillColor =
typeof name === "string" && name in regionColors
? regionColors[name]
: "#cccccc";
return {
fillColor,
strokeColor: "#555",
strokeWeight: 1,
fillOpacity: 0.6,
};
});
map.data.addListener("mouseover", (event: any) => {
map.data.overrideStyle(event.feature, { fillColor: "#FEB24C" });
});
map.data.addListener("mouseout", () => {
map.data.revertStyle();
});
};
return (
<LoadScript googleMapsApiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY!}>
<GoogleMap
mapContainerStyle={containerStyle}
center={center}
zoom={7}
onLoad={onLoad}
/>
</LoadScript>
);
}
์ฐธ๊ณ :
.envํ์ผ์ Google Maps API Key๋ฅผ ๋ฃ์ด์ฃผ๊ณREACT_APP_GOOGLE_MAPS_API_KEY=...ํ์์ผ๋ก ์ค์ ํด์ผ ํฉ๋๋ค.
์ฒ์์ ์ด๋ฐ ์๋ฌ๊ฐ ๋ฐ์ํ์ด์:
TS2538: Type 'unknown' cannot be used as an index type.
์ด๋ feature.getProperty("CTP_KOR_NM")์ ๋ฐํ ํ์
์ด unknown์ด๊ธฐ ๋๋ฌธ์ด์์ต๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด typeof name === "string"์ผ๋ก ๋จผ์ ์ฒดํฌํ ๋ค์,
name in regionColors๋ก ํค ์กด์ฌ ์ฌ๋ถ๋ฅผ ํ์ธํด ํ์
์์ ์ฑ์ ํ๋ณดํ์ต๋๋ค.
if (typeof name === "string" && name in regionColors) {
const fillColor = regionColors[name]; // ์์ !
}

map.data.addGeoJson()์ผ๋ก GeoJSON์ ์ง์ ์ถ๊ฐํ ์ ์๋ค.map.data.setStyle()์ Feature๋ณ๋ก ์คํ์ผ์ ์ปค์คํฐ๋ง์ด์งํ ์ ์๋ ์ ์ฉํ ๊ธฐ๋ฅ!value is Type ํํ์ ํ์
๊ฐ๋ ํจ์๋ก TypeScript์์๋ ์์ ํ GeoJSON ํธ๋ค๋ง์ด ๊ฐ๋ฅin ์ฐ์ฐ์๋ ๊ฐ์ฒด์ ํค ์กด์ฌ ์ฌ๋ถ๋ฅผ ์์ ํ๊ฒ ์ฒดํฌํ๋ ๋ฐ ๊ผญ ํ์ํจ์ง๋ ์๊ฐํ๋ ์๊ฐ๋ณด๋ค ์ฌ๋ฏธ์๊ณ , ํ์ฉ๋๊ฐ ๋์ ์์
์ด์์ต๋๋ค.
ํนํ GeoJSON์ ์ด๋ป๊ฒ ํ์ฉํ๋๋์ ๋ฐ๋ผ, ํ์ ๊ตฌ์ญ ์๊ฐํ๋ถํฐ ๋ฐ์ดํฐ ๊ธฐ๋ฐ ๋ถ์๊น์ง ๋ค์ํ ํ๋ก์ ํธ๋ก ํ์ฅํ ์ ์๊ฒ ๋ค๋ ๊ฐ๋ฅ์ฑ์ ๋๊ผ์ด์.
๊ถ๊ธํ ์ ์ด๋ ๋์์ด ํ์ํ์ ๋ถ์ ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์ธ์!
์ฝ์ด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค โบ๏ธ