상권's

TIL 80 (카카오 지도 API 사용하기) 본문

~2022 작성 글/TIL

TIL 80 (카카오 지도 API 사용하기)

라마치 2022. 4. 25. 16:03

지난 주말동안 선정된 메뉴를 판매하는 식당을 지도에 출력하는 기능을 구현해보았습니다. 카카오 지도 API를 이용해서 지도 기능 구현 과정을 공유해보겠습니다.

 

먼저, 지난 카카오 로그인과 같이 Kakao Developer에서 애플리케이션을 등록해야 합니다.

카카오 Developer 이동하기

 

Kakao Developers

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

developers.kakao.com

 

카카오 Developer에서 애플리케이션 등록하는 방법은 TIL 78 앞 부분을 참고하시면 됩니다.

TIL 78 이동하기

 

TIL 78 (개인 프로젝트 카카오 로그인 구현)

지난 주말부터 개인 프로젝트의 소셜 로그인을 구현해봤습니다. 네이버와 카카오 로그인 기능을 구현했는데 카카오 로그인 먼저 알아보겠습니다. 카카오 로그인은 Kakao Developers에서 애플리케이

sangkwon2406.tistory.com

 

애플리케이션 등록한 후 카카오 지도 API 페이지를 참고해서 코드를 구현했습니다.

카카오 지도 API 페이지

 

Guide의 시작하기를 따라서 구현해보겠습니다.

먼저 '지도를 담을 영역 만들기' 코드는 MapPage의 return 부분에 넣어주고, 클라이언트 단 html에 '실제 지도를 그리는 Javascript API를 불러오기'를 추가해주겠습니다.

 

여기서 발급받은 APP KEY는 왼쪽 하단의 열쇠 모양으로 들어가서 등록한 애플리케이션의 키 중 JavaScript 키를 넣어주면 됩니다.

 

//theMenu/client/public/index.html

  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script src="//dapi.kakao.com/v2/maps/sdk.js?appkey=%REACT_APP_KAKAO_JAVASCRIPT_KEY%&libraries=services"></script>

저는 <div id='root'></div>의 아랫 부분에 추가해주었습니다. 자바스크립트 키는 .env에 작성한 후 저렇게 불러왔습니다.  뒤에 추가된 libraries=services는 사용자가 선정한 메뉴를 키워드로 식당을 찾을 때 사용되기 때문에 추가합니다.

 

구현하려는 기능이 사용자 인근에서 해당 메뉴를 판매하는 식당을 나타내는 것이기 때문에 사용자의 위치를 먼저 찾도록 하겠습니다.

아래의 사진은 카카오 지도 API에서 확인되는 저의 현재 위치입니다. 코드 구현 후 동일하게 위치가 잡히는 지 확인해보겠습니다. 사실 지도 상에서 세븐 일레븐 편의점 근처에 살고 있는데 저렇게 표시가 되고 있습니다. 그래서 카페같이 몇 군데에서 더 테스트해보고 수정할 예정입니다.

해당 페이지에서 제공하는 코드에서 HTML5의 geolocation으로 사용할 수 있는지 확인하는 if문만 복사해서 MapPage의 useEffect문에 붙여넣었습니다.

 

그리고 선정된 메뉴를 키워드로 장소를 검색하기 위해 라이브러리로 이동합니다.

해당 페이지에서의 코드와 아까 제 위치를 찾는 코드를 합치면 되는데, 이번에 처음 구현해보는 거다 보니 코드를 가감을 하는 과정을 못 남겼습니다. 최종 코드를 보여드리겠습니다.

import React, { useEffect } from "react";
import { useLocation } from 'react-router-dom';

const { kakao } = window;

