kakao map API을 사용해 지도를 띄워보자

Joshua·2024년 10월 30일
2

DA

목록 보기
4/5
post-thumbnail

지금 내가 하고 있는 일이 완전히 DA 인가?

라고 물어본다면 그건 아니지만, 인턴을 하는 입장으로써 여러가지를 경험해본다는 것은 정말 행운이다😊

다행히 지금 일하고 있는 회사가 배움에 있어서는 정말 자유롭기 때문에 나도 이런 저런 툴을 써가면서 열심히 일하는 중이다✊

그러던 중 컨퍼런스 장소 선정에 대한 분석을 요청 받았는데
장소에서 중요한건 뭐니뭐니 해도 위치가 아니겠나

그냥 지하철에서 가깝다 - 정도가 아니라
지도에 정확히 보일 수 있고, 거리까지 계산하고 싶었다

그래서 사용해본 ✨KAKAO MAP API✨!
여담이지만 네이버는 워낙 잘 막혀서 찾다가 알게 되었다는 사실

그런데 생각보다 정말 잘 되어 있는 것이 아닌가 !
하나하나 파헤쳐 보자


1. kakao map api 사용하기

https://developers.kakao.com/

일단 여기로 접속한다

TMI : 최근 if(kakao) 컨퍼런스를 온라인으로 들었었는데 카카오가 좋아하는 디자인이 뭔지 알거 같다. 약간 어두운 배경에 밝은 도형

내 애플리케이션에 들어가면 추가하기가 있다
나는 이미 생성해둔 상태라 (1)로 떠있음

애플리케이션 추가하기를 입력하면 이렇게 앱을 생성하는 곳이 뜬다
간단한 정보를 입력하면 바로 생성할 수 있다.

내가 만든 map 애플리케이션에 들어가면 이렇게 정보를 확인할 수 있다
음,,, 사실 이거 뭔지 잘 모르겠음 내가 서비스를 만들 수 있는 것 같은데🙄?

우리는 API KEY가 필요하니 대시보드로 향한다

앱키 탭으로 들어가면 이렇게 다양한 곳에서 사용이 가능한 키가 주르륵 나온다.
나는 flask를 이용해서 지도를 올릴 거기 때문에 Javascript 키를 사용한다

또, 카카오는 api로 사용이 가능한 라이브러리를 제공한다

clusterer: 마커를 클러스터러 라이브러리
services: 장소 검색, 주소-좌표 변환 라이브러리
drawing: 마커와 그래픽스 객체 그리기 모드 라이브러리

appkey를 입력하면서 함께 입력해주면 된다
appkey=APIKEY&libraries=services 이런식으로 !

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>행사장 위치 찾기</title>
    <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey={발급받은 key 입력}"></script>
    <!-- CSS 파일 링크 -->
    <link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<body>
    <h2>행사장 위치</h2>
    <div id="map"></div>

script type의 src 부분에 kakao 링크와 발급받은 appkey를 입력해주면 된다.
처음에 무지성으로 gpt한테 물어봤다가 된통 당했음. gpt 분리불안 버릇좀 고쳐야겠어😢


🚩 지도 생성

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<title>Kakao 지도 시작하기</title>
</head>
<body>
	<div id="map" style="width:500px;height:400px;"></div>
	<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은 APP KEY"></script>
	<script>
		var container = document.getElementById('map');
		var options = {
			center: new kakao.maps.LatLng(33.450701, 126.570667),
			level: 3
		};
		var map = new kakao.maps.Map(container, options);
	</script>
</body>
</html>

내 코드를 가져오려고 했는데, kakao 설명이 더 깔끔해서 그대로 들고왔다 😅

보통 프론트 작업은

  static/css
  ⌞styles.css //스타일 정리해놓은 파일
static/js
  ⌞map.js // 기능 정리해둔 java
templates/
  ⌞index.html // front

이런식으로 작업하기 때문에 내 코드는 뿔뿔히 흩어져있다..^^

// Kakao 지도 로드
kakao.maps.load(function() {
    // Kakao 지도 객체 생성
    var mapContainer = document.getElementById('map'), 
        mapOption = {
            center: new kakao.maps.LatLng(37.486320, 126.898530), 
            level: 4 
        };
    var map = new kakao.maps.Map(mapContainer, mapOption);
    // 주소-좌표 변환 객체 생성 (전역 변수로 설정)
    window.geocoder = new kakao.maps.services.Geocoder();
    // 인포윈도우를 하나만 관리하도록 설정
    var infowindow = new kakao.maps.InfoWindow({zIndex: 1});
    // 여러 주소 처리
    locations.forEach(function(item) {
        // 불용어가 포함된 주소인지 확인
        if (!containsStopWords(item.address)) {
            // 주소로 좌표 변환
            geocoder.addressSearch(item.address, function(result, status) {
                if (status === kakao.maps.services.Status.OK) {
                    var coords = new kakao.maps.LatLng(result[0].y, result[0].x);
                    // 마커 추가
                    var marker = new kakao.maps.Marker({
                        map: map,
                        position: coords
                    });
                    // 마커 클릭 시 인포윈도우 표시
                    kakao.maps.event.addListener(marker, 'click', function() {
                        // 기존에 열린 인포윈도우 닫기
                        infowindow.close();
                        // 클릭한 마커의 정보를 표시할 새로운 인포윈도우 내용
                        var content = '<div style="width:300px;text-align:center;padding:6px 0;">' +
                                    '<strong>' + item.title + '</strong><br>' +
                                    'address : ' + item.address + '<br>' +
                                    'Point : ' + item.point + '<br>' +
                                    // 'URL : ' + item.url + '<br>'+
                                    // '<a href="' + item.url + '" target="_blank">homepage</a>' +
                                    '</div>';
                        // 새로운 인포윈도우를 열기
                        infowindow.setContent(content);
                        infowindow.open(map, marker);
                        // 표 업데이트
                        updateInfoTableWithSingleMarker(item);
                        // 가까운 역 찾기
                        findNearestStation(coords, item);
                    });
                    // 지도의 중심을 해당 주소로 이동
                    map.setCenter(coords);
                }
            });
        } else {
            console.log(`주소 "${item.address}"는 불용어가 포함되어 있어 검색하지 않습니다.`);
        }
    });
});  

