OpenAPI/C# OpenAPI

3. 지역 검색 및 위치 확인 [경로찾기 프로젝트 – C#, 카카오 지도 API, SK TMAP API 활용 ]

언휴 2024. 1. 9. 08:39

안녕하세요. 언제나휴일입니다.

1. 유튜브 동영상 강의

2. 프로젝트 소개 및 요구 기술

이번에는 지역 검색 및 위치 확인 앱 개발입니다.

지역 검색한 후에 검색 결과를 선택하면 지도에 Center를 이동시키고 마커를 보여주는 프로그램입니다.

지역 검색 및 위치 확인
지역 검색 및 위치 확인

이 프로젝트는 C#, Windows Form(.NET Framework) 앱으로 개발합니다.

지역 검색은 카카오 개발자 센터 로컬 REST API를 사용합니다.

지도는 카카오 개발자 센터의 지도 API를 사용합니다.

지도는 웹 에 게시해야 하는데 여기에서는 IIS에 게시하는 것으로 할게요.

3. 컨트롤 배치

먼저 C#, Windows Forms 앱(.NET Framework) 프로젝트를 생성합니다.

Form1.cs를 MainForm.cs 로 파일명을 변경할게요.(무시해도 무관합니다.)

아래 그림처럼 컨트롤을 배치하세요.

컨트롤 배치
컨트롤 배치

컨트롤 이름과 속성은 다음처럼 지정하세요.

1번 TextBox 이름은 tbox_query

2번 Button 이름은 btn_search

3번 ListBox 이름은 lbox_locale

4번 WebBrowser 이름은 wb로 설정합니다.

4. 지역 검색

지역 검색은 앞에서 작성한 지역 검색 예광탄을 참고합니다.

먼저 btn_search의 클릭 이벤트 핸들러를 추가하세요.

그리고 지역 정보를 Locale 클래스로 표현할게요.

Locale 클래스를 추가한 후에 다음처럼 지역 명, 위도, 경도를 멤버로 갖게 정의하세요.

차후에 라이브러리로 작성할 수도 있는 부분이라 internal 액세스 지정 대신 public으로 지정했습니다.

현재 프로젝트에서는 internal로 지정하는 것이 더 어울릴 수 있으나 미래를 위해 public으로 할게요.

namespace 지역_검색_및_위치_확인
{
    public class Locale
    {
        public string Pname;
        public double Lng { get; }
        public double Lat { get; }
        public Locale(string pname, double lng, double lat)
        {
            Pname = pname;
            Lng = lng;
            Lat = lat;
        }
        public override string ToString()
        {
            return Pname;
        }
    }
}

btn_search의 클릭 이벤트 핸들러에서는 이전 지역 검색 예광탄의 코드를 복붙합니다.

그리고 지역 정보를 Locale 개체로 생성하여 lbox_locale에 추가하게 수정합니다.

지도 부분을 웹 게시한 후에 마커 추가 및 시각화 하는 부분을 추가로 구현할 것입니다.

현재까지 코드는 다음과 같습니다.

*여기에 사용한 카카오 개발자 센터의 REST API 키는 이미 삭제한 것이므로 사용할 수 없습니다.

여러분의 REST API키를사용 하세요. *

        private void btn_search_Click(object sender, EventArgs e)
        {
            string query = tbox_query.Text;
            string url = "https://dapi.kakao.com/v2/local/search/keyword.json";
            string query_str = string.Format("{0}?query={1}", url, query);
            WebRequest request = WebRequest.Create(query_str);
            request.Headers.Add("Authorization", "KakaoAK 569a69082cd0c209180eb69aaaa48f1b");
            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader sr = new StreamReader(stream);
            string content = sr.ReadToEnd();

            JavaScriptSerializer jss = new JavaScriptSerializer();
            dynamic d = jss.Deserialize(content);
            dynamic[] ddoc = d["documents"];
            Locale locale;
            HtmlDocument hdoc = webbr.Document;
            object[] objs = new object[2];
            foreach (dynamic elem in ddoc)
            {
                string pname = elem["place_name"];
                double lng = double.Parse(elem["x"]);
                double lat = double.Parse(elem["y"]);
                locale = new Locale(pname, lng, lat);
                lbox_locale.Items.Add(locale);
                //지도에 중심 이동시키기
                //지도에 마커 추가
            }
            //지도에 마커 시각화

        }

실행해서 잘 동작하는 지 확인하세요.

지역 검색
지역 검색

5. 지도 html 및 웹 게시

지도는 카카오 개발자 센터의 지도 API를 사용할 것입니다.

카카오 개발자 센터>>지도>>웹>>Sample을 클릭하면 다양한 샘플 HTML 코드를 확인할 수 있습니다.

카카오 개발자 센터 지도 API
카카오 개발자 센터 지도 API

지도 생성하기 부분에 있는 HTML+JavaScript 코드를 복사하여 메모장에 붙여넣기 합니다.

제공하는 코드는 다음과 같습니다.

“발급받은 APP Key를 사용하세요.” 부분은 내 애플리케이션의 JavaScript 키를 사용합니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>지도 생성하기</title>
    
</head>
<body>
<!-- 지도를 표시할 div 입니다 -->
<div id="map" style="width:100%;height:350px;"></div>

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

// 지도를 표시할 div와  지도 옵션으로  지도를 생성합니다
var map = new kakao.maps.Map(mapContainer, mapOption); 
</script>
</body>
</html>

파일 명을 KakaoMap.html로 저장한 후에 가상 디렉토리로 옮기세요.

그리고 브라우저에서 http://localhost/KakaoMap.html을 입력할 때 지도가 보이면 성공한 것입니다.

브라우저에서 지도 확인하기
브라우저에서 지도 확인하기

중심 이동시키기에서 setCenter 함수를 복사하여 KakaoMap.html에 붙여넣기 하세요.

마커 생성하기에서 마커 생성하는 코드도 복사하여 KakaoMap.html에 붙여넣기 하세요.

여기에서는 setCenter 함수에 위도, 경도를 입력인자로 받아 지도 중심을 변경하는 형태로 수정합니다.

마커를 추가하는 함수와 시각화하는 함수도 작성합니다.

*작성한 코드는 다음과 같습니다. 여기에 사용한 appkey는 이미 삭제한 키이므로 여러분의 JavaScript키를 사용하세요.*

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>지도 생성하기</title>
    
</head>
<body>
<!-- 지도를 표시할 div 입니다 -->
<div id="map" style="width:100%;height:350px;"></div>

<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=2a391cc7267b6657a73bfdb91ef09d26"></script>
<script>
var mapContainer = document.getElementById('map'), // 지도를 표시할 div 
    mapOption = { 
        center: new kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표
        level: 3 // 지도의 확대 레벨
    };
function setCenter(lat,lng) {            
    // 이동할 위도 경도 위치를 생성합니다 
    var moveLatLon = new kakao.maps.LatLng(lat,lng);
    
    // 지도 중심을 이동 시킵니다
    map.setCenter(moveLatLon);
}


var markers = [];

function addMarker(lat,lng) {       
    var markerPosition  = new kakao.maps.LatLng(lng,lat);
    // 이동할 위도 경도 위치를 생성합니다 
    var marker = new kakao.maps.Marker({
        position: markerPosition
    });
    markers.push(marker);
}

function showMarkers() {
    for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(map);
    }            
}
// 지도를 표시할 div와  지도 옵션으로  지도를 생성합니다
var map = new kakao.maps.Map(mapContainer, mapOption); 
</script>
</body>
</html>

