[Django] 공공API 지도에 맵핑하기

Cherry·2022년 6월 23일
0

팀장님이 급하게 부탁하셔서 만든 프로젝트이다. 아래에 있는 공공 api에서 데이터들을 받아와서 그 데이터들을 지도에 뿌려주고 맵핑시켜주면 된다. 다하면 너무 넓으니까 우선 용인시만 진행했다.

공공 API

  1. 위의 API를 요청해서 받아보기
  2. 받은 API를 Django를 통해 지도에 띄워보기

네이버 지도 API

우선은 네이버에서 지도 api를 받아와 진행하기로 했다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
    <title>mapAPI</title>
    <script type="text/javascript" src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=[클라이언트ID]"></script>
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
</head>
<body>
<div id="map" style="width:100%;height:700px;"></div>

<script>
var mapOptions = {
    center: new naver.maps.LatLng(37.3595704, 127.105399),
    zoom: 7
};

var map = new naver.maps.Map('map', mapOptions);

</script>
</body>
</html>

지도가 아주 잘 띄워진다.

공공 API 데이터 불러오기

토지정보 API

2D 데이터 API 2.0 레퍼런스-토지이용계획도으로 접속해서 자세한 요청 파라미터를 보면 엄청나게 많을 텐데 이중에서 attrFilter만 사용해서 요청을 보낼 것이다.


용인시에 있는 토지정보만을 불러올것이기 때문에 먼저 용인시에 있는 읍면동의 코드들을 따로 추출해 주어야 한다. 읍면동 코드를 요청하는 url이 존재하기 때문에 따로 요청해서 배열에 모아주는 함수를 만들었다.

def YongIn_regionName():
    url = "https://api.vworld.kr/req/data?key=인증키&domain=도메인&service=data&version=2.0&request=getfeature&format=json&size=100&page=1&data=LT_C_ADEMD_INFO&geometry=true&attribute=true&attrfilter=emd_cd:like:"
    yongin_emdcd = []

    for gu in ["41463", "41465", "41461"]:
        requestData = requests.get(url + gu)
        jsonData = None

        if requestData.status_code == 200:
            # print(requestData.status_code, "Request OK - ", gu)

            jsonData = requestData.json()

            features = jsonData.get('response').get('result').get('featureCollection').get('features')

            for f in features:

                yongin_emdcd.append(f.get('properties').get('emd_cd'))

    return yongin_emdcd

그 다음에 이제 위 용인시의 읍면동 코드들을 통해 토지정보를 가지고 올 것이다. url뒤에 용인시에 있는 읍면동에 해당하는 코드들을 넣어주고 넘어온 데이터들을 배열에 같이 넣어준다.

def land_API(request):
    featureCollection = {"type": "FeatureCollection",
                         "bbox": [127.00212289179542, 37.09498614424044, 127.45205299927372, 37.38706567868086],
                         "features": []}
    yongin_emdcd = YongIn_regionName()
    for i in yongin_emdcd:
        url = 'http://api.vworld.kr/req/data?service=data&request=GetFeature&key=인증키&domain=도메인&data=LT_C_LHBLPN&attrFilter=emdCd:=:'
        url += str(i)
        try:
            requestData = requests.get(url)
            jsonData = None
            if requestData.status_code == 200:
                jsonData = requestData.json()
                features = jsonData.get('response').get('result').get('featureCollection').get("features")
                for f in features:
                    featureCollection.get("features").append(f)
                print(requestData.status_code, "Request OK")
        except:
            pass
    f = open("./map/templates/landData.json", 'w', encoding='utf-8')
    f.write(str(featureCollection).replace('\'', '"'))
    f.close()

    return redirect('land')

아주 자아알 나온다. 해당 구역 위에 마우스를 올려주면 해당 토지의 정보들이 같이 나온다.

도로정보 API

도로정보도 토지정보와 비슷하다. 용인시 읍면동 코드를 url 뒤에 붙인다음에 도로데이터들을 불러와서 geojson파일을 생성해준다.

def road_API(request):
    url = "http://api.vworld.kr/req/data?service=data&request=GetFeature&data=LT_C_UPISUQ151&key=인증키&domain=도메인&attrFilter=emdCd:=:"
    yongin_emdcd = YongIn_regionName()
    featureCollection = {"type": "FeatureCollection", "bbox": [127.00212289179542, 37.09498614424044, 127.45205299927372, 37.38706567868086], "features": []}

    for emdcd in yongin_emdcd:
        requestData = requests.get(url + emdcd)
        jsonData = None
        
        if requestData.status_code == 200:
            jsonData = requestData.json()
            # print(requestData.status_code, "Request OK")
            features = jsonData.get('response').get('result').get('featureCollection').get("features")
            for f in features:
                featureCollection.get("features").append(f)

    f = open("./map/templates/roadData.json", 'w', encoding='utf-8')
    f.write(str(featureCollection).replace('\'', '"'))
    f.close()
    
    return redirect('road')