내가 구현한 카카오맵 기본 구조
함수까지 적으면 너무 길어질 것 같아서 map.js의 부분만 가져왔다

프론트, 특히 java는 거의 만져본적이 없는데 나름 재미있었다
파이썬에서 쓰는 것처럼 함수도 지정해서 사용하기도 하고 👶


2. kakaomap api으로 거리 계산하기

내가 api를 쓰면서 가장 신기했던 점...

위에서 쓰인 getDistance 함수는 이렇게 작성되었다

// 거리 계산 함수
function getDistance(coords1, coords2) {
    var lat1 = coords1.getLat();
    var lng1 = coords1.getLng();
    var lat2 = coords2.getLat();
    var lng2 = coords2.getLng();
    // Haversine formula (지구의 곡률을 고려한 거리 계산)
    var R = 6371e3; // 지구의 반지름 (미터)
    var φ1 = lat1 * Math.PI/180; // 위도를 라디안으로 변환
    var φ2 = lat2 * Math.PI/180; //위도를 라디안으로 변환
    var Δφ = (lat2-lat1) * Math.PI/180; //두 위도의 차이를 라디안으로 계산
    var Δλ = (lng2-lng1) * Math.PI/180; //두 경도의 차이를 라디안으로 계산
    var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
            Math.cos(φ1) * Math.cos(φ2) *
            Math.sin(Δλ/2) * Math.sin(Δλ/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    return Math.round(R * c); // 거리 반환 (미터 단위)
}

이야 이게 무슨 소리야 😅

차근차근 해보자면

var lat1 ~ lng2 : 위도(lat), 경도(lng) 추출
var R ~ var Δλ : Haversine 공식을 위한 상수 및 변환
var a : 두 좌표 간의 대원적 거리의 제곱을 계산
var c : 아크 탄젠트 함수(atan2)를 사용하여 두 점 사이의 중심각 계산

아직 한 60%만 감이 잡혔는데, 지도상의 거리를 지구의 곡률을 고려하여 정확히 계산하는 방법이라 생각하면 되겠다
kakao map에 위치를 입력하면 위도와 경도를 알려주기 때문에 거리 계산도 한결 편했다👌


3. kakaomap + flask

from flask import Flask, render_template
import pandas as pd
app = Flask(__name__)
@app.route('/')
def index():
    # CSV 파일 읽기
    # df = pd.read_csv('processed_df.csv')
    df = pd.read_excel('handling.xlsx')
    # 결측값 제거 및 필요한 데이터만 리스트로 변환
    data = df.dropna(subset=['address', 'title', 'point', 'url', 'condition', 'contact'])
    # 'keyword' 컬럼에서 지역 이름 추출 (공백으로 구분된 첫 번째 단어)
    data['region'] = data['keyword'].str.split().str[0]
    # 줄바꿈 문자를 <br>로 변환
    data['condition'] = data['condition'].str.replace('\n', '<br>', regex=False)
    # 중복된 지역 이름 제거 후 리스트로 변환
    regions = sorted(data['region'].unique().tolist())
    # 필요한 컬럼을 딕셔너리로 변환
    locations = data[['title', 'address', 'point', 'url', 'region', 'condition', 'contact']].to_dict(orient='records')
    # 템플릿에 데이터 전달
    return render_template('index.html', locations=locations, regions=regions)
if __name__ == '__main__':
    app.run(debug=True)

flask로 구현한 main.py를 실행시키면

이렇게 지도에 위치 마커가 표시 된다

마커를 누르면 마커 위에 정보를 표시하고,
지역 별로 드롭다운으로 구현하고,
아래에 표로 나타내고,
엑셀로 다운로드 하는 기능까지 구현해봤다

사실 마커 부분을 제외하면 java로 구현한거지만 ^^;;ㅎㅎ
이렇게 또 하나 배워가는거지

https://apis.map.kakao.com/

위의 사이트를 들어가면 kakaomap에 대해 더 자세히 알 수 있다
그럼 다음에는 꼭 LLM을 공부를.............

profile
🐥삐약이 개발자🐤

0개의 댓글

관련 채용 정보