diff --git a/src/frontend/src/components/common/KakaoMap.tsx b/src/frontend/src/components/common/KakaoMap.tsx index d529ed1..339a887 100644 --- a/src/frontend/src/components/common/KakaoMap.tsx +++ b/src/frontend/src/components/common/KakaoMap.tsx @@ -1,48 +1,100 @@ import { useEffect, useState } from "react"; -import { Map, MapMarker } from "react-kakao-maps-sdk"; +import { Map, MapMarker, Polyline } from "react-kakao-maps-sdk"; +import axios from "axios"; +import { api } from "@/apis"; -const KakaoMap = () => { +interface LatLng { + lat: number; + lng: number; +} + +interface Route { + id: string; + path: LatLng[]; +} + +const KakaoMapWithMultiplePolylines = () => { const [state, setState] = useState({ - center: { - lat: 33.450701, // 초기 위치 설정 (임의의 위치) - lng: 126.570667, - }, - errMsg: null as string | null, // string | null 타입으로 지정 + center: { lat: 37.5665, lng: 126.978 }, // 기본 위치 (서울 시청) + errMsg: null as string | null, isLoading: true, + routes: [] as Route[], // GPX 경로 데이터를 저장 }); useEffect(() => { - if (navigator.geolocation) { - // GeoLocation을 이용해서 현재 위치를 얻습니다 - navigator.geolocation.getCurrentPosition( - (position) => { - setState((prev) => ({ - ...prev, - center: { - lat: 37.5665, // 임의의 위치(발표용) - lng: 126.978, // 임의의 위치(발표용) - // lat: position.coords.latitude, // 위도 - // lng: position.coords.longitude, // 경도 - }, - isLoading: false, - })); - }, - (err) => { - setState((prev) => ({ - ...prev, - errMsg: err.message, // 오류 메시지 설정 - isLoading: false, - })); - } - ); - } else { - // GeoLocation을 사용할 수 없는 경우 처리 - setState((prev) => ({ - ...prev, - errMsg: "geolocation을 사용할 수 없어요.", - isLoading: false, - })); - } + // 현재 위치를 가져오는 함수 + const getCurrentLocation = () => { + if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition( + (position) => { + setState((prev) => ({ + ...prev, + center: { + lat: position.coords.latitude, + lng: position.coords.longitude, + }, + })); + fetchGpxData(position.coords.latitude, position.coords.longitude); + }, + (err) => { + setState((prev) => ({ + ...prev, + errMsg: err.message, + isLoading: false, + })); + } + ); + } else { + setState((prev) => ({ + ...prev, + errMsg: "geolocation을 사용할 수 없어요.", + isLoading: false, + })); + } + }; + + // 서버에서 GPX 데이터를 가져오는 함수 + const fetchGpxData = async (lat: number, lon: number) => { + try { + const response = await api.get( + `/course/recommend?lat=${lat}&lon=${lon}` + ); // 서버에서 경로를 받아옴 + const gpxFiles = response.data; // GPX 파일 목록 + + const parsedRoutes = await Promise.all( + gpxFiles.map(async (file: { id: string; url: string }) => { + const gpxResponse = await axios.get(file.url); + const parser = new DOMParser(); + const xml = parser.parseFromString( + gpxResponse.data, + "application/xml" + ); + + const trackPoints = Array.from(xml.getElementsByTagName("trkpt")); + const path = trackPoints.map((point) => ({ + lat: parseFloat(point.getAttribute("lat") || "0"), + lon: parseFloat(point.getAttribute("lon") || "0"), + })); + + return { id: file.id, path }; + }) + ); + + setState((prev) => ({ + ...prev, + routes: parsedRoutes, + isLoading: false, + })); + } catch (err) { + setState((prev) => ({ + ...prev, + errMsg: "GPX 데이터를 가져오는 중 오류가 발생했습니다.", + isLoading: false, + })); + } + }; + + getCurrentLocation(); }, []); return ( @@ -55,11 +107,22 @@ const KakaoMap = () => { width: "100%", height: "100vh", }} - level={3} + level={5} > + {state.routes.map((route) => ( + + ))} + {state.errMsg &&
{state.errMsg}
} {!state.isLoading && } ); }; -export default KakaoMap; +export default KakaoMapWithMultiplePolylines;