본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


앵귤러, 리엑트, 뷰/뷰(Vuejs)

[Vuejs] 카카오맵, 티맵 API 길 찾기 연동

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2023. 3. 23.

 

뷰(Vuejs) 환경에서 카카오맵과 T맵 API를 간단하게 연동하는 방법 입니다.

이러한 외부 서비스를 사용하기 위해서는 해당 API를 검색하여 가입을 한 뒤에 사용할 컴퓨터 IP를 등록하고, 등록된 인증 키를 받아서 호출해야 합니다.

 

* 카카오맵 API 가입 및 키 받는 방법

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

 

* 티맵 API 가입 및 키 받는 방법

https://tmapapi.sktelecom.com/main.html#webv2/guide/apiGuide.guide1

 

각각의 키를 받은뒤에는 해당 라이브러리를 등록 해 주어야 합니다. 웹 기반 환경 이므로 추가로 설치하는 것은 없습니다.

* 대상(부트스트랩하는 html 파일) : index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
    <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=카카오API키"></script>
    <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=카카오API키&libraries=services,clusterer,drawing"></script>  
    
    <script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
    <script src="https://apis.openapi.sk.com/tmap/jsv2?version=1&appKey=T맵API키"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

 

위 스크립트 테그에서 잊지말고 등록 해야 하는 Jquery!!! 입니다.

T맵 같은 경우에는 몇몇 함수가 "$" 값을 찾고 있는 모습을 볼 수 있습니다.

바로 제이쿼리(Jquery)를 내부적으로 쓴 다는 뜻이겠지요.

그러므로 티맵 관련된 api를 사용하려면 반드시 제이쿼리 파일을 넣어 주어야 합니다.

 

 

#1. 카카오맵(kakao map)

여기까지 하고 난 뒤에 먼저 카카오API를 연동하기 위한 페이지를 만들어 줍니다.

아래 샘플코드는 카카오맵을 단순하게 실행하여 나타내는 코드 입니다.      * axios를 왜 쓰는지는 나중에....

* 카카오 파일

<script>
import axios from 'axios'
export default {

    data() {
        return {
            options: {
                center: new kakao.maps.LatLng(37.39843974939604, 127.10972941510465),
                level: 13
            },
            map: null
        }
    },
    computed: {

    },
    watch: {

    },
    mounted() {
        const container = this.$refs.map;
        let _map = new kakao.maps.Map(container, this.options);
        this.map = _map;    
    },
  }
</script>

<template>
    <div id="map" ref="map"></div>
</template>
<style>
#map {
    width: 100%;
    height: 750px;
    border: 1px solid gray;
}
</style>

 

직관적인 코드의 모습 입니다.

map 이라는 객체의 참조(ref) 값을 가져와서 kakao라는 객체를 통해 생성해 주는 모습 입니다.

위 코드를 실행하면 아래처럼 지도가 나타나게 됩니다.

잘 되는군요!

 

카카오맵 같은 경우에는 지도를 표현하기 위해서 div 엘리먼트에 이미지를 넣어서 지도를 그리고, 경로나 좌표계를 표현하기 위해서는 svg를 사용하고 있습니다.

또한 위에 표시하는 오버레이 같은 경우에는 일반 html 테그로 되어 있습니다.

그렇기 때문에 맘먹고 경로같은 것은 돔(dom)에 직접 접근하여 바로 제거하거나 변조가 가능 합니다.

* 근데 굳이 그러진 않겠죠..?

간단한 예제 입니다. 저거 걍 삭제하면 경로 사라집니다..ㅎ

 

#2. 티맵(Tmap)

T맵 페이지도 만들어 보았습니다.

T맵같은 경우에는 원래 교통상황, 길 안내에 최척화된 친구 답게 API내용도 어마어마 했습니다.

티맵 사용법은 카카오 맵과 비슷 하였습니다.

 

아래 샘플코드는 티맵을 단순하게 실행하여 나타내는 코드 입니다.     

* 티맵 파일

<script>

export default {
  mounted() {
    let option = {
      center: new Tmapv2.LatLng(37.39843974939604, 127.10972941510465),
      width: "890px",
      height: "400px",
      zoom: 7
    };
    let map = new Tmapv2.Map(this.$refs.tmap, option);
  }

}
</script>

<template>
  <div ref="tmap">
  </div>
</template>

 

생성이나 사용하는 방법이 거의 같았습니다.

위 코드를 실행하면 마찬가지로 지도가 잘 나타나게 됩니다.

 

T맵에서는 길찾기나 경로 표시를 canvas를 활용하여 나타내고 있습니다.

마찬가지로 지도 이미지는 div 테그에서 각각 적용하여 나타내고 있습니다.

T맵에서 좀더 좋았던 점은 교통흐름을 추가하여 데이터를 표현할 수 있다는 점 이였습니다.

이녀석은 canvas를 날려버리면 되는데..그러면 두번다시 길을 못그립니다...

 

#3. 길 찾기(카카오)

카카오에서는 폴리라인(poly line), 즉 사용자가 이동해야 되는 길을 표시하려면 http 통신을 따로 보내어 "길찾기 api 요청 주소" 에 맞추어 데이터를 받아와야 합니다.

그러므로 axios 함수를 설치한 뒤에 아래처럼 요청 해 주면 됩니다.

get방식의 요청에 데이터를 받아와서 받아온 데이터를 잘 정리하면 길을 이쁘게 그릴 수 있습니다.

뭐..네 그렇습니다.

 

이렇게 나온데이터는 맨 처음에 생성한 카카오 맵 객체를 사용하여 그림을 그려주면 됩니다.

주의 해야되는 점은 뷰 개발 환경에서 "카카오 길찾기 api"를 요청하게 되면 cors 문제에 직면하게 됩니다.

그러므로 프록시 설정을 해 주거나 아니면 개발중인 서버를 통해서 데이터를 받아오는 구조가 되어 있어야 합니다.

여기서는 프록시(proxy) 설정을 통하여 데이터를 받아와 표현 하였습니다.

target에 카카오 길찾기 api 주소를 써 주세요

 

카카오맵 길찾기를 구현한 샘플 코드 입니다.

<script>
import axios from 'axios'
export default {
    data() {
        return {
            options: {
                center: new kakao.maps.LatLng(37.39843974939604, 127.10972941510465),
                level: 13
            },
            map: null
        }
    },
    mounted() {
        const container = this.$refs.map;
        let _map = new kakao.maps.Map(container, this.options);
        this.map = _map;

        kakao.maps.event.addListener(_map, 'click', function(mouseEvent) {     
            console.log(mouseEvent.latLng);
        });                    

        setTimeout(() => {

            axios.get('/api?origin=127.11409769110776,37.99269184820678&destination=126.62974669101217,37.39996530012616&waypoints=&priority=RECOMMEND&car_fuel=GASOLINE&car_hipass=false&alternatives=false&road_details=false', {
                headers : {
                    'Authorization' :'KakaoAK 키값',
                    'Content-Type'  : 'application/json'
                }
            })
            .then(arg => {
                let {result_code, summary, sections} = arg?.data?.routes[0];
                console.log(arg)
                if(sections[0]){
                    let {distance, duration, guides : arrays, roads} = sections[0];  //distance : 미터단위, duration : 초 단위
                    
                    let detailRoads = [];

                    for(let i=0;i < roads.length;i++){
                        let arg = roads[i];
                        let mini = arg.vertexes;
                        let cursor = 0;
                        while(cursor < mini.length){
                            let obj = new kakao.maps.LatLng(mini[cursor+1], mini[cursor]);
                            detailRoads.push(obj);
                            cursor = cursor + 2;
                            if(cursor >= 1000000) break;
                        }                             
                    }
                    arrays = arrays.map( (arg, idx)=>{
                        let{x, y}  = arg;
                        if(x && y){
                            arg.position = new kakao.maps.LatLng(arg.y, arg.x);
                        }
                        return arg;
                    });          
                         
                    let { title, position} = arrays[0];
                    // 마커 이미지의 이미지 크기 입니다
                    let imageSize = new kakao.maps.Size(24, 35);
                    // 마커 이미지를 생성합니다    
                    let image = new kakao.maps.MarkerImage('https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/red_b.png', imageSize);
                    // 마커를 생성합니다
                    let marker1 = new kakao.maps.Marker({
                        map: _map, // 마커를 표시할 지도
                        position,
                        title: title? title : '', // 마커의 타이틀, 마커에 마우스를 올리면 타이틀이 표시됩니다
                        image // 마커 이미지 
                    });

                    let {title : title2, position : position2} = arrays[arrays.length-1];
                    // 마커 이미지의 이미지 크기 입니다
                    // 마커 이미지를 생성합니다    
                    let image2 = new kakao.maps.MarkerImage('https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/blue_drag.png', imageSize);
                    // 마커를 생성합니다
                    let marker2 = new kakao.maps.Marker({
                        map: _map, // 마커를 표시할 지도
                        position : position2,
                        title: title2? title2 : '', // 마커의 타이틀, 마커에 마우스를 올리면 타이틀이 표시됩니다
                        image : image2 // 마커 이미지 
                    });                   
                        
                    // 지도에 표시할 선을 생성합니다
                    let polyline = new kakao.maps.Polyline({
                        //path: arrays.map( arg=> arg.position), // 선을 구성하는 좌표배열 입니다
                        path : detailRoads,
                        strokeWeight: 5, // 선의 두께 입니다
                        strokeColor: 'red', // 선의 색깔입니다
                        strokeOpacity: 0.7, // 선의 불투명도 입니다 1에서 0 사이의 값이며 0에 가까울수록 투명합니다
                        strokeStyle: 'solid' // 선의 스타일입니다
                    });

                    // 지도에 선을 표시합니다 
                    polyline.setMap(_map);                      

                    let customOverlay = new kakao.maps.CustomOverlay({
                        position: new kakao.maps.LatLng(37.39843974939604, 127.10972941510465),
                        content: `<div class ="label">거리, 시간 : ${distance}, ${duration}</div>`
                    });

                    // 커스텀 오버레이를 지도에 표시합니다
                    customOverlay.setMap(_map);

                    //지우는 방법
                    // setTimeout(() => {
                    //     polyline.setMap(null);
                    //     customOverlay.setMap(null);
                    //     marker1.setMap(null);
                    //     marker2.setMap(null);
                    // }, 3000);
                }
            }).catch(err => {
                console.log(err)
            });
        }, 3000);
    }
}
</script>

<template>
    <div id="map" ref="map"></div>
</template>
<style>
#map {
    width: 100%;
    height: 750px;
    border: 1px solid gray;
}
.label{
    padding: 1rem;
    background : white;
    border: 1px solid blue;
}
</style>

 

 

#4. 길 찾기(티맵)

티맵에서는 axios 같은 HTTP 통신 모듈을 따로 쓰지 않아도 길찾기와 관련된 함수를 통해 쉽게 접근하게 해 줍니다.

길찾기를 하기 위해서는 Tmapv2.extension.TData, Tmapv2.extension.GeoJSON 요 2 객체를 사용하면 간단하게 구현 가능 합니다.

시작, 종료 지점과 함께 데이터를 받아와서 동작 할 콜백용 파라미터를 만들어어 실행해야 합니다.

티맵 길찾기에 사용된 샘플코드 입니다.

<script>
export default {
  mounted() {
    let option = {
      center: new Tmapv2.LatLng(37.39843974939604, 127.10972941510465),
      width: "890px",
      height: "650px",
      zoom: 7
    };
    let map = new Tmapv2.Map(this.$refs.tmap, option);
    
    setTimeout(() => {

      let s_latlng = new Tmapv2.LatLng(37.99269184820678, 127.11409769110776);  //시작
      let e_latlng = new Tmapv2.LatLng(37.39996530012616, 126.62974669101217);  //도착

      let optionObj = {
        reqCoordType: "WGS84GEO", //요청 좌표계 옵셥 설정입니다.
        resCoordType: "WGS84GEO",  //응답 좌표계 옵셥 설정입니다.
        trafficInfo: "Y"
      };

      let markers = [];  //초기화를 위한 배열1
      let polyies = [];  //초기화를 위한 배열2

      let params = {  //콜백용 파라미터
        onComplete: function () {  //화살표함수 쓰시면 안됩니다...this 동작 안해요...
          console.log(this._responseData);

          let {features} = this._responseData;
          let jsonObject = new Tmapv2.extension.GeoJSON();
          let jsonForm = jsonObject.rpTrafficRead(this._responseData);

          console.log('소요 예측 시간 : ',features[0].properties.totalTime)
          console.log('총 거리 : ',features[0].properties.totalDistance)

          let marker1 = new Tmapv2.Marker({
            position: new Tmapv2.LatLng(jsonForm[0].geometry[0].y, jsonForm[0].geometry[0].x) ,
            icon: 'http://tmapapi.sktelecom.com/upload/tmap/marker/pin_r_m_s.png',
            map: map,
            tag: ''
          });
          let marker2 = new Tmapv2.Marker({
            position: new Tmapv2.LatLng(jsonForm[jsonForm.length-1].geometry[0].y, jsonForm[jsonForm.length-1].geometry[0].x) ,
            icon: 'http://tmapapi.sktelecom.com/upload/tmap/marker/pin_r_m_e.png',
            map: map,
            tag: ''
          });
          markers.push(marker1);
          markers.push(marker2);

          let trf = {
            // 사용자가 임의로 색상을 설정할 수 있습니다.
            // 교통정보 옵션 - 라인색상
            '1': "green", //원할
            '2': "#afb935", //서행
            '3': "#ff8a5b",  //정체
            '4': "red"  //정체
          };          

          jsonForm.forEach( ({attributes, geometry}) => {
              if(!attributes.pointType){
                let ar_line = [];
                let color = 'black';
                geometry.forEach( geo => {
                  ar_line.push(new Tmapv2.LatLng(geo.y, geo.x));
                  if(geo.t){
                    color = trf[geo.t];
                  }
                });
                let polyline = new Tmapv2.Polyline({
                  path: ar_line,
                  strokeColor: color,
                  strokeWeight: 6,
                  map: map
                });  
                polyies.push(polyline);
              }
          });
        },
        onProgress: function () {  //진행중일때 동작

        },
        onError: function () {  //오류나면 동작

        }
      };

      //// TData 객체 생성
      const tData = new Tmapv2.extension.TData();

      //// TData 객체의 경로요청 함수
      tData.getRoutePlanJson(s_latlng, e_latlng, optionObj, params);

      //초기화
      // setTimeout(() => {
      //   markers.forEach(element => {
      //     element.setMap(null);
      //   });
      //   polyies.forEach(element => {
      //     element.setMap(null);
      //   });        
      // }, 5000);
    }, 2000);

  }
}
</script>

<template>
  <div ref="tmap">
  </div>
</template>

 

티맵이 좀더 좋았던 점은 교통흐름에 따른 값을 받을수 있어서 편리했던 것 같습니다.

받아온 데이터를 Tmapv2.extension.GeoJson 객체의 rpTrafficRead 함수를 실행 해 주면 교통 흐름에 따른 구간별 색상을 표현하기에 유용했습니다.

 

2개의 API 모두 일일 단위로 일정이상 사용하게 되면 무료버전에서는 사용불가 제한을 받습니다.

이점 참고하여 기획 및 개발을 진행하면 되겠습니다.

 

이상으로 카카오맵, 티맵 API 길 찾기 연동에 대해서 소개하여 보았습니다.

궁금한점 또는 틀린부분은 언제든지 환영 입니다! 👻

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글