6. 지역 선택 및 위치 확인 구현

webbr의 NavigateUrl 속성을 http://localhost/KakaoMap.html로 설정합니다.

먼저 lbox_locale을 선택 항목 이벤트 핸들러를 추가합니다.

선택 항목이 없을 때는 SelectedIndex가 -1일 때입니다.

선택 항목을 Locale 형식 개체로 참조합니다.

그리고 WebBrowser 개체의 Document 개체를 참조합니다.

참조한 Document 개체의 InvokeScript 메서드를 호출하면서 setCenter 함수 이름과 위도 경도를 object 배열로 전달합니다.

        private void lbox_locale_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(lbox_locale.SelectedIndex == -1)
            {
                return;
            }
            Locale locale = lbox_locale.SelectedItem as Locale;
            HtmlDocument hdoc = webbr.Document;
            object[] objs = new object[] { locale.Lat,locale.Lng};
            hdoc.InvokeScript("setCenter", objs);
        }

그리고 btn_search의 클릭 이벤트 핸들러 부분도 지도에 마커를 추가하고 시각화하는 부분을 추가합니다.

        private void btn_search_Click(object sender, EventArgs e)
        {
            string query = tbox_query.Text;
            string url = "https://dapi.kakao.com/v2/local/search/keyword.json";
            string query_str = string.Format("{0}?query={1}", url, query);
            WebRequest request = WebRequest.Create(query_str);
            request.Headers.Add("Authorization", "KakaoAK 569a69082cd0c209180eb69aaaa48f1b");
            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader sr = new StreamReader(stream);
            string content = sr.ReadToEnd();

            JavaScriptSerializer jss = new JavaScriptSerializer();
            dynamic d = jss.Deserialize(content);
            dynamic[] ddoc = d["documents"];
            Locale locale;
            HtmlDocument hdoc = webbr.Document;
            object[] objs = new object[2];
            foreach (dynamic elem in ddoc)
            {
                string pname = elem["place_name"];
                double lng = double.Parse(elem["x"]);
                double lat = double.Parse(elem["y"]);
                locale = new Locale(pname, lng, lat);
                lbox_locale.Items.Add(locale);
                //지도에 중심 이동시키기
                //지도에 마커 추가
                objs[0] = locale.Lat;
                objs[1] = locale.Lng;
                hdoc.InvokeScript("setCenter", objs);
                hdoc.InvokeScript("addMarker", objs);                
            }
            //지도에 마커 시각화
            hdoc.InvokeScript("showMarkers",null);
        }

