반응형
내용은 나중에 다시 정리하더라도, 일단은 스니펫 으로 크게 남겨 둡니다. 제가 공부하면서 적어두는 것이라 좀 지저분 합니다. 혹시나 참고하는 분 있다면 이 점 고려해서 보시길 바랍니다. |
관련 문제나 사용법 등에 설명하는 글들은 정말 많지만, 이 내용을 기록해두는 목적은 kakao 가 정의되지 않았다 에러, LatLng 이 생성자 함수가 아니다 라는 둥의 에러가 떴을 때 나에게 맞는 명확한 방법이 없었기 때문이다. 혹여나 이 글을 보는 유사한 고민을 가진 분이 있다면 바로 해결 하길 바라며 남겨본다. |
// /*global kakao*/: 이 주석은 전역적으로 사용되는 변수 kakao를 선언한 것
// 이렇게 선언하면 ESLint와 같은 코드 검사 도구에서 해당 변수를 선언하지 않은 것으로
// 인식하는 오류를 방지 단, 이렇게 해도 정의되지 않았다고 뜨기도 하는데, 아래에서 설명함.
/*global kakao*/
import React, { useEffect } from "react";
import styles from "./KaMap.module.css";
// 이건 그냥 타입스크립트로 경도와 위도, 지도의 display 변수와 함수에 대한 타입을 지정해둔 것
// la? : 에서 ? 는 선택적 매개변수라고 해서 매개변수에 아무런 인자가 전달되지 않으면
// undefined 가 할당된다. 타입스크립트에서 해당값이 null 일 수도 있다는 경고를 듣고 수정한 것
interface KaMapType {
la?: string;
lo?: string;
isDisplay?: boolean;
setIsDisplay?: (state: boolean) => void;
}
function KaMap({ la = "33", lo = "33", isDisplay, setIsDisplay }: KaMapType) {
// 컴포넌트가 렌더링된 이후에 실행토록 useEffect 훅 내에서 api 관련 코드를 작성
useEffect(() => {
// script 를 html 에 동적으로 추가하기 위해 요소를 생성
const script = document.createElement("script");
script.type = "text/javascript";
script.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=[개인이 발급받은 api 키]&autoload=false`;
// 생성된 script 를 문서 객체의 head 속성의 마지막 자식요소로 추가
document.head.appendChild(script);
// id가 map 인 요소를 가져와서 container 변수에 할당
// ! : 타입스크립트에서 해당 변수의 타입이 절대 null 이나 undefined가 아니라고 명시할 때 사용
const container = document.getElementById("map")!;
// kakao 는 앞서 호출한 sdk 스크립트가 온전히 로드가 된 이후에 인식
// 따라서 script 요소에 onload 이벤트를 등록하여 script 가 완전히 로드 되면
// kakao map 코드가 차례대로 실행토록 콜백함수를 작성
// 이렇게 순차적으로 접근하지 않으면 어느 하나의 요소가 정의되지 않았다는 둥, 생성자 함수가 아니라는
// 둥 잡다한 에러 메시지가 뜨기 때문에 꼭 지켜줘야 할 것. 더 나은 방법이 있다면 그것도 좋음
script.onload = () => {
kakao.maps.load(function () {
const options = {
center: new kakao.maps.LatLng(Number(la), Number(lo)),
level: 3,
};
/* 이 부분은 kakao 에 대한 타입이 정의되어 있지 않은 관계로 타입 체크를 해제시킨 것.
여기서 kakao.maps.Map 생성자를 사용하여 container에 지도 객체를 생성.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const map = new kakao.maps.Map(container, options);
});
};
}, [la, lo]);
return (
<article
className={styles.Map}
style={isDisplay ? { display: "none" } : { display: "block" }}
>
<span
onClick={() => {
setIsDisplay && setIsDisplay(!isDisplay);
}}
className={styles.close_btn}
>
✕
</span>{" "}
<section
id="map"
className={styles.KaMap}
style={{ width: "500px", height: "500px", display: "block" }}
></section>
</article>
);
}
export default KaMap;
스크립트의 경우에는 index.html 파일에 집적 head 요소에 명시해도 된다. 하지만, 확인의 편의성을 위해서 한 곳에서 같이 처리했다. 그 외 다른 이유도 있지만, 이게 제일 크다. |
결과적으로 잘 나온다.
반응형
'리액트' 카테고리의 다른 글
[리액트 npm error] CRA 환경에서 nth-check 취약점 문제 (0) | 2023.09.11 |
---|---|
[리액트] 개인 코드 정리(리덕스 툴킷 타입스크립트 설정) (0) | 2023.07.26 |
[react] 리액트에서 카카오 맵 사용하기( with ReactKakaoMapSDK) (0) | 2023.07.21 |
[react hooks] 3. useContext 에 대한 정리 (0) | 2023.06.06 |
[react-router-dom] useSearchParams () 에 대한 정리 (0) | 2023.06.05 |