export default function MapPage () {
  const { state } = useLocation();
  
  useEffect(() => {
    const container = document.getElementById("map");
    const options = {
      center: new kakao.maps.LatLng(35.85133, 126.570667),
      level: 5,
    };
    const map = new kakao.maps.Map(container, options);

    const ps = new kakao.maps.services.Places(); 
    
    function displayKeywordMarker(place) {
      const infowindow = new kakao.maps.InfoWindow({zIndex:1});
      const marker = new kakao.maps.Marker({
          map: map,
          position: new kakao.maps.LatLng(place.y, place.x) 
      });
      kakao.maps.event.addListener(marker, 'click', function() {
        infowindow.setContent('<div style="padding:5px;font-size:12px;">' + place.place_name + '</div>');
        infowindow.open(map, marker);
      });
    }
    
    function displayMarker(locPosition, message) {
      const marker = new kakao.maps.Marker({  
          map: map, 
          position: locPosition
      }); 
      const iwContent = message,
          iwRemoveable = true;
  
      const infowindow = new kakao.maps.InfoWindow({
          content : iwContent,
          removable : iwRemoveable
      });
      
      infowindow.open(map, marker);
      map.setCenter(locPosition);      
    }    

    navigator.geolocation.getCurrentPosition(function(position) {
      const lat = position.coords.latitude,
        lon = position.coords.longitude;
      
      const locPosition = new kakao.maps.LatLng(lat, lon), 
        message = '<div style="padding:5px;">Your Location</div>';

      ps.keywordSearch(`${state}`, placesSearchCB, {location: new kakao.maps.LatLng(lat,lon)}); 

      function placesSearchCB (data) {
        const bounds = new kakao.maps.LatLngBounds();

        for (let i=0; i<data.length; i++) {
            displayKeywordMarker(data[i]);    
            bounds.extend(new kakao.maps.LatLng(data[i].y, data[i].x));
        }       
      }
      
      displayMarker(locPosition, message);
    });
    
  }, [state]);

  return (
    <div>
      <div id="map" style={{width:'600px', height:'600px'}}>
      </div>
    </div>
  );
};

container와 options는 지도를 생성하기 위해 사용됩니다.

 

displayKeywordMarker 함수는 키워드로 찾아진 위치를 표시해주는 함수입니다. 키워드로 찾기에서 함수명을 변경해주었습니다.

displayMarker는 사용자의 현재 위치를 나타내는 함수입니다.

 

이 함수들 내부의 infowindow는 위치에 표시되는 상호명과 사용자 위치에 표시되는 텍스트가 담기는 박스입니다.

 

사용자의 위치를 중심으로 검색해야되기 때문에 keywordSearch함수의 옵션을 변경해줍니다. 프로젝트에 맞게 기능들을 수정하려면 Docs에서 해당 함수를 검색해서 수정해주면 됩니다.

사진이 흐릿한데 해당 함수를 검색해보면 keywordSearch는 첫번째 인수를 키워드로 검색을 하며, 두번째 인수는 키워드 검색이 완료되면 호출되는 callback함수이고, 세번째 인수부터 옵션을 넣을 수 있습니다. 사용자의 위치를 중심으로 검색하기 위해 location에 getCurrentPosition에서 lat과 lon을 이용했습니다.

 

질문에 답하고 메뉴를 클릭할 경우 아래와 같은 화면이 출력됩니다.

Your Location을 확인해보면 카카오 지도 API 페이지에서 나오는 제 위치와 동일한 것을 확인할 수 있습니다. 짬뽕 메뉴를 클릭할 경우 제 위치에서 짬뽕 키워드로 검색되는 식당들을 확인할 수 있습니다.

아직 디테일은 부족하지만 기획했던 기능들의 절반은 넘게 구현한 것 같습니다. 지도 기능은 검색된 결과나 거리 등 정보를 옆에 따로 출력을 해줄지는 고민이지만 카카오 지도 API를 이용해서 기능을 수정할 경우 추가적으로 공유하도록 하겠습니다.

 

 

 

추가

카카오 지도 API에서 현재 위치가 정확한게 표시 되지 않는 에러는 노트북의 위치 서비스가 비활성화 되어 있어서 발생한 것을 확인했습니다. 위치 서비스 활성화 후 재조회 하니 정상적으로 출력되는 것을 알 수 있었습니다.

 

Comments