FR_page.10

김수현·2025년 3월 25일

Suhyeon's 개발일지

목록 보기
13/34

기기의 위치를 경도 위도 뿐 만 아니라 고도로도 표현했다.
고도를 표현하기 위해 google의 elevation api를 사용했다.

일단 API를 사용하기 위해 google cloud에 가입을 하고 elevation API key를 신청했다.

const[elevations, setElevations] = useState({});
const getElevation = async (device) => {
    
    const lat = device?.install.lat;
    const lng = device?.install.lng;
    const targetUrl =  `https://maps.googleapis.com/maps/api/elevation/json?locations=${lat},${lng}&key=`;

    try {
        const response = await fetch(
        (targetUrl));

        const data = await response.json();
        
        if (data.status === "OK") {
        setElevations((prev) => ({
            ...prev,
            [device.IMEI]: data.results[0].elevation, // IMEI를 키로 사용하여 개별 기기 고도 저장
            }));
        } else {
        console.error("Elevation API Error:", data.status);
        alert("고도를 가져오지 못했습니다.");
        }
    } catch (error) {
        console.error("Error fetching elevation:", error);
    }
};

useEffect(() => {
    favoriteDevice.forEach((device) => {
        if (!elevations[device.IMEI]) {
        getElevation(device);
        }
    });
    }, [favoriteDevice, elevations]); // elevations을 넣지 않음 (무한 루프 방지)

favoriteDevice에 있는 기기들의 주소 정보를 가져와 고도를 구하도록 하였다. 각각의 기기에 해당하는 고도를 표현하기 위해 IMEI를 key로 설정한 후 고도를 지정해줬다.
prev는 기존 상태를 뜻하고, 새로운 imei가 들어오면 imei를 key로 지정하여 새로운 값을 상태에 추가해준다.

해당 기기의 경도와 위도를 가져와서 고도를 구하는 것은 구현했지만, 월 5000회만 무료인 점에서 구조를 다시 생각해봐야 할 것 같다..
이 코드는 화면에 들어올 때마다 로드가 되면서 api를 불러오게 된다. 지금은 하나의 기기로만 테스트 중이기 때문에 횟수에는 지장이 없지만 나중에 많은 기기를 하기에는 무리가 있다.

내가 원하는 방법은 주소를 설정할 때 table에 elevation column을 추가해서 같이 저장되도록 하고 싶어서 도전해봤지만, 아직 백엔드와의 연동 부분에서 어려움을 느껴서 다시 공부하고 코드를 구현하려고 한다.

위의 코드에서 주소가 지정되지 않았을 때의 기능도 추가 구현해야한다.

 color: '#6183DB'{elevations[d.IMEI] !== undefined? `${elevations[d.IMEI].toFixed(2)}m`: "불러오는 중..."

화면에서 불러올 땐 위의 코드로 불러온다.

kakao.maps.event.addListener(marker, "click", function () {
const lat = location.getLat();
const lng = location.getLng();

// 🔥 기존 선택된 2개 마커 초기화 (3번째 마커 클릭 시)
if (clickedMarkers.length === 2) {
    clickedMarkers.forEach((m) => m.setImage(redMarkerImage)); // 원래 크기로 변경
    clickedMarkers = []; // 배열 초기화
    firstClick = null; // 첫 번째 클릭 정보 초기화
}

// 현재 클릭된 마커 추가
clickedMarkers.push(marker);
marker.setImage(bigRedMarkerImage); // 큰 마커로 변경

if (clickedMarkers.length === 1) {
    // 첫 번째 마커 선택
    firstClick = { lat, lng };
    let newPosition = moveLatLngUp(lat, lng, 0.0001);
    infowindow.setContent(`<div style="padding:5px;">                                
        <strong>위도:</strong> ${convertToDMS(lat.toFixed(6))}<br>
        <strong>경도:</strong> ${convertToDMS(lng.toFixed(6))}</div>`);
    infowindow.setPosition(newPosition); 
    infowindow.setMap(map);
    console.log("첫 번째 마커 선택:", firstClick);
} else if (clickedMarkers.length === 2) {
    // 두 번째 마커 선택 → 거리 계산 후 표시
    const distance = getDistance(firstClick.lat, firstClick.lng, lat, lng);
    console.log("두 마커 사이의 거리:", distance.toFixed(0), "m");

    let newPosition = moveLatLngUp(lat, lng, 0.0001);
    infowindow.setContent(`<div style="padding:5px;">
        <strong>두 위치의 거리: ${distance.toFixed(0)} m</strong><br>
        <strong>위도:</strong> ${convertToDMS(lat.toFixed(6))}<br>
        <strong>경도:</strong> ${convertToDMS(lng.toFixed(6))}</div>`);
    infowindow.setPosition(newPosition); 
    infowindow.setMap(map);
}

두 개의 마커 선택 시 두 위치의 거리를 표시하는 기능을 조금 더 확실하게 표현해 주었다.
두 개의 마커 클릭 시 bigRedMarkerImage를 설정해주었고, 두 마커의 거리를 표시해주었다.
3번째 마커를 클릭하게 되면 배열을 초기화 하고 원래의 마커 크기로 변경했다. 하나 마커 클릭 시 경도 위도를 표시해주었다.

0개의 댓글