카카오 지도에 여러개의 마커 표시하기

전윤환·2022년 5월 27일
3

들어가며

네이버 maps api를 쓰다가 카카오가 쉽다는 얘기를 들어서 한번 해봄
나같은 쌩초보 생활코딩러는 난이도가 정말 중요하기에...
근데 별 차이는 없는것 같다. 네이버와 카카오간에 차이점이라면, 네이버는 한달 한도가 있다면 카카오는 1일 한도가 있다는 점? (네이버: 1달 3천만, 카카오: 1일 30만)

선행조건

1) 카카오디벨로퍼스 가입, 어플리케이션 등록
2) 몽고db에 데이터 업로드
3) 자바스크립트 왕초보 수준의 이해도
4) 서버 생성

나는 코딩공부를 스파르타코딩클럽의 왕초보 난이도밖에 해본 적이 없다. 전공도 아니고 다른데서 배운 적도 없다. 그 중에서도 '웹개발 종합반'에서 배운 내용이 내 코딩의 전부라고 할 수 있다. 위 선행조건 2), 3), 4)는 그곳에서 배운 내용과, 그때 작성했던 코드를 거의 그대로 복붙한 내용이므로, 이번 글의 내용은 딱 저정도 수준에서 우왕좌왕하는 분들에게 적당한 도움이 될 것이라 생각한다.

1) 카카오디벨로퍼스 가입, 어플리케이션 등록

카카오디벨로퍼스

maps api를 가입 후 플랫폼을 웹, 안드로이드, ios 중에서 웹을 선택한다. 로컬서버에서 돌릴거면 도메인을 localhost, 그게 아니면 아이피와 포트를 입력 후 저장 (예: 123.456.789.012:9999)

2) 몽고db에 데이터 업로드

데이터는 내가 기존에 가지고 있던 엑셀파일을 토대로, 파이썬으로 몽고db에 업로드했다. 이 당시 내가 가진 정보는 1300여개의 주소였고 이걸 전부 지도에 마커로 띄워야했기 때문에, 코드에 주소좌표를 전부 넣느니 몽고db를 활용하는게 좋겠다고 생각함.

나는 로보3t와 아틀라스를 연동해서 사용하고 있다. 아틀라스는 구글 아이디로 회원가입 후 무료 이용이 가능하고, 로보는 아틀라스 웹페이지보다 시인성이 좋다고 판단했기 때문이다.

*아틀라스와 로보를 연동하는 방법은 구글에 쌔고 쌨으니 생략합니다.

당시 보유하고 있던 주소지 엑셀파일의 컬럼명

위 엑셀파일을 db에 업로드할때 쓴 코드

import pandas as pd

# 아래 3줄은 아트라스 mongoDB 사용시 설정
from pymongo import MongoClient
client = MongoClient('mongodb+srv://아틀라스아이디_:아틀라스비번@cluster0.9ws0c.mongodb.net/?retryWrites=true&w=majority')
db = client.만들db이름
mycoll = db.만들컬렉션이름
df = pd.read_excel(f'D:\\불러올엑셀파일이름.xlsx')
# print(df) # 잘 불러와지나 확인

for i in range(len(df)):
  m_name = df.iloc[i]['매장명']
  m_addr = df.iloc[i]['전체주소']
  m_x = df.iloc[i]['x좌표']
  m_y = df.iloc[i]['y좌표']
  m_g = df.iloc[i]['권역']
  m_n = df.iloc[i]['노선코드'][0:4]
  m_gj = df.iloc[i]['거점']
  m_gr = (df.iloc[i]['그룹'])
  res = {'매장명': m_name, '매장주소': m_addr, 'x좌표': m_x, 'y좌표': m_y,'그룹': m_gr, '거점': int(m_gj), '권역': m_g, '노선코드': m_n}
  # print(res) # 원하는 형태로 잘 됐나 확인
  mycoll.insert_one(res)

암튼 이런 식으로 db를 만들었고, 이제 웹페이지에서 db의 x,y좌표를 따서 마커를 표시하면 된다!

3)자바스크립트 왕초보 수준의 이해도

카카오지도 web api 가이드

html파일을 생성하고, 위 사이트에 예제코드를 몇개만 넣으면 지도는 기본적으로 완성이 된다. (아이디 넣는 부분만 잘 수정하면)
그러므로 바로 마커를 만들어야 하는데...

카카오지도 web api 가이드 (마커 생성하기)

이런게 있네. 근데 나는 1300개를 띄워야 되니까

카카오지도 web api 가이드 (마커 여러개 표시하기)

이걸로 간다.

그리고 마커를 눌렀을 때 주소도 같이 나왔으면 좋겠어서

인포윈도우 생성하기

이것도 같이 추가해줬다.

그래서 내가 만든 파일은 총 3개. html파일 1개와 js파일 2개.

html파일
<!DOCTYPE html>

<head>
    <meta charset="utf-8" />
    <!-- JQuery를 import 합니다 -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <title>
        다음지도
    </title>
    <style>
        .ifw {
            height: auto;
            width: auto;
            padding: 5px;
            margin-top: -15px;
        }

        .area {
            position: absolute;
            background: #fff;
            border: 1px solid #888;
            border-radius: 3px;
            font-size: 12px;
            top: -5px;
            left: 15px;
            padding: 2px;
        }

        .info {
            font-size: 12px;
            padding: 5px;
        }

        .info .title {
            font-weight: bold;
        }

        #btns {
            padding: auto;
            margin: auto;
            align-items: auto;
        }
        #iw_con_info {
            width:auto; height:auto; margin-top: -13px; padding: auto; border: auto;
        }
    </style>
