[django] 카카오맵 api를 이용해 지도에 마크 + 오버레이

김우경·2020년 12월 7일
1

본인은 js 알못이고,, 일단 기능 완성하는게 중요한 제출 기간이 얼마 안남은 프로젝트를 위해 오픈소스+카카오맵 가이드+구글링의 결과물인 소스입니다. 절대 정답이 아님을 밝힙니다 ^.ㅠ

어제 api 연결에 이어 json으로 받은 좌표를 지도 위에 핀찍고, 클릭 시 해당 장소의 상세정보를 보여주는 오버레이 띄우기까지 해봅시다.

사실 되게와 되는거 타협의 현장...

Reference

울산 코로나맵
카카오 맵 api 가이드
문돌이가 이해한 인공지능 이야기님 블로그

하고자 하는것

  • Json으로 받은 관광지 정보 공공데이터를 파싱해서 html에 넘겨주기
  • 해당 관광지의 위도, 경도를 지도 위에 마크
  • 마크 클릭시 모달창으로 해당 위치의 상세정보 알려주기

1. Json 데이터의 파싱

데이터 분석을 맡은 팀원에게 json형식의 파일을 받았다.

{"response":{"header":{"resultCode":"0000","resultMsg":"OK"},
             "body":
             {"items":
              {"item":
               [{"addr1":"전라남도 완도군 청산면 당락리",
                 "addr2":656,
                 "areacode":38,
                 "cat1":"A02",
                 "cat2":"A0203",
                 "cat3":"A02030400",
                 "contentid":2518765,
                 "contenttypeid":12,
                 "createdtime":20171130000022,
                 "firstimage":"http:\/\/tong.visitkorea.or.kr\/cms\/resource\/23\/2026123_image2_1.jpg",
                 "firstimage2":"http:\/\/tong.visitkorea.or.kr\/cms\/resource\/23\/2026123_image3_1.jpg",
                 "mapx":"126.8621585545",
                 "mapy":"34.1718000440",
                 "modifiedtime":20180720143515,
                 "readcount":320,
                 "sigungucode":18,
                 "tel":"061-550-6495",
                 "title":"‘서편제’ 촬영지"}
                .......

일단 문제점

  • json객체인 관광지마다 가지는 데이터가 다르다. 즉, 좌표가 있는 데이터가 있고 없는 데이터가 있고, 전화번호가 있는 데이터가 있고 없는 데이터가 있고,, 제각각이다.

지도에 마크하기 위해서 필수적으로 필요한 정보를 위도, 경도, 관광지명 정도로 두고 세 값이 모두 있는 관광지에 대해서는 일단 전부 마크하기로 했다.

필요한 데이터만 다시 json 형식으로 넘기기


처음에는 전체 json 파일을 통째로 넘겼더니 앞단에서 불러올때 너어무 오래 걸려서 필요한 데이터만 뽑았다.

python에서 json파일 읽기

TWpower's Tech Blog를 참고했습니다.
with문과 json 모듈을 이용해서 파싱한다.

import json

def showattractions(request):
    #with와 json 모듈을 이용해 Json파일 불러오기
    with open('static/json/attractions.json', encoding='utf-8') as json_file:
        attractions = json.load(json_file)['response']['body']['items']['item']

필요한 데이터만 뽑아서 html에 렌더링

그럼 이제 이렇게 관광지 객체들만 쫙 뽑혀서 attractions에 저장된다.
이 중에서도 필요한 데이터(x좌표, y좌표, 관광지명, 전화번호 등)만 뽑아서 json 형식으로 javascript 코드가 있는 map.html 에 렌더링한다.

attractiondict = []
    #불러온 json 객체들 중 필요한 데이터만 뽑기
    for attraction in attractions:
        if attraction.get('mapx'):
            content = {
                "title": attraction['title'],
                "mapx": str(attraction['mapx']),
                "mapy": str(attraction['mapy']),
                "addr1": str(attraction['addr1']),
            }
            if attraction.get('tel'):
                content['tel'] = str(attraction['tel'])
            else:
                content['tel'] = ''
            attractiondict.append(content)
    attractionJson = json.dumps(attractiondict, ensure_ascii=False)

view.py 전체 코드

def showattractions(request):
    with open('static/json/attractions.json', encoding='utf-8') as json_file:
        attractions = json.load(json_file)['response']['body']['items']['item']

    attractiondict = []
    for attraction in attractions:
        if attraction.get('mapx'):
            content = {
                "title": attraction['title'],
                "mapx": str(attraction['mapx']),
                "mapy": str(attraction['mapy']),
                "addr1": str(attraction['addr1']),
            }
            if attraction.get('tel'):
                content['tel'] = str(attraction['tel'])
            else:
                content['tel'] = ''
            attractiondict.append(content)
    attractionJson = json.dumps(attractiondict, ensure_ascii=False)
    return render(request, 'map/map.html', {'attractionJson': attractionJson})

2. json으로 받은 좌표를 지도에 마크하기

여러개 마커 표시하기를 참고했습니다.

지도의 생성

<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은 api키"></script>
<script>
       var mapContainer = document.getElementById('map'), // 지도를 표시할 div
           mapOption = {
               center: new kakao.maps.LatLng(38.0368457410, 128.5594244943), // 지도의 중심좌표
               level: 3 // 지도의 확대 레벨
            };

       var map = new kakao.maps.Map(mapContainer, mapOption); // 지도를 생성합니다
</script>

map.html에서 json 파싱

문돌이가 이해한 인공지능 이야기를 참고했습니다.
{{ attractionJson|escapejs }}를 이용해서 파싱하면 된다고 한다. escapejs가 뭐냐면 장고 공식 문서에 나와있다. escapejs말고도 secret 등 여러 옵션이 있는데 처음에 유니코드가 그대로 나와서 이거저거 해보다가 결국 escapejs로 성공해서 일단 이걸로 한다,, 나중에 자세히 찾아보기

var attractions = JSON.parse("{{ attractionJson|escapejs }}");
console.log(attractions)

이렇게 파싱을 하면 크롬 콘솔창에서 제대로 데이터를 받아왔음을 알 수 있다.

마커 표시하기

이제 이 각각의 attraction의 데이터를 kakaomap에 찍기 위해 마커를 표시할 위치와 title 객체 배열에 담는다.

var positions = [];
for (var i = 0; i < Object.keys(attractions).length; i++) {
  var content = {
    title: attractions[i].title,
    latlng: new kakao.maps.LatLng(attractions[i].mapy, attractions[i].mapx),
    addr1: attractions[i].addr1,
    detail: "디테일입니다 추후 추가예정",
    tel: attractions[i].tel,
  }
  positions.push(content);
};
console.log(positions);

뭔가 똑같은거 두번 한 느낌인데

이제 이 배열에 담긴 모든 관광지에 대해 마크를 찍는다.

// 마커 이미지의 이미지 주소입니다
var imageSrc = "https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/markerStar.png";
for (var i = 0; i < positions.length; i++) {
  // 마커 이미지의 이미지 크기 입니다
  var imageSize = new kakao.maps.Size(24, 35);
  // 마커 이미지를 생성합니다
  var markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize);
  // 마커를 생성합니다
  var marker = new kakao.maps.Marker({
    map: map, // 마커를 표시할 지도
    position: positions[i].latlng, // 마커를 표시할 위치
    title: positions[i].title, // 마커의 타이틀, 마커에 마우스를 올리면 타이틀이 표시됩니다
    image: markerImage // 마커 이미지
  });

그럼 이제 이렇게 마크가 찍힌 것을 볼 수 있다.

3. 마크 클릭 시 상세정보 오버레이

닫기가 가능한 커스텀 오버레이를 참고했습니다.
이제 마크한 관광지를 클릭했을때 관광지 이름, 주소, 번호 등 상세 정보를 알려주는 오버레이를 띄운다. 이거 하면서 눈물 많이 흘림 ^.ㅜ

(function(marker, place) {
  // 마크 클릭 시
  kakao.maps.event.addListener(marker, 'click', function() {
    var overlay = new kakao.maps.CustomOverlay({
      // 오버레이에 띄울 내용
      content: '<div class="wrap">' +
            '    <div class="info">' +
            '        <div class="title">' +
            place.title +
            '        </div>' +
            '        <div class="body">' +
            '            <div class="desc">' +
            '                <div class="ellipsis">' + place.addr1 + '</div>' +
            '		       <div class="jibun ellipsis">' + place.tel + '</div>' +
            '            </div>' +
            '        </div>' +
            '    </div>' +
            '</div>',
      map: map,
      position: marker.getPosition()
    });
    // 아무데나 클릭하게되면 overlay를 끄기
    kakao.maps.event.addListener(map, 'click', function(mouseEvent) {
      overlay.setMap(null)
    })
    console.log(overlay);
    overlay.setMap(map);
  })
})(marker, positions[i])

그럼 이제 이렇게 마크를 클릭했을때 오버레이가 생긴다.

마커 이외의 지도의 다른 부분을 클릭하면 오버레이가 사라진다.

돌아 돌아 돌아 돌아온 이 느낌,,,,,,,,,,,,,,,,,,

profile
Hongik CE

4개의 댓글

comment-user-thumbnail
2021년 8월 22일

잘 읽었습니다:)

답글 달기
comment-user-thumbnail
2023년 9월 23일

저 그 혹시 html 에 관한 코드들은 그냥 처음부터 다 복사 시키면 되나요?

답글 달기
comment-user-thumbnail
2023년 11월 22일

Our Call Girl in Aerocity does a lot to keep the customers happy and to make them happy in all possible manners. If you're not happy with your partner just because she isn't able to gratify your biological needs so here is the solution.

답글 달기
comment-user-thumbnail
2023년 12월 11일

You can find out the most effective India Call Girls Service, who will serve your objective with perfection. No matter what is your purpose of hiring, they are devoted to assist you in your opportunity so let them serve you and please you with their expertise and arts.Look for for the Independent India Escorts could be ended at our website, which is a well known India escort service agency.
Connaught Place Escorts
Escorts in CR Park
Dabri Escorts Service
Dakshinpuri Call Girls
Call Girls in Dareeba

답글 달기