기록
article thumbnail
Published 2023. 4. 24. 17:45
카카오맵 가지고 놀기 기타
728x90

💚 뭐하고 있어?

인구 밀집 시뮬레이션을 개발을 위해 오늘도 끄적끄적 연구중

카카오맵을 쓸지는 모르겠지만 일단 만져보고 있다.

이것은 인구 밀집을 이런식으로 나타내라 안내해주는 글이 아님을 밝힙니당.. (혼자 삽질 기록용임!)

 

🧀 카카오맵을 사용하기 앞서

카카오맵을 사용하기 위해서는 개발자 등록(Kakao developers)을 해야한다. 

이건 개발 공부하는 사람이라면 다 알거라 생각하니 패스 (절대 귀찮아서가 아니다.)

 

나는 nodejs + express 로 진행했고, 앱키는 JavaScript키를 이용했다. 각자 개인 페이지에서 필요한 키를 확인해서 쓰면 된다.

키키 옛날에 테스트한다고 등록해놨었더라! 귀여운 파란 고양이 뭐람..?

 

카카오 맵 개발을 위한 상세 내용은 이미 가이드 페이지에 상세하게 나오므로 사용방법은 여기에서 알아보자

(나는 지금 카카오맵 연동과 사용법을 소개하려고 글을 쓰는게 아니다!)

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

 

🏃‍♂️ 어떻게 표현해볼까...

인구 밀집 표현을 위해 카카오맵에서 제공해주는 샘플을 둘러보던 중 

클러스터 마커 표시를 알게되었다.

샘플데이터가 아주아주 귀엽당 삐약

아하! 이걸로 특정 구역에 위·경도 값들로 [원활, 보통, 혼잡, 매우혼잡]을 표시하면 되겠다. 라고 생각했다.

그런데 카카오에서 제공해주는 샘플 데이터들은 전국구로 넓게 분포되어 있어서 인구밀집도(?)라고 생각하기엔 문제가 있다.

아니 json 샘플 파일명도 치킨이다 치킨..! 아마도 어떤 치킨집의 위치인것같다!!!