7. MainForm.cs 소스

using System;
using System.IO;
using System.Net;
using System.Web.Script.Serialization;
using System.Windows.Forms;

namespace 지역_검색_및_위치_확인
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void btn_search_Click(object sender, EventArgs e)
        {
            string query = tbox_query.Text;
            string url = "https://dapi.kakao.com/v2/local/search/keyword.json";
            string query_str = string.Format("{0}?query={1}", url, query);
            WebRequest request = WebRequest.Create(query_str);
            request.Headers.Add("Authorization", "KakaoAK 569a69082cd0c209180eb69aaaa48f1b");
            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader sr = new StreamReader(stream);
            string content = sr.ReadToEnd();

            JavaScriptSerializer jss = new JavaScriptSerializer();
            dynamic d = jss.Deserialize(content);
            dynamic[] ddoc = d["documents"];
            Locale locale;
            HtmlDocument hdoc = webbr.Document;
            object[] objs = new object[2];
            foreach (dynamic elem in ddoc)
            {
                string pname = elem["place_name"];
                double lng = double.Parse(elem["x"]);
                double lat = double.Parse(elem["y"]);
                locale = new Locale(pname, lng, lat);
                lbox_locale.Items.Add(locale);
                //지도에 중심 이동시키기
                //지도에 마커 추가
                objs[0] = locale.Lat;
                objs[1] = locale.Lng;
                hdoc.InvokeScript("setCenter", objs);
                hdoc.InvokeScript("addMarker", objs);                
            }
            //지도에 마커 시각화
            hdoc.InvokeScript("showMarkers",null);
        }

        private void lbox_locale_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(lbox_locale.SelectedIndex == -1)
            {
                return;
            }
            Locale locale = lbox_locale.SelectedItem as Locale;
            HtmlDocument hdoc = webbr.Document;
            object[] objs = new object[] { locale.Lat,locale.Lng};
            hdoc.InvokeScript("setCenter", objs);
        }
    }
}

잘 동작하는 지 확인해 보세요.