Contact 페이지에서는 임의의 주소를 입력하고, 해당 서비스를 운영하는 사무실인 것처럼 구성하려 한다.

이를 위해 카카오맵 API를 호출했다.

 

구현 방법은 다른 공식 문서에 비해 가독성도 높고, 구현하기 간단했다.

 

https://apis.map.kakao.com/

 

 

 

 

자바스크립트로 구현 방법이 설명되어 있는데, 이것을 타입스크립트로 바꿔보았다.

많은 글에서 <script> 태그를 index.html에 삽입하라고 쓰여 있지만, 동적으로 태그를 추가할 수 있도록 구현해보았다.

import { useEffect } from "react";
import s from "../stores/styling";

const FetchMap = () => {

//useEffect를 통해 컴포넌트 마운트 될 때 <script>태그를 동적으로 추가하는 법
  useEffect(() => {
    const loadKakaoMapScript = () => {
      return new Promise<void>((resolve, reject) => {
        const script = document.createElement("script");    //<script>태그 생성
        script.type = "text/javascript";
        //api키는 프로젝트 루트 디렉토리 .env 파일에 저장. CRA 보안 정책
        script.src = `//dapi.kakao.com/v2/maps/sdk.js?autoload=false&appkey=${process.env.REACT_APP_KAKAO_MAP_KEY}&libraries=services`;
        
        //onload (then 역할)와 onerror (catch 역할)은 <script>요소의 이벤트 핸들러 속성으로 제공됨.
        script.onload = () => { //성공
          resolve();
        };
        script.onerror = () => {    //실패
          reject(new Error("Kakao Map script loading error"));
        };
        document.head.appendChild(script);  //생성된 <script>를 HTML <head>에 추가
      });
    };

    //지도 초기화
    const initMap = () => {

      if (!window.kakao || !window.kakao.maps) {
        console.error("Kakao maps library is not loaded.");
        return;
      }

      let container = document.getElementById("map"); // 지도를 담을 영역의 DOM 레퍼런스
      let options = {
        center: new window.kakao.maps.LatLng(33.450701, 126.570667), // 지도 중심 좌표
        level: 3, // 지도의 레벨(확대, 축소 정도)
      };
      
      // kakao 객체가 window 하위 객체라고 정의해야하므로 window.kakao라고 표기
      let map = new window.kakao.maps.Map(container, options); // 지도 생성 및 객체 리턴
    };

    loadKakaoMapScript()
      .then(() => { //지도 로드 성공 시, 지도 초기화
        initMap();
      })
      .catch((error) => {   //지도 로드 실패 시, 로그 메세지
        console.error(error);
      });
  }, []);   //마운트 시 한번만 수행

  return <s.Map id="map" />;
};

export default FetchMap;

 

정석대로 따라간 것처럼 보이지만, 

'Property 'kakao' does not exist on type 'Window & typeof globalThis'. 라는 오류가 나타난다.

이것은 kakao 객체가 window에 있는지 확인할 수 없기 때문이다.

따라서 전역으로 선언하여 kakao 객체를 알아볼 수 있도록 declare global을 해준다.

// 'Property 'kakao' does not exist on type 'Window & typeof globalThis'.' 오류에 대한 해결법.
// kakao 객체가 window에 있다고 declare로 명시한다.
declare global {
  interface Window {
    kakao: any;
  }
}

 

 

이럼에도 불구하고 TypeError: window.kakao.maps.LatLng is not a constructor 라는 또다른 에러가 나타난다.

 

* 많은 글에서 스크립트 파라미터, 즉 src 부분에 &autoload=false 을 추가해야 한다는 조언을 받았는데...

   나의 경우 달라지는 점이 보이지 않았다.

 

한참의 서칭 끝에 해결법을 알아냈다.

 

window.kakao.maps가 아직 로드되지 않았는데 initMap이 먼저 실행되어 충돌이 일어나는 것으로 보였다.

따라서 initMap이 실행되는 시점을 정확하게 명시해보았다.

 

//...전략

 loadKakaoMapScript()
      .then(() => { 
        window.kakao.maps.load(initMap);
        //window.kakao.maps가 로드됐을 때 initMap 실행
      })
      .catch((error) => {
        console.error(error);
      });
  }, []);
  
  //...후략

 

 

 

 

비로소 브라우저에 지도가 온전히 나타나는 것을 확인할 수 있다.

+ Recent posts