</head>

<body>

    <div id="map" style="width:100%;height:1040px;"></div>

    <script type="text/javascript"
        src="//dapi.kakao.com/v2/maps/sdk.js?appkey=애플리캐이션 키 입력"></script>


    <script src="../static/kakaoscript0.js"></script>
    <script src="../static/kakaoscriptAll.js"></script>

</body>

</html>
js파일 첫번째. 카카오맵 기본 설정
// 기본 지도 설정
var container = document.getElementById('map'); //지도를 담을 영역의 DOM 레퍼런스
var options = { //지도를 생성할 때 필요한 기본 옵션
    center: new kakao.maps.LatLng(지도의 첫 화면에 놓일 중심 좌표 지정), //지도의 중심좌표.
    level: 12 //지도의 레벨(확대, 축소 정도)
};

var map = new kakao.maps.Map(container, options),
    customOverlay = new kakao.maps.CustomOverlay({}),
    infowindow = new kakao.maps.InfoWindow({ removable: true });; //지도 생성 및 객체 리턴
// 이 위까지가 기본설정 끝
js파일 두번째. 서버를 통해 db에서 데이터를 가져오고 마커를 뿌림

// 아래는 서버한테 데이터 수신
getdatas = []
m_infos = []
positions = []

$.ajax({
    type: 'get',
    url: "/data",
    success: function (response) {
        getdatas = response['result']
        for (i = 0; i < getdatas.length; i++) {
            let m_g = getdatas[i]['매장명']
            let m_a = getdatas[i]['매장주소']
            let m_x = getdatas[i]['x좌표']
            let m_y = getdatas[i]['y좌표']
            let m_w = getdatas[i]['권역']
            let m_gj = getdatas[i]['거점']
            let m_gr = getdatas[i]['그룹']
            let m_gc = getdatas[i]['간선코드']

            let m_info = { '매장명': m_g, '매장주소': m_a, 'x좌표': m_x, 'y좌표': m_y, '권역': m_w, '거점': m_gj }
            m_infos.push(m_info)
        }

        //  아래는 마커와 인포윈도우 여러개 표시
        for (var i = 0; i < m_infos.length; i++) {
            var m_i_name = m_infos[i]['매장명']
            var m_i_x = m_infos[i]['x좌표']
            var m_i_y = m_infos[i]['y좌표']
            var m_i_addr = m_infos[i]['매장주소']
            var m_i_gw = m_infos[i]['권역']
            var m_i_gj = m_infos[i]['거점']
            var gb_position = { content: `<div class="ifw"><h5>${m_i_name}</h5><h6>${m_i_addr}</h6><h5> ${m_i_gw}</h5>`, latlng: new kakao.maps.LatLng(m_i_y, m_i_x) }
            positions.push(gb_position)
        }


        for (var i = 0; i < positions.length; i++) {
            var m_i_addr2 = m_infos[i]['매장주소']
            var m_i_name2 = m_infos[i]['매장명']
            var m_i_gw2 = m_infos[i]['권역']
            var m_i_gj2 = m_infos[i]['거점']
            var marker = new kakao.maps.Marker({
                map: map,
                position: positions[i].latlng,
                clickable: true
            })
            var iwContent = `<div id="iw_con_info"><h5>${m_i_name2}</h5><h5>${m_i_addr2}</h5><h5>권역: ${m_i_gw2}</h5><h5>거점: ${m_i_gj2}</h5></div>`, // 인포윈도우에 표출될 내용으로 HTML 문자열이나 document element가 가능합니다
                iwRemoveable = true; // removeable 속성을 ture 로 설정하면 인포윈도우를 닫을 수 있는 x버튼이 표시됩니다

            var infowindow = new kakao.maps.InfoWindow({
                content: iwContent,
                removable: iwRemoveable
            });

            kakao.maps.event.addListener(marker, 'click', makeOverListener(map, marker, infowindow));

        }
    }
})

// 인포윈도우를 표시하는 클로저를 만드는 함수
function makeOverListener(map, marker, infowindow) {
    return function () {
        infowindow.open(map, marker);
    };
}
// 인포윈도우를 닫는 클로저를 만드는 함수
function makeOutListener(infowindow) {
    return function () {
        infowindow.close();
    };
}

결과물

끝내며

마커를 웹페이지에 올리는 데에 성공했지만, 난 솔직히 이게 어떻게 작동하는지 모르겠다. ㅎㅎㅎㅎ;;;
마커와 인포윈도우를 배열로 관리하라고 하던데, 자바스크립트에서 배열은 파이썬의 리스트와 같은 대괄호 형태인데... 거기서 map, new를 통해 마커를 쫙쫙 뿌려주는건가?

다음번엔 웹페이지에 버튼을 만들어서 구역별로 마커가 따로 출력되는 코드를 짜봐야지

profile
코딩 연습장. 발전하고 싶습니다. 모든 방향에서의 비판 부탁드립니다.

0개의 댓글