-
Vue.js 카카오맵API 날씨RSS를 통한 주소지 날씨 받기WEB 2021. 6. 26. 23:11
입력하는 주소의 날씨를 알아봐야 하는 경우가 생겼다.
이 부분을 구현할때 몇가지 사항을 고려해야 한다.
1. 대부분 주소를 입력하는 경우 주소가 명확하지 않은 경우가 있다.
예를 들어 "충청북도"를 "충북"이라고 기재한다거나, 동이나 지번을 생략하는 경우가 있다.
>카카오맵 API를 사용하면 생략되거나 간략 기재된 주소인식률이 높다.
2.날씨를 알려주는 RSS나 RestfulAPI 서비스 중 무료.
https://openweathermap.org/ 가 있으나, 지역이라던지 결과값이 한글표기가 아닌듯 했다.
> http://www.kma.go.kr/weather/lifenindustry/sevice_rss.jsp 에서 검색한 내용을
> http://www.kma.go.kr/wid/queryDFS.jsp?gridx=61&gridy=127 의 위도와 경도를 넣어서 받을 수 있다.
> 1번 카카오맵API를 이용하여 위도와 경도를 뽑을 수 있다.
> 위도와 경도를 그리드로 변환해야한다. dfs_xy_conv() 참고
Geocoder()를 사용해야하는데 SDK를 불러오는 부분에 '&libraries=services'이 구문을 넣자.
3. 카카오 개발 API에 가입하여 WEB을 사용하고,
localhost로 테스트중이라면 도메인 등록에 localhost와 포트까지 추가해야한다.
또한, Vue에서는 카카오 맵 모듈의 탑재에 대해 정식적인 방안이 없다.
여러 방법을 찾아 테스트하였으며 아래 기재하였다.
4. Vue에서 2번 항목 접근시 CORS가 발생한다.
> vue.config.js를 생성 또는 그 안에 내용을 추가해야한다.
> npm run serve로 실행해야 한다.
module.exports = { devServer: { proxy : { '/wid': { target: 'http://www.kma.go.kr', //changeOrigin: true } } } };
5. XML 파싱
> DOMParser()라는것을 이용하여 직접 파싱을 해줘야 한다.
> 데이터의 내용은 보면 충분히 알 것이다.
6. 아래는 Vue의 소스
> 제일 기본적인 맵 표시와, 기본 포인트에 대한 로그출력이 있으므로 참고하자.
> 추가로, const self = this라고 표기되어있는데, 테스트를 위해 간편하게 기재한 것이고,
함수의 ES6와 관련이 있는 내용으로 해결해야 한다.
<template> <div id="map" style="width:500px;height:400px;"> </div> </template> <script> import axios from "axios"; export default { name: 'HelloWorld', props: { msg: String }, data() { return { //geoval : "" } }, methods: { initMap() { //axios를 위해 변환을 해줘야함 const self = this; var mapContainer = document.getElementById('map'), // 지도를 표시할 div mapOption = { center: new kakao.maps.LatLng(37.564343, 126.947613), // 지도의 중심좌표 level: 3, // 지도의 확대 레벨 }; var map = new kakao.maps.Map(mapContainer, mapOption); //마커추가하려면 객체를 아래와 같이 하나 만든다. var marker = new kakao.maps.Marker({ position: map.getCenter() }); marker.setMap(map); // 주소-좌표 변환 객체를 생성합니다 var geocoder = new kakao.maps.services.Geocoder(); // 주소로 좌표를 검색합니다 geocoder.addressSearch('주소', function(result, status) { // 정상적으로 검색이 완료됐으면 if (status === kakao.maps.services.Status.OK) { var coords = new kakao.maps.LatLng(result[0].y, result[0].x); var message = 'latlng: new kakao.maps.LatLng(' + result[0].y + ', '; message += result[0].x + ')'; console.log(message); var gridXY = self.dfs_xy_conv("toXY", result[0].y, result[0].x); self.getWeather(gridXY) // 결과값으로 받은 위치를 마커로 표시합니다 var marker = new kakao.maps.Marker({ map: map, position: coords }); // 인포윈도우로 장소에 대한 설명을 표시합니다 var infowindow = new kakao.maps.InfoWindow({ content: '<div style="width:150px;text-align:center;padding:6px 0;">장소</div>' }); infowindow.open(map, marker); // 지도의 중심을 결과값으로 받은 위치로 이동시킵니다 map.setCenter(coords); } }); }, getWeather(params) { //좌표에 따른 날씨 XML데이터로 받아옴 var strQuery = "/wid/queryDFS.jsp?gridx=" + params.x + "&gridy=" + params.y; //var strQuery = "http://www.kma.go.kr/wid/queryDFS.jsp?gridx=" + params.x + " &gridy=" + params.y; console.log(strQuery); axios .get(strQuery, {timeout: 5000}) .then((response) => { console.log(response.data); var parser = new DOMParser(); var xml = parser.parseFromString(response.data, 'text/xml'); var children = xml.getElementsByTagName('body')[0].getElementsByTagName('data')[0].getElementsByTagName('wfKor')[0].childNodes[0].nodeValue; console.log(children); }) .catch((error) => { self.loading = false; throw error; }); }, dfs_xy_conv(code, v1, v2) { //<!-- // // LCC DFS 좌표변환을 위한 기초 자료 // var RE = 6371.00877; // 지구 반경(km) var GRID = 5.0; // 격자 간격(km) var SLAT1 = 30.0; // 투영 위도1(degree) var SLAT2 = 60.0; // 투영 위도2(degree) var OLON = 126.0; // 기준점 경도(degree) var OLAT = 38.0; // 기준점 위도(degree) var XO = 43; // 기준점 X좌표(GRID) var YO = 136; // 기1준점 Y좌표(GRID) // // LCC DFS 좌표변환 ( code : "toXY"(위경도->좌표, v1:위도, v2:경도), "toLL"(좌표->위경도,v1:x, v2:y) ) // var DEGRAD = Math.PI / 180.0; var RADDEG = 180.0 / Math.PI; var re = RE / GRID; var slat1 = SLAT1 * DEGRAD; var slat2 = SLAT2 * DEGRAD; var olon = OLON * DEGRAD; var olat = OLAT * DEGRAD; var sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5); sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn); var sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5); sf = Math.pow(sf, sn) * Math.cos(slat1) / sn; var ro = Math.tan(Math.PI * 0.25 + olat * 0.5); ro = re * sf / Math.pow(ro, sn); var rs = {}; if (code == "toXY") { rs['lat'] = v1; rs['lng'] = v2; var ra = Math.tan(Math.PI * 0.25 + (v1) * DEGRAD * 0.5); ra = re * sf / Math.pow(ra, sn); var theta = v2 * DEGRAD - olon; if (theta > Math.PI) theta -= 2.0 * Math.PI; if (theta < -Math.PI) theta += 2.0 * Math.PI; theta *= sn; rs['x'] = Math.floor(ra * Math.sin(theta) + XO + 0.5); rs['y'] = Math.floor(ro - ra * Math.cos(theta) + YO + 0.5); } else { rs['x'] = v1; rs['y'] = v2; var xn = v1 - XO; var yn = ro - v2 + YO; ra = Math.sqrt(xn * xn + yn * yn); if (sn < 0.0) - ra; var alat = Math.pow((re * sf / ra), (1.0 / sn)); alat = 2.0 * Math.atan(alat) - Math.PI * 0.5; if (Math.abs(xn) <= 0.0) { theta = 0.0; } else { if (Math.abs(yn) <= 0.0) { theta = Math.PI * 0.5; if (xn < 0.0) - theta; } else theta = Math.atan2(xn, yn); } var alon = theta / sn + olon; rs['lat'] = alat * RADDEG; rs['lng'] = alon * RADDEG; } return rs; } }, mounted(){ if (window.kakao && window.kakao.maps) { this.initMap(); } else { const script = document.createElement('script'); script.onload = () => kakao.maps.load(this.initMap); //카카오 개발자 서비스에서 서버 주소 등록해야 함 script.src = '//dapi.kakao.com/v2/maps/sdk.js?autoload=false&appkey=카카오키값&libraries=services'; document.head.appendChild(script); } } } </script>
'WEB' 카테고리의 다른 글
InfluxDB 1.8.1 윈도우 설치 (0) 2023.07.17 Node.js 연동 ajax 기본 (0) 2022.09.29 pm2 명령어를 찾을 수 없습니다. (0) 2022.09.27 mariadb 최초 설정 (1) 2022.09.26 공공데이터포털을 통한 날씨 받기 (0) 2021.07.05