프로젝트/React+TypeScript

[React & TS] Kakao 지도 API 추가

dev-hpk 2024. 11. 13. 11:30

1. 애플리케이션 추가 및 키 발급

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

위 주소에서 애플리케이션을 등록하고 로컬 환경을 도메인으로 추가했다.

 

 

키도 발급 완료했으니 공식 문서를 보면서, 화면에 지도를 띄워보겠습니다.

 

2. 지도를 그리는 JavaScript API 불러오기

index.html에 직접 <script> 태그를 추가해 로드하는 방법으로 따라 했다.

<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은 APP KEY를 넣으시면 됩니다."></script>

 

 

서버를 실행시켜 확인해 보니, 내 api key가 개발자 도구에 그대로 노출되고 있었다.

 

3. API Key env로 관리하기

API Key를 Github이나 서버에서 개발자 도구로 확인하지 못하게 하기 위해 .env에서 환경변수로 관리하기로 했다.

// .env
KAKAO_MAP_API_KEY = ~~KEY 값~~
process.env.KAKAO_MAP_API_KEY

 

평소처럼 process.env로 env에 선언한 KEY 값을 사용하려고 했는데, process is not defined라는 오류가 발생했다.

찾아보니 vite로 만든 프로젝트에서는 process.env 대신 import.meta.env를 사용해야 한다고 한다. 추가로 vite로 접근하기 위한 환경변수는 일반 환경변수와 구분하기 위해 접두사로 "VITE_"를 작성해줘야 한다고 한다.

 

Vite

Vite, 프런트엔드 개발의 새로운 기준

ko.vite.dev

 

4. 지도 영역 생성 및 지도 띄우기

위에서 html에 <script> 태그를 사용하는 방법을 찾아보니 치명적인 단점들이 있었다.

  • 성능 문제: 앱 전체에 항상 로드되므로, 모든 페이지에서 지도를 사용하는 것이 아니라면 불필요한 리소스 로딩이 발생할 수 있습니다.
  • 환경 변수 사용 제한: 일반적으로 직접 index.html에 작성한 <script> 태그는 환경 변수를 적용하기 어렵습니다.
  • 보안 문제 :  API 키를 동적으로 관리하기가 어려워 보안적인 측면에서 유연성이 떨어질 수 있습니다.

위와 같은 문제를 해결하기 위해 지도를 랜더링 하는 KaKaoMap 컴포넌트를 만들었습니다.

import { useEffect, useRef } from 'react';

// Kakao 지도 API는 window 객체에 kakao라는 글로벌 객체를 추가합니다. 
// TypeScript는 kakao 객체의 타입을 알지 못하기 때문에 
// declare global로 window.kakao의 존재를 알립니다.
declare global {
  interface Window {
    kakao: any;
  }
}

function KaKaoMap() {
  const container = useRef<HTMLDivElement>(null); // 지도를 표시할 DOM 요소를 참조하는 Ref 객체
  
  useEffect(() => {
    const script = document.createElement('script');
    script.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${
      import.meta.env.VITE_KAKAO_MAP_API_KEY
    }&autoload=false`;
    script.async = true;
    document.head.appendChild(script);

    script.onload = () => {
      window.kakao.maps.load(() => {
        const options = {
          //지도를 생성할 때 필요한 기본 옵션
          center: new window.kakao.maps.LatLng(33.450701, 126.570667), //지도의 중심좌표.
          level: 3, //지도의 레벨(확대, 축소 정도)
        };

        new window.kakao.maps.Map(container.current, options); //지도 생성 및 객체 리턴
      });
    };
  }, []);
  return (
    <div>
      <div
        ref={container}
        id="map"
        style={{ width: '500px', height: '400px' }} // 지도 확인을 위한 임시 스타일
      />
    </div>
  );
}

export default KaKaoMap;

 

KaKaoMap 컴포넌트는 마운트 될 때 동적으로 지도를 생성하는 API를 로드하기 때문에 필요한 곳에서만 지도를 사용해 불필요한 리소스 로딩에 대한 문제를 해결했습니다. 추가로 import.meta.env로 환경변수를 사용할 수 있어 개발자 도구에 API Key가 노출되는 것을 해결했습니다.

useEffect(() => {
    const script = document.createElement('script');
    script.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${
      import.meta.env.VITE_KAKAO_MAP_API_KEY
    }`;
    script.async = true;
    document.head.appendChild(script);

    // 스크립트가 완전히 로드된 후 window.kakao.maps.load가 호출되며,
    // 이를 통해 Kakao 지도가 생성됩니다.
    script.onload = () => {
      window.kakao.maps.load(() => {
        const options = {
          //지도를 생성할 때 필요한 기본 옵션
          center: new window.kakao.maps.LatLng(33.450701, 126.570667), //지도의 중심좌표.
          level: 3, //지도의 레벨(확대, 축소 정도)
        };

        new window.kakao.maps.Map(container.current, options); //지도 생성 및 객체 리턴
      });
    };
  }, []);

 

5. 서버 실행 후  지도 확인하기

또 에러다...😅😅😅

https://apis.map.kakao.com/web/documentation/#load_load

위 내용을 참고해 autoload=false 파라미터를 추가했더니, 지도가 잘 나온다😂😂

이제 다른 라이브러리들 추가로 불러와서 여러 기능들을 만들어 봐야겠다.