실행해보면 지도에 잘 표시되어 있는 것을 볼 수 있다. 도로정보도 마우스를 올리면 잘 보인다.

지도 위에 맵핑하기

이제 도로정보하고 토지정보를 합친 지도를 만들것 인데 그냥 위에 두개의 지도를 합친다고 보면 된다. 코드는 아래와 같다.

//geojson이 있는 파일을 불러온다.
naver.maps.Event.once(map, 'init', function () {
    $.ajax({
        url: '/data',
        dataType: 'json',
        success: startDataLayer
    });
});

var tooltip = $('<div style="position:absolute;z-index:1000;padding:5px 10px;background-color:#fff;border:solid 2px #000;font-size:14px;pointer-events:none;display:none;white-space:pre-line;"></div>');

tooltip.appendTo(map.getPanes().floatPane);

function startDataLayer(geojson) {
    // geojson info load
    map.data.addGeoJson(geojson);

    // map data layer style
    map.data.setStyle(function(feature) {
        if (typeof feature.property_blocktype == "undefined"){
            var styleOptions = {
            fillColor: '#ff0000',
            fillOpacity: 0.0001,
            strokeColor: '#ff0000',
            strokeWeight: 2,
            strokeOpacity: 0.4
            };
        }
        else {
            var styleOptions = {
                fillColor: '#0000ff',
                fillOpacity: 0.0001,
                strokeColor: '#0000ff',
                strokeWeight: 2,
                strokeOpacity: 0.4
            };
        }

        return styleOptions;
    });

    // show info box while mouseover
    map.data.addListener('mouseover', function(e) {
        var feature = e.feature
		//도로정보/토지정보에 따라 다르게 정보가 나타난다.  
        if (typeof feature.property_blocktype == "undefined"){
            var info = "PRESENT_SN : " + feature.property_present_sn + "\n"
                    + "도형 대분류코드 : " + feature.property_lclas_cl + "\n"
                    + "도형 중분류코드 : " + feature.property_mlsfc_cl + "\n"
                    + "도형 소분류코드 : " + feature.property_sclas_cl + "\n"
                    + "도형 속성코드 : " + feature.property_atrb_se + "\n"
                    + "조서관리 코드 : " + feature.property_wtnnc_sn + "\n"
                    + "결정고시관리코드 : " + feature.property_ntfc_sn + "\n"
                    + "라벨명 : " + feature.property_dgm_nm + "\n"
                    + "면적(도형) : " + feature.property_dgm_ar + "\n"
                    + "길이(도형) : " + feature.property_dgm_lt + "\n"
                    + "지자체관리코드 : " + feature.property_signgu_se + "\n"
                    + "규모_등급 : " + feature.property_grad_se + "\n"
                    + "규모_류별 : " + feature.property_road_ty + "\n"
                    + "규모_번호 : " + feature.property_road_no + "\n"
                    + "도로기능 : " + feature.property_road_role + "\n"
                    + "집행상태코드 : " + feature.property_excut_se + "\n"
                    + "시군구명 : " + feature.property_sig_nam + "\n"
                    + "도형대분류명 : " + feature.property_lcl_nam + "\n"
                    + "도형중분류명 : " + feature.property_mls_nam + "\n"
                    + "도형소분류명 : " + feature.property_scl_nam + "\n"
                    + "도형속성명 : " + feature.property_atr_nam + "\n"
                    + "도로기능명 : " + feature.property_pmi_nam + "\n"
                    + "집행상태명 : " + feature.property_exc_nam + "\n"
        }
        else {
            var info = "계획구역명: "+feature.property_blocktype + "\n"
                    + "사업지구경계도: " + feature.property_zonename + "\n"
        }
        tooltip.css({
            display: '',
            left: e.offset.x,
            top: e.offset.y
        }).text(info);

        map.data.overrideStyle(feature, {
            fillOpacity: 0.6,
            strokeWeight: 4,
            strokeOpacity: 1
        });
    });

    // remove info box while mouseout
    map.data.addListener('mouseout', function(e) {
        tooltip.hide().empty();
        map.data.revertStyle();
    });
}

토지를 파란색 도로를 빨간색으로 표시했다.

위에 마우스를 올리면 해당 도로인지 토지인지에 따라 필요한 정보들이 같이 나온다.

0개의 댓글