리액트에서 구글 맵 적용시 페이지 이동(리액트 라우트)

SPA 환경에서 구글 맵

이미 구글 맵을 한번 로드한 상태에서 리액트 라우트를 통해서 페이지 이동시 URL 변경은 있지만 실제로 이동은 하지 않은 상태인데 구글맵 스크립트를 또 불러서 문제가 생긴적이 있었다. 그리고 아래처럼 해결하려고 했었다.

const apiKey = ''; // 제거

const removeScript = () => {
  if (window.google) {
    const scripts = document.getElementsByTagName('script');
    const googleCodes = [].filter.call(
      scripts,
      (script) => script.src.indexOf(apiKey) > 0,
    );

    for (const script of googleCodes) {
      document.head.removeChild(script);
    }

    window.google = undefined;
  }
};

참고 : stackoverflow

그런데 이런 삽질 할 필요 없이 리액트 라우트에서 처리해주면 된다.

const loadScript = (apiKey) =>
  new Promise((resolve) => {
    if (!window.google) {
      return $.getScript(
        `https://maps.googleapis.com/maps/api/js?key=${apiKey}`,
      ).done((script, textStatus) => {
          resolve('done');
      }).fail((jqxhr, settings, exception) => {
        console.log(exception);
        resolve('fail');
      });
    }

    resolve('fail');
  });

let map;

const initGoogleMap = (elementId, option) => {
  // 생략...

  map = new window.google.maps.Map(document.getElementById(elementId), option);
};

위처럼 로드와 초기화를 구분하여 컴포넌트화 해놓고 useParams 훅을 이용해서 페이지 이동시 구글 지도를 이미 로드했다면 초기화만 새로 해주는 식으로 사용하면 된다.

const urlParams = useParams();

useEffect(() => {
  if (window.google) {
    initGoogleMap();
  }
}, [urlParams.key]);