(샘플파일 Link : https://apis.map.kakao.com/download/web/data/chicken.json)

 

 

🛴 밀집도를 표현해보자

나는 홍대 거리 혼잡도를 테스트하기로 했다. 

◼ 위경도 값을 사람이라고 가정하고, 홍대 위주로 위경도 값이 400~600개가 있어야함
     => 홍대 위주의 위경도 값을 랜덤으로 생성해야된다.

◼ 지도level을 최소값으로 했을때 마커가 아니라 [원활, 보통, 혼잡, 매우혼잡]으로 나타나야함 
(카카오맵 level이 낮을수록 건물들이 자세하게 보이고, 높을수록 구... 지역... 한국지도(?) 이런식으로 ? 표현됨. 레벨은 1~15) 

 

1. 먼저 구글맵에서 위경도를 조사했다.. (카카오맵에서는 위경도를 알려주지 않더라. 내가 못찾는건가?)
대충 범위를 정해서 각 꼭지점의 위경도를 구했다.

37.556473, 126.922957
37.556550, 126.928133
37.554400, 126.922900
37.554887, 126.929416

 

 

2. 특정 범위내 위경도 생성 랜덤함수 짜기 + 리스트에 넣기

lat 의 min과 max 의 차이는 약 2150이었고,  lng 의 min과 max의 차이는 약 6500이었다.

그래서 먼저 각각 2150, 6500의 랜덤한 수를 생성해서

위경도 값으로 변경하는 작업을 했다.

각각 min값에서 부터 랜덤으로 추출된 값을 더하는 식으로 진행했다. 

var list = { positions:[] }
for(var i=0; i<10; i++) {
  var lat = Math.floor(Math.random() * 2151);
  var lng = Math.floor(Math.random() * 6501);
  
  lat = ((lat+554400) * 0.000001 + 37).toFixed(6);
  lng = ((lng+922900) * 0.000001 + 126).toFixed(6);
  
  list.positions.push({lat, lng});
}
console.log(list);

(코드를 더 깔끔하게 할 수 있을것같은데 모르겠다 일단 이렇게..ㅎㅎㅎ..? )

chicken.js가 아래와 같은 형식으로 나타나므로 나도 똑같이 만들어보려고 위와 같이 코드를 작성함.

결과 json 내에  positions 라는 객체가 리스트를 담고 있는 형태

 

3. index.js

// 2023.04.24 - 만약에 count가 입력되지 않는다면 default로 100건
router.get('/hongdae', function (req, res, next) {
  var list = getPosition(100);
  res.json(list);
});

// 2023.04.24 - count 특정값 입력가능. 근데 1000 초과는 안됨. 과부하걸릴것같아서 그냥 막음. 
router.get('/hongdae/:count', function (req, res, next) {
  let count = req.params.count;
  if (count > 1000) {
    res.send('너무 많습니다.');
  } else {
    var list = getPosition(count);
    res.json(list);
  }
})

 

4. index.ejs 내 script 

var container = document.getElementById('map'); //지도를 담을 영역의 DOM 레퍼런스
    var options = { //지도를 생성할 때 필요한 기본 옵션
        center: new kakao.maps.LatLng(37.557527, 126.9244669), //지도의 중심좌표.
        level: 3 //지도의 레벨(확대, 축소 정도)
    };
    var map = new kakao.maps.Map(container, options); //지도 생성 및 객체 리턴

    var clusterer = new kakao.maps.MarkerClusterer({
        map: map, // 마커들을 클러스터로 관리하고 표시할 지도 객체 
        averageCenter: true, // 클러스터에 포함된 마커들의 평균 위치를 클러스터 마커 위치로 설정 
        minLevel: 1, // 클러스터 할 최소 지도 레벨 
        calculator: [10, 30, 50], // 클러스터의 크기 구분 값, 각 사이값마다 설정된 text나 style이 적용된다
        texts: getTexts, // texts는 ['삐약', '꼬꼬', '꼬끼오', '치멘'] 이렇게 배열로도 설정할 수 있다 
        styles: [{ // calculator 각 사이 값 마다 적용될 스타일을 지정한다
                width : '30px', height : '30px',
                background: 'rgba(51, 204, 255, .8)',
                borderRadius: '15px',
                color: '#000',
                textAlign: 'center',
                fontWeight: 'bold',
                lineHeight: '31px'
            },
            {
                width : '40px', height : '40px',
                background: 'rgba(255, 153, 0, .8)',
                borderRadius: '20px',
                color: '#000',
                textAlign: 'center',
                fontWeight: 'bold',
                lineHeight: '41px'
            },
            {
                width : '50px', height : '50px',
                background: 'rgba(255, 51, 204, .8)',
                borderRadius: '25px',
                color: '#000',
                textAlign: 'center',
                fontWeight: 'bold',
                lineHeight: '51px'
            },
            {
                width : '60px', height : '60px',
                background: 'rgba(255, 80, 80, .8)',
                borderRadius: '30px',
                color: '#000',
                textAlign: 'center',
                fontWeight: 'bold',
                lineHeight: '61px'
            }
        ]
    });

    // 클러스터 내부에 삽입할 문자열 생성 함수입니다 
    function getTexts( count ) {

        // 한 클러스터 객체가 포함하는 마커의 개수에 따라 다른 텍스트 값을 표시합니다 
        if(count < 10) {
            return '원활';        
        } else if(count < 30) {
            return '보통';
        } else if(count < 50) {
            return '혼잡';
        } else {
            return '매우혼잡';
        }
    }

    $.get("/hongdae", function(data) {
        console.log(data.positions);
        // 데이터에서 좌표 값을 가지고 마커를 표시합니다
        // 마커 클러스터러로 관리할 마커 객체는 생성할 때 지도 객체를 설정하지 않습니다
        var markers = $(data.positions).map(function(i, position) {
            return new kakao.maps.Marker({
                position : new kakao.maps.LatLng(position.lat, position.lng)
            });
        });

        // 클러스터러에 마커들을 추가합니다
        clusterer.addMarkers(markers);
    });

    
    kakao.maps.event.addListener(clusterer, 'clusterclick', function(cluster) {

        // 현재 지도 레벨에서 1레벨 확대한 레벨
        var level = map.getLevel()-1;

        // 지도를 클릭된 클러스터의 마커의 위치를 기준으로 확대합니다
        map.setLevel(level, {anchor: cluster.getCenter()});
    });

카카오맵 예제에서 긁어왔고, 수정한 내용은 별로없다.

1. clusterer - minLevel 1로 조정

2. 삐약, 꼬꼬, 치멘 등을 원활, 보통, 혼잡으로 수정

3. chicken.js url을 위에서 만든 hongdae로 수정

 

🍋 결과

내가 원한대로 데이터가 잘 넘어왔고…

정확히 사각형 모양으로 저렇게 분포되었다.

원활, 보통, 혼잡, 매우혼잡 값 범위는 조정하면 될 것 같다..

 

 

내가 원했던 작업은 끝!

지도 크기에 따라서 내가 원하는대로 clusterer의 값 제공

 

 

 

💒 그런데 말입니다.

인구 밀집도? 혼잡도를 이런식으로 지도 표시하는게 맞을까? 

사실 내가 해야하는건 다중밀집에 대한 내용이었는데 …

교통량 표시하는 것 처럼 길에 빨강, 노랑, 초록 표시를 하는게 맞지 않을까? 

(그치만 교통은 정말 도로위의 혼잡도..)

 

 

 

길 위에 선을 긋는 방법을 찾아봐야지. 

그런데 고맙게도 카카오맵에서 도형그리기(선그리기)를 지원한다. 

다음번에 알아보도록하자.

 

 

(없는게 뭐지. 멋있다.)

profile

기록

@데굴데구르르 림

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

2025, 이제 사내 컨플루언스에 모두 작성하게 되어서 업데이트가 잘 없을 것 같습니다..