본문 바로가기

리액트

[React] 리액트에서 카카오 맵 불러오기 (with kakao map)

반응형

 

내용은 나중에 다시 정리하더라도, 일단은 스니펫 으로 크게 남겨 둡니다. 제가 공부하면서 적어두는 것이라 좀 지저분 합니다.
혹시나 참고하는 분 있다면 이 점 고려해서 보시길 바랍니다.

관련 문제나 사용법 등에 설명하는 글들은 정말 많지만, 이 내용을 기록해두는 목적은 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 요소에 명시해도 된다. 하지만, 확인의 편의성을 위해서 한 곳에서 같이 처리했다. 그 외 다른 이유도 있지만, 이게 제일 크다.

 

 결과적으로 잘 나온다.

 

반응형