Google Map을 간단하게 React에서 사용하여 <Map />컴포넌트를 만드는 방법이다.
항상 외부 라이브러리나 기술을 다룰때는
- 공식문서 ⇒ 정답
- 기타 레퍼런스 자료들(타 코드) ⇒ 항상 정답은 아님
아무튼..
google Cloud Platform으로 지금 구글의 API서비스는 모두 합쳐진 상황이다.
웹에서 google Map API를 사용하는 경우, Maps Javascript API를 사용하면 된다.
다음은 Javascript에서 사용하는 google Map API의 Document주소이다.
이런 API들은 다 사용하는 방법이 똑같다.
- 먼저 API키를 발급받는다.
- 로드할때 API키를 가지고 API를 호출한다.
- 끝
Next.js 에서의 사용
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap&libraries=&v=weekly" async ></script>
현재 구글에서 만들어준 예제에는 위의 script tag가 지도를 불러와야하는 html에서 세팅이 되어서 필요한 자바스크립트 파일들을 요청하고 있다.
React의 경우 index.html이 존재하기 때문에 이것은 굉장히 쉽게 해결이 될 수 있다.
특히나 React에서 html에서 .env의 변수를 불러오는 것을 지원하기 때문에 불러오는 것은 굉장히 쉽게 해결이 된다.
하지만 Next.js에서는 index.html이 존재하지 않는다.
그래서 pages 디렉토리에 _documents.js를 생성하고 return하는 jsx문법에 위의 script태그를 추가하는 식으로 작업을 할 수도 있을 것이다.
그렇지만 이렇게 할 경우 문제가 있다. Map을 사용하지 않는 곳에서도 google Map API에 필요한 자원들이 불러와지고 사용되지 않는 낭비가 일어난다.
따라서 Map을 컴포넌트화하고 Map 컴포넌트가 쓰여진 페이지에서만 Map을 만드는데 필요한 통신과 자원이 불러와지도록 할 필요가 있다.
<div id="map"></div>
위의 보이는 div안에 id가 map인 태그가 문서를 읽어보면 알겠지만, Map API가 불러와지면 찾는 진입점이다.
따라서 저 마크업이 들어가있는 컴포넌트를 만들면 된다.
const Map: FC<MapProps> = ({ width, height}) => { return (<div id="map" style={{ width: width, height: height}}></div>) }
위처럼 마크업을 해주고 나서 이제 script를 불러오면 된다.
다음의 방법은 누군가 이미 했던 방법을 참고한 것이다. 레퍼런스 자료에 링크를 남겨두도록 하겠다.
const [mapLoaded, setMapLoaded] = useState<boolean>(false); useEffect(() => { const $script = document.createElement("script"); $script.src = "https://maps.googleapis.com/maps/api/js?key=AIzaSyCG1xfBcGHsvwjampRyLW78W8XypHwE8Jo"; $script.addEventListener("load", () => setMapLoaded(true)); document.body.appendChild($script); }, []);
그러고나서 위 처럼 컴포넌트 내에 useState, useEffect 훅을 이용하여 script를 불러오게 한다.
이때 useEffect의 의존성 배열이 비어있는 것을 보면 초기 렌더링때 저 Effect내의 콜백함수가 한번만 호출된다는 것을 알 수 있다.
그러고 나서 밑에 useEffect(() ⇒ {}, [])를 사용하여서 지도에 Marker, customOverlay등을 붙여주면 된다.
현재는 React에 google Map을 사용할 수 있는 npm package가 생겼기 때문에 사실 이렇게 하지 않아도 된다고 한다... 하..