디벨로퍼스 앱 ID 829278
JS,React,TS 사용, 어플리케이션 내의 날씨 모달창을 작업중입니다
기상청 날씨 API로 현재 위치를 따면 nx, ny 이런식으로 나와서
그 위치를 토대로 역지오코딩을 통해 00시 00구 00동으로 현재 위치를 텍스트로 보이게 하려 합니다
https://apis.map.kakao.com/web/sample/coord2addr/
이 문서를 보고 구현해보았는데
// WeatherModal.tsx
import React, { useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faTimes, faMapMarkerAlt } from "@fortawesome/free-solid-svg-icons";
import { useWeatherData } from "./useWeatherData";
import WeatherDisplay from "./WeatherDisplay";
import { useReverseGeocoding } from "./useReverseGeocoding";
import { useLocation } from "./useLocation";
interface WeatherModalProps {
isOpen: boolean;
onClose: () => void;
}
const WeatherModal: React.FC<WeatherModalProps> = ({ isOpen, onClose }) => {
const {
location,
isLoading: isLocationLoading,
error: locationError,
} = useLocation(isOpen);
const {
weatherData,
isLoading: isWeatherLoading,
error: weatherError,
} = useWeatherData(isOpen);
const address = useReverseGeocoding(
location?.latitude ?? 0,
location?.longitude ?? 0
);
useEffect(() => {
console.log("Location:", location);
console.log("Address:", address);
}, [location, address]);
if (!isOpen) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white p-6 rounded-lg max-w-sm w-full">
<div className="flex justify-between items-center">
<h2 className="text-xl font-bold">현재 날씨</h2>
<button
onClick={onClose}
className="text-gray-500 hover:text-gray-700"
>
<FontAwesomeIcon icon={faTimes} />
</button>
</div>
<div className="mt-2">
<FontAwesomeIcon icon={faMapMarkerAlt} className="mr-2" />
<span>
{isLocationLoading
? "위치 불러오는 중..."
: locationError
? locationError
: address || "주소를 가져올 수 없습니다"}
</span>
</div>
<WeatherDisplay
weatherData={weatherData}
isLoading={isWeatherLoading}
error={weatherError}
/>
</div>
</div>
);
};
export default WeatherModal;
// useReverseGeocoding.ts
import { useState, useEffect } from "react";
import { loadKakaoMapScript } from "../../utils/kakaoMapLoader";
declare global {
interface Window {
kakao: any;
}
}
export const useReverseGeocoding = (latitude: number, longitude: number) => {
const [address, setAddress] = useState<string>("");
useEffect(() => {
if (latitude && longitude) {
loadKakaoMapScript()
.then(() => {
if (
!window.kakao ||
!window.kakao.maps ||
!window.kakao.maps.services
) {
console.error("Kakao Maps API is not fully loaded");
setAddress("주소를 가져올 수 없습니다");
}
const geocoder = new window.kakao.maps.services.Geocoder();
const coords = new window.kakao.maps.LatLng(latitude, longitude);
geocoder.coord2RegionCode(
coords.getLng(),
coords.getLat(),
(result: any, status: any) => {
if (status === window.kakao.maps.services.Status.OK) {
for (let i = 0; i < result.length; i++) {
if (result[i].region_type === "H") {
setAddress(
`${result[i].region_1depth_name} ${result[i].region_2depth_name} ${result[i].region_3depth_name}`
);
break;
}
}
} else {
setAddress("주소를 가져올 수 없습니다");
}
}
);
})
.catch((error) => {
console.error("Error initializing Kakao Maps:", error);
setAddress("주소를 가져올 수 없습니다");
});
}
}, [latitude, longitude]);
return address;
};
// kakaoMapLoder.ts
declare const kakao: any;
let isLoading = false;
let isLoaded = false;
export const loadKakaoMapScript = (): Promise<void> => {
return new Promise((resolve, reject) => {
if (isLoaded) {
resolve();
return;
}
if (isLoading) {
const checkLoaded = setInterval(() => {
if (isLoaded) {
clearInterval(checkLoaded);
resolve();
}
}, 100);
return;
}
isLoading = true;
const script = document.createElement("script");
script.type = "text/javascript";
script.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.REACT_APP_KAKAO_API}&libraries=services`;
script.onload = () => {
window.kakao.maps.load(() => {
isLoaded = true;
isLoading = false;
console.log("Kakao Maps script loaded and initialized successfully");
resolve();
});
};
script.onerror = (error) => {
isLoading = false;
console.error("Error loading Kakao Maps script:", error);
reject(
new Error(
`Failed to load Kakao Maps script. Please check your API key (${process.env.REACT_APP_KAKAO_API}) and network connection.`
)
);
};
document.head.appendChild(script);
});
};
const displayCurrentLocation = (latitude: number, longitude: number) => {
loadKakaoMapScript() // Kakao 지도 스크립트가 완전히 로드된 후 실행
.then(() => {
const geocoder = new window.kakao.maps.services.Geocoder();
const coords = new window.kakao.maps.LatLng(latitude, longitude);
// 좌표로 행정동 주소 정보를 요청
geocoder.coord2RegionCode(
coords.getLng(),
coords.getLat(),
(result: any, status: any) => {
if (status === window.kakao.maps.services.Status.OK) {
for (let i = 0; i < result.length; i++) {
// 행정동(region_type === 'H') 주소만 가져옴
if (result[i].region_type === "H") {
const currentLocation = `${result[i].region_1depth_name} ${result[i].region_2depth_name} ${result[i].region_3depth_name}`;
document.getElementById("current-location")!.innerText =
currentLocation;
break;
}
}
} else {
console.error("Failed to fetch address");
}
}
);
})
.catch((error) => {
console.error("Error loading Kakao Maps script:", error);
});
};
const getCurrentLocation = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;
displayCurrentLocation(latitude, longitude);
},
(error) => {
console.error("Error fetching current location:", error);
}
);
} else {
console.error("Geolocation is not supported by this browser.");
}
};
loadKakaoMapScript()
.then(() => {
getCurrentLocation();
})
.catch((error) => {
console.error("Kakao Maps script failed to load:", error);
});
이렇게 했을때 대체로 이 오류가 나타납니다
API 키와 플랫폼 도메인은 확인하였습니다
22Third-party cookie will be blocked in future Chrome versions as part of Privacy Sandbox.
kakaoMapLoader.ts:64 Error loading Kakao Maps script: TypeError: Cannot read properties of undefined (reading 'Geocoder')
at eval (kakaoMapLoader.ts:45:51)
지오코더를 계속 불러오질 못해서 찾아보다
https://developers.kakao.com/docs/latest/ko/getting-started/scope-of-support#local
여기 API 지원 범위를 확인해 보니 이 기능은 REST API로만 제공하는것 같은데
지도 API 사이트에는 또 자바스크립트로 구현이 되어있으니 제가 잘못 코드를 짜고 있는건지,
지원이 안되는걸 계속 하고 있는건지 모르겠습니다 도와주십시오