시도 별로 행정구역을 나누는 작업을 진행한 내용입니다.
행정구역 데이터 파일 📖
SHP 파일
시도, 시군구, 읍면동, 리 별로 데이터가 있어 원하는 파일을 다운 받으면 됩니다.
저는 시도 정보가 필요했기 때문에 가장 최신 SHP 파일을 다운로드 했습니다.
파일을 다운로드하고 압축을 풀면 3개의 파일이 들어있습니다.
방위나 지도가 담긴 공간 데이터 파일을 JSON 파일로 사용하기 위해 `XrProjection` 으로 변환을 해야 합니다.
`XrProjection`을 실행시키면 아래 사진과 같은 화면이 나오게 됩니다.
입력 SHP에 아까 다운로드한 `ctprvn.shp`
좌표계는 `UTM-K(GRS80 타원체)`
아래 좌표계는 `WGS84 타원체의 경위도`
출력 SHP는 기존 `ctprvn.shp`를 선택하고 뒤에 `_wgs84`를 붙여주고 변환 버튼 클릭
파일 변환에 성공하게 되면 `_wgs84`가 붙은 파일 3개가 생성이 됩니다.
이렇게 방위를 변환한 파일을 JSON 파일로 변경하기 위해서는 아래 사이트에 접속해 줍니다.
아까 생성된 3개의 파일을 선택하고 `encoding=euckr`을 적어줍니다.
❓`encoding=euckr`을 적는 이유
SHP 내용 중 한글로 되어 있는 부분을 깨지지 않도록 하기 위해서입니다!
이후 Submit 버튼을 누르게 되면 아래 같이 시도 지도가 나오게 됩니다!!
근데 우리나라는 섬이 엄청 많기 이대로 변환하면 지도 용량이 커지게 됩니다. 그래서 작은 섬들은 나타나지 않게 간략화해주기 위해서 우측 상단에 `Simplify` 버튼을 클릭하고 prevent shape removal을 체크하고 `Apply`버튼을 눌러줍니다.
그리고 위에 Settings 바를 움직이면서 시군 경계면 지역을 보면서 조절을 하면 됩니다!
이제 `Export`버튼을 눌러 `GeoJSON`을 체크하고 precision=0.001 encoding=utf-8을 적어주고 `Export`버튼을 눌러줍니다.
❓ Precision, Encoding
`Precision`은 위경도의 소수점 몇 자리까지를 표시할지를 결정하는데 시도를 보여 주는 것으로 그리 정밀하지 않기 때문에 3자리로 설정을 하고 `Encoding`은 한글이 깨지지 말라고 utf-8로 설정을 했습니다.
JSON 파일
다운로드한 파일을 이제 적용만 해주면 끝입니다!
코드 작성 📖
JSON 데이터
`features > geometry > coordinates` 속성에 해당 지역 좌표들이 배열로 들어있는 걸 확인할 수 있습니다.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[128.54880989370014, 38.301950820518755],
[128.5600921732829, 38.25735515107489],
....
]
]
},
"properties": {
"CTPRVN_CD": "42",
"CTP_ENG_NM": "Gangwon-do",
"CTP_KOR_NM": "강원도"
}
},
....
],
}
받아온 json 데이터에서 type이 `Polygon`이면 3차원 배열로 `MultiPolygon`이면 4차원 배열로 구성되어 있습니다.
const [geoList, setGeoList] = useState([]);
useEffect(() => {
const { features } = coordRegionCode;
const data = [];
for (let item of features) {
const { geometry, properties } = item;
const { CTP_KOR_NM } = properties;
const { coordinates, type } = geometry;
const pathList = [];
if (type === "Polygon") {
for (let areaList of coordinates) {
const path = [];
for (let area of areaList) {
path.push({
lng: area[0],
lat: area[1],
});
}
pathList.push(path);
}
} else if (type === "MultiPolygon") {
for (let polygon of coordinates) {
for (let areaList of polygon) {
const path = [];
for (let area of areaList) {
if (Array.isArray(area)) {
path.push({
lng: area[0],
lat: area[1],
});
}
}
pathList.push(path);
}
}
}
data.push({
name: CTP_KOR_NM,
path: pathList,
isHover: false,
key: Math.random(),
});
}
setGeoList(data);
}, []);
그래서 조건문을 통해 3,4차원에 배열을 `pathList`에 push 해줍니다.
geoList를 map 메서드를 이용해 `Polygon`을 만들어줍니다.
return (
<Map
id="map"
center={{
// lat: 36.450701,
// lng: 127.570667,
lat: 35.90701,
lng: 127.570667,
}}
className="w-[100vw] h-[100vh] relative"
level={12}
>
{geoList.map((item, index) => {
const { key, path, isHover } = item;
const color = globalColor[index];
return (
<Polygon
key={key}
path={path}
strokeWeight={2} // 선의 두께입니다
strokeColor={color} // 선의 색깔입니다
strokeOpacity={0.8} // 선의 불투명도 입니다
strokeStyle={"solid"} // 선의 스타일입니다
fillColor={isHover ? color : "#ffffff"} // 채우기 색깔입니다
fillOpacity={0.4} // 채우기 불투명도 입니다
onMouseover={() => {
// 마우스 오버시 색 변경
setGeoList((pre) =>
pre.map((area) => {
if (area.key === key) {
return {
...area,
isHover: true,
};
}
return area;
})
);
}}
onMouseout={() => {
// 색 다시 reset
setGeoList((pre) =>
pre.map((area) => {
if (area.key === key) {
return {
...area,
isHover: false,
};
}
return area;
})
);
}}
/>
);
})}
</Map>
);
출처 🏷️
https://blog.naver.com/PostView.nhn?blogId=kcchang61&logNo=221350672356
'공부 > Next' 카테고리의 다른 글
Next 커스텀 훅을 사용한 모달창 기능 구현 (1) | 2024.11.01 |
---|---|
[리팩토링] 데이터 로직 분리 및 서버 상태 관리 최적화 (0) | 2024.10.28 |
Next 카카오맵을 활용한 시도별 가로 스크롤 버튼 이동 구현 (0) | 2024.10.28 |
[리팩토링] Next 카카오 맵 폴리곤 렌더링 리팩토링 - 커스텀 훅, 유틸 함수 구조 개선 (0) | 2024.10.24 |
Next 카카오 맵 구현 (0) | 2024.10.23 |
[Next, Supabase Auth] 이메일, 소셜 로그인 기능 구현 및 트리거 설정 (2) | 2024.10.14 |
Next.js 알아보기 8 (Caching - 어려움 주의) (0) | 2024.09.27 |
Next.js 알아보기 7 (Route Handler & Server Action) (0) | 2024.09.26 |