본문 바로가기

문돌이 존버/Django 스터디

Django 데이터 변수를 javascript에 넘기기 feat. 카카오맵 API

반응형

카카오맵 API를 연동하여 지도 위에 DB에 있는 위경도 데이터를 표시해야 할 필요가 있었습니다. 즉, 탑승객이 디바이스에 의해 인식되면 어느 지하철역에서 인식되었는지를 나타내는 것입니다. 이로써 위험 증상이 있는 사람이 다녀간 지하철역의 위치를 바로 확인할 수 있겠죠. (제가 참여한 프로젝트의 데이터에 대해 이해하고 싶다면 여기를 참고해주시기 바랍니다.)

아래는 views.py 에 추가한 지도 관련 함수입니다. 우선, javascript에 DB의 데이터 변수를 보내려면 json 포맷을 사용해야 하기 때문에 파이썬의 내장 json 모듈을 불러와야 합니다. 이후 dictionary 형태를 만들어줘서 json.dumps() 을 통해 json 포맷으로 변환합니다. (참고로 json.dumps()는 메모리 상에 json 포맷 데이터를 만들어놓고 파이썬에서 계속 작업을 하는 것이고, json.dump()의 경우, 디스크에 파일을 저장하는 것입니다. 자세한 사항은 해당 블로그를 방문해주세요.)

json 포맷으로 바뀐 데이터를 javascript 코드가 있는 map.html 에 렌더링 해줍니다. 

import json

@csrf_exempt
def showmap(request, tbl_person_info_id):
    person = TBL_PERSON_INFO.objects.get(id=tbl_person_info_id)
    persondict = {
        'lat': person.deviceid.latitude,
        'lon': person.deviceid.longitude,
        'station': person.deviceid.station
    }
    personJson = json.dumps(persondict)
    return render(request, 'map.html', {'personJson': personJson})

이제 map.html 을 살펴볼 차례입니다. 해당 파일은 카카오맵 API에 소개된 이미지 마커와 커스텀 오버레이 샘플을 그대로 사용했습니다. 

json 포맷의 데이터는 JSON.parse("{{ 변수명|escapejs }}") 를 통해 받아오면 됩니다. escapejs에 관한 설명은 장고 공식 문서를 참고하면 됩니다만... 간단히 설명하자면 탬플릿(template)을 사용하여 javascript/JSON 코드를 작성할 때에 해당되는 것이고, javascript에 맞춰 views.py 에서 넘긴 데이터에 대해 구문 오류(syntax errors)를 방지해주는 역할을 합니다. 

{% extends 'base.html' %}
{% load static %}
{% block content %}

<head>
    <meta charset="utf-8">
    <title>고온자 발생 지하철역</title>
    <style>
.customoverlay {position:relative;bottom:85px;border-radius:6px;border: 1px solid #ccc;border-bottom:2px solid #ddd;float:left;}
.customoverlay:nth-of-type(n) {border:0; box-shadow:0px 1px 2px #888;}
.customoverlay a {display:block;text-decoration:none;color:#000;text-align:center;border-radius:6px;font-size:14px;font-weight:bold;overflow:hidden;background: #d95050;background: #d95050 url(https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/arrow_white.png) no-repeat right 14px center;}
.customoverlay .title {display:block;text-align:center;background:#fff;margin-right:35px;padding:10px 15px;font-size:14px;font-weight:bold;}
.customoverlay:after {content:'';position:absolute;margin-left:-12px;left:50%;bottom:-12px;width:22px;height:12px;background:url('https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/vertex_white.png')}
</style>
</head>
<body>
<div id="map" style="width:100%;height:650px;"></div>
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=915ab51c3ca143c1bedbc92943dc01ae&libraries=services"></script>

<script>
// json 형식으로 가져오기 = dictionary 형태
var person = JSON.parse("{{ personJson|escapejs }}");

var mapContainer = document.getElementById('map'), // 지도를 표시할 div 
  mapOption = { 
        center: new kakao.maps.LatLng(person['lat'], person['lon']), // 지도의 중심좌표
        level: 4 // 지도의 확대 레벨
    };

var map = new kakao.maps.Map(mapContainer, mapOption);

// 로컬에서 이미지를 가져와 객체를 생성
var imageSrc = '/marker.png', // 마커이미지의 주소입니다    
    imageSize = new kakao.maps.Size(55, 55), // 마커이미지의 크기입니다
    imageOption = {offset: new kakao.maps.Point(27, 69)}; // 마커이미지의 옵션입니다. 마커의 좌표와 일치시킬 이미지 안에서의 좌표를 설정합니다.

// 마커의 이미지정보를 가지고 있는 마커이미지를 생성합니다
var markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imageOption),
    markerPosition = new kakao.maps.LatLng(person['lat'], person['lon']); // 마커가 표시될 위치입니다

// 마커를 생성합니다
var marker = new kakao.maps.Marker({
  position: markerPosition,
  image: markerImage // 마커이미지 설정 
});

// 마커가 지도 위에 표시되도록 설정합니다
marker.setMap(map);  

// 커스텀 오버레이에 표출될 내용으로 HTML 문자열이나 document element가 가능합니다
var content = '<div class="customoverlay">' +
    '  <a href="https://map.kakao.com/?q=' + person['station'] + '" target="_blank">' +
    '    <span class="title">' + person['station'] + '</span>' +
    '  </a>' +
    '</div>';

// 커스텀 오버레이가 표시될 위치입니다 
var position = new kakao.maps.LatLng(person['lat'], person['lon']);  

// 커스텀 오버레이를 생성합니다
var customOverlay = new kakao.maps.CustomOverlay({
    map: map,
    position: position,
    content: content,
    yAnchor: 1 
});
</script>
</body>

{% endblock %}

원래 샘플 코드에서 제가 조금 수정한 부분은 마커이미지와 커스텀 오버레이에 표출될 내용입니다. 마커이미지는 제가 따로 만든 것이라 로컬 파일에서 가져오는 방식으로 진행했고, 관련 부분 역시 카카오맵 API 공식 문서를 참고했습니다. 커스텀 오버레이는 지하철 역명을 그때그때마다 입력해줘야 하기 때문에 map.kakao.com/ 뒤에 바로 "?q="을 추가했습니다. 제목(title) 역시 마찬가지로 똑같이 설정해줬습니다. 

728x90
반응형