혜미의 개발 일지
[API] API로 날씨와 지도 구현하기 본문
현재 API연습을 위해 지도맵과 날씨 기상예보 페이지를 만들어 보는 중이다.
일단, 카카오의 지도 API를 이용하여 카카오 지도맵과 카카오 검색 기능을 오픈소스로 가져와서 구현해봤다.
<div id="map" style="width:800px;height:700px;">
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=5~~~f&libraries=services,clusterer"></script>
<script>
var container = document.getElementById('map');
var markers = [];
var options = {
center: new kakao.maps.LatLng(37.5642135, 127.0016985),
level: 12
};
//처음 지도 표출
var map = new kakao.maps.Map(container, options);
var places = new kakao.maps.services.Places();
places.setMap(map);
//검색후 지도 표시
var mapContainer = document.getElementById('map'), // 지도를 표시할 div
mapOption = {
center: new kakao.maps.LatLng(37.5642135, 127.0016985), // 지도의 중심좌표
level: 3 // 지도의 확대 레벨
};
// 검색한 지도를 생성합니다
var map = new kakao.maps.Map(mapContainer, mapOption);
// 장소 검색 객체를 생성합니다
var ps = new kakao.maps.services.Places();
// 검색 결과 목록이나 마커를 클릭했을 때 장소명을 표출할 인포윈도우를 생성합니다
var infowindow = new kakao.maps.InfoWindow({zIndex:1});
// 키워드 검색을 요청하는 함수입니다
function searchPlaces() {
var keyword = document.getElementById('searchKeyword').value;
if (!keyword.replace(/^\s+|\s+$/g, '')) {
alert('키워드를 입력해주세요!');
return false;
}
// 장소검색 객체를 통해 키워드로 장소검색을 요청합니다
ps.keywordSearch( keyword, placesSearchCB);
}
// 장소검색이 완료됐을 때 호출되는 콜백함수 입니다
function placesSearchCB(data, status, pagination) {
if (status === kakao.maps.services.Status.OK) {
// 정상적으로 검색이 완료됐으면
// 검색 목록과 마커를 표출합니다
displayPlaces(data);
// 페이지 번호를 표출합니다
displayPagination(pagination);
} else if (status === kakao.maps.services.Status.ZERO_RESULT) {
alert('검색 결과가 존재하지 않습니다.');
return;
} else if (status === kakao.maps.services.Status.ERROR) {
alert('검색 결과 중 오류가 발생했습니다.');
return;
}
}
// 검색 결과 목록과 마커를 표출하는 함수입니다
function displayPlaces(places) {
var listEl = document.getElementById('placesList'),
menuEl = document.getElementById('menu_wrap'),
fragment = document.createDocumentFragment(),
bounds = new kakao.maps.LatLngBounds(),
listStr = '';
// 검색 결과 목록에 추가된 항목들을 제거합니다
removeAllChildNods(listEl);
// 지도에 표시되고 있는 마커를 제거합니다
removeMarker();
for ( var i=0; i<places.length; i++ ) {
// 마커를 생성하고 지도에 표시합니다
var placePosition = new kakao.maps.LatLng(places[i].y, places[i].x),
marker = addMarker(placePosition, i),
itemEl = getListItem(i, places[i]); // 검색 결과 항목 Element를 생성합니다
// 검색된 장소 위치를 기준으로 지도 범위를 재설정하기위해
// LatLngBounds 객체에 좌표를 추가합니다
bounds.extend(placePosition);
// 마커와 검색결과 항목에 mouseover 했을때
// 해당 장소에 인포윈도우에 장소명을 표시합니다
// mouseout 했을 때는 인포윈도우를 닫습니다
(function(marker, title) {
kakao.maps.event.addListener(marker, 'mouseover', function() {
displayInfowindow(marker, title);
});
kakao.maps.event.addListener(marker, 'mouseout', function() {
infowindow.close();
});
itemEl.onmouseover = function () {
displayInfowindow(marker, title);
};
itemEl.onmouseout = function () {
infowindow.close();
};
})(marker, places[i].place_name);
fragment.appendChild(itemEl);
}
// 검색결과 항목들을 검색결과 목록 Element에 추가합니다
listEl.appendChild(fragment);
menuEl.scrollTop = 0;
// 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다
map.setBounds(bounds);
}
// 검색결과 항목을 Element로 반환하는 함수입니다
function getListItem(index, places) {
var el = document.createElement('li'),
itemStr = '<span class="markerbg marker_' + (index+1) + '"></span>' +
'<div class="info">' +
' <h5>' + places.place_name + '</h5>';
if (places.road_address_name) {
itemStr += ' <span>' + places.road_address_name + '</span>' +
' <span class="jibun gray">' + places.address_name + '</span>';
} else {
itemStr += ' <span>' + places.address_name + '</span>';
}
itemStr += ' <span class="tel">' + places.phone + '</span>' +
'</div>';
el.innerHTML = itemStr;
el.className = 'item';
return el;
}
// 마커를 생성하고 지도 위에 마커를 표시하는 함수입니다
function addMarker(position, idx, title) {
var imageSrc = 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_number_blue.png', // 마커 이미지 url, 스프라이트 이미지를 씁니다
imageSize = new kakao.maps.Size(36, 37), // 마커 이미지의 크기
imgOptions = {
spriteSize : new kakao.maps.Size(36, 691), // 스프라이트 이미지의 크기
spriteOrigin : new kakao.maps.Point(0, (idx*46)+10), // 스프라이트 이미지 중 사용할 영역의 좌상단 좌표
offset: new kakao.maps.Point(13, 37) // 마커 좌표에 일치시킬 이미지 내에서의 좌표
},
markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imgOptions),
marker = new kakao.maps.Marker({
position: position, // 마커의 위치
image: markerImage
});
marker.setMap(map); // 지도 위에 마커를 표출합니다
markers.push(marker); // 배열에 생성된 마커를 추가합니다
return marker;
}
// 지도 위에 표시되고 있는 마커를 모두 제거합니다
function removeMarker() {
for ( var i = 0; i < markers.length; i++ ) {
markers[i].setMap(null);
}
markers = [];
}
// 검색결과 목록 하단에 페이지번호를 표시는 함수입니다
function displayPagination(pagination) {
var paginationEl = document.getElementById('pagination'),
fragment = document.createDocumentFragment(),
i;
// 기존에 추가된 페이지번호를 삭제합니다
while (paginationEl.hasChildNodes()) {
paginationEl.removeChild (paginationEl.lastChild);
}
for (i=1; i<=pagination.last; i++) {
var el = document.createElement('a');
el.href = "#";
el.innerHTML = i;
if (i===pagination.current) {
el.className = 'on';
} else {
el.onclick = (function(i) {
return function() {
pagination.gotoPage(i);
}
})(i);
}
fragment.appendChild(el);
}
paginationEl.appendChild(fragment);
}
// 검색결과 목록 또는 마커를 클릭했을 때 호출되는 함수입니다
// 인포윈도우에 장소명을 표시합니다
function displayInfowindow(marker, title) {
var content = '<div style="padding:5px;z-index:1;">' + title + '</div>';
infowindow.setContent(content);
infowindow.open(map, marker);
}
// 검색결과 목록의 자식 Element를 제거하는 함수입니다
function removeAllChildNods(el) {
while (el.hasChildNodes()) {
el.removeChild (el.lastChild);
}
}
//시설카운트 버튼 클릭시 지도위에 지역 마커 표시
/* var map = new kakao.maps.Map(document.getElementById('map'), { // 지도를 표시할 div
center : new kakao.maps.LatLng(36.2683, 127.6358), // 지도의 중심좌표
level : 13 // 지도의 확대 레벨
}); */
// 마커 클러스터러를 생성합니다
var clusterer = new kakao.maps.MarkerClusterer({
map: map, // 마커들을 클러스터로 관리하고 표시할 지도 객체
averageCenter: true, // 클러스터에 포함된 마커들의 평균 위치를 클러스터 마커 위치로 설정
minLevel: 10, // 클러스터 할 최소 지도 레벨
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 '10개이하';
} else if(count < 30) {
return '30개이하';
} else if(count < 50) {
return '50개이하';
} else {
return '없음';
}
}
// 데이터를 가져오기 위해 jQuery를 사용합니다
// 데이터를 가져와 마커를 생성하고 클러스터러 객체에 넘겨줍니다
function hygeraMarkers() {
//json 형태로 우리 시설을 사용하는 카운트 마커를 조회하는 쿼리를 보낸다.
$.get("/control/selectHygeraSiteList.do", function(data) {
//성공이면
// 데이터에서 좌표 값을 가지고 마커를 표시합니다
// 마커 클러스터러로 관리할 마커 객체는 생성할 때 지도 객체를 설정하지 않습니다
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);
//에러면 alert
});
}
</script>
</div>
다음은 저기 저 초록색 버튼을 클릭하면 우리 제품을 사용하고 있는 시설들을 카운트로 매겨
그룹으로 묶어 지도에 표기하는 기능을 만들려고 오픈소스를 가져와서 표기하려 했다.
예를 들면 이런 기능인데,
참조 https://apis.map.kakao.com/web/sample/chickenClusterer
마커에 텍스트로 표시하는 건 카카오의 오픈소스를 가져다가 사용하면 그만이지만
현재 우리 제품을 사용하는 시설에 위치값으로 지역을 그룹바이로 묶어서 마커에 표시하려면 해당 시설의 위도, 경도 데이터가 필요한 것이다.
그리고 원래 위도, 경도를 구하려면 좌표를 구해야하고 그 좌표도 국내 해외로 나눠진다는데..
해외는
Proj 라이브러리를 이용한 GIS 좌표변환
- TM 좌표계
- 동네예보 자료 좌표계
- GPS 측위 좌표계(WGS84)
* GCS(geographic coordinate system = cartographic CS) : 경위도 좌표계
* PCS(projected coordinate system = cartesian CS) : 직각 좌표계
를 이용하고,
국내 좌표
-gridx, gridy
좌표를 이용한다고 한다.
기상청API 사용시 좌표 (gridX, gridY) 얻는 방법
기상청API 메뉴얼 : http://www.kma.go.kr/images/weather/lifenindustry/timeseries_XML.pdf 기상청...
blog.naver.com
대충 이러한 방법들인거 같았는데... 나는 단순 한 방법을 찾다가
구글에 위도, 경도를 구할 수 있는 api 가 있어 구글지도맵 Maps JavaScript API와 지오코딩을 사용하도록 하였다.
(원래는 이거 때문에 위도경도를 통해 좌표를 구하려 했던건데 위도 경도를 활용해서 날씨api를 써보고 싶어서 같이 진행하였다.)
그래서 내 작업 순서를 나눠 보자면
1. 시설이나 지역을 검색하면 구글 api를 통해 해당 위도 , 경도의 값을 구하고.
2. 구한 위도 , 경도로 날씨 api 를 요청한다.
3. 날씨를 구현한다.
4. 추가 기능 현위치 (자바스크립트에 현위치의 위도, 경도를 구하는 함수가 있다! 참조 : https://velog.io/@lsj8367/JavaScript-%EC%A2%8C%ED%91%9C-%EC%A3%BC%EC%86%8C-%EB%B3%80%ED%99%98%EA%B3%84)
[JavaScript] GeoLocation api, 카카오 좌표 -> 주소 변환계 구현하기
GeoLocation API GeoLocation API는 navigator.geolocation 객체를 통해 사용을 할 수가 있다.
velog.io
5. 1번을 통해 얻은 시설의 위도 경도를 지역별로 묶어 카운트를 매긴다. 그 카운트로 지도에 마커표시한다.
라고 나눠 질 수 있겠다.
어째 점점 돌고 돌아 스케일이 커지는 중 같지만...

차근차근 해보도록 하자...!
먼저 , 1번을 구현하기 위해 https://console.cloud.google.com 에 내 프로젝트를 등록하고 여러가지 기본 설정을 한다. 위 과정은 검색해보면 많으니 생략하겠다!
그 후 Maps JavaScript API 와 Geocoding API 를 라이브러리에서 검색해서 api를 받고 설정해준다.
Geocoding Service | Maps JavaScript API | Google Developers
Send feedback Geocoding Service Note: Server-side libraries This page describes the client-side service available with the Maps JavaScript API. If you want to work with Google Maps web services on your server, take a look at the Node.js Client for Google M
developers.google.com
그 후 위에 사이트에 나온대로 구글의 가이드라인을 따라 코드를 작성하고 api key값을 넣어
(코드 첨부 예정)
이렇게 전송을 보내긴 하였는데
위에 에러가 발생하였다.
"Google 지도를 제대로 로드할 수 없습니다" 또는 "The Google Maps API server rejected your request" 이와 같은 에러 현상의 원인은 크게 두가지라는데
1. api키 설정에 HTTP 리퍼러 제한 설정을 안 해줬을 경우
구글 플랫폼에서 https://console.cloud.google.com
API를 클릭해 위와 같은 설정을 확인 후 아니라면 저런식으로 맞춰준다. 웹사이트 주소는 http://~.com 이런 형식인데 나같은 경우는 아직 도메인을 등록하지 않았기에 로컬 주소를 입력해뒀다.
2. 결제 계정 등록을 확인한다.
여기서 결제를 클릭해서 결제 계정이 등록되어있는 지 확인한다.
없다면 등록해준다.
나의 경우는 2번이었는데, 등록 후 지도맵은 떳지만 크롬에서 디버깅모드로 보았던 두개의 에러는 해결이 나지 않았다.
그래서 두번째 에러는 전역변수 설정과 codeAddress함수 안에 gecoder를 다시 선언해서 사용하니 잘 작동 하였고,
var geocoder;
var map;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions = {
zoom: 8,
center: latlng
}
map = new google.maps.Map(document.getElementById('map'), mapOptions);
}
function codeAddress() {
var address = document.getElementById('address').value;
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == 'OK') {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
그 다음 403 forbidden 에러는 해결이 안났었는데.
이렇게 지도는 떠있지만 403 forbidden 에러는 계속 있는 것이다.
https://kuduz.tistory.com/1092
ggmap '404 forbidden' 에러 해결하기
ggmap 패키지를 사용한 이 포스트와 이 포스트에 코드를 따라 했는데 '403 forbidden' 에러가 난다고 댓글을 쓴 분들이 계십니다. 위키피디아 한국어판은 이 에러를 "서버가 허용하지 않는 웹 페이지
kuduz.tistory.com
알고 보니 구글이 지도 자료를 공급하는 방식을 최근에 바꿔서 ggmap도 새로운 방식으로 데이터를 받아 와야 한다는 것이다.
깃허브에는 2.7 버전이 올라와 있기 때문에 이 버전을 사용하면 에러는 사라진다고 한다. 방법은 저기 블로그를 참조하면 되는데 일단 저 에러는 넘겨도 잘 작동 하기때문에 내 우선 목적을 먼저 성공 후 마지막에 해결하도록 할 것이다.
일단 본론으로 들어가서 구글 지도맵을 통해 마크업에서 나오는 현재 검색의 위도, 경도를 가져온다.
var lat;
var lon;
function codeAddress() {
var address = document.getElementById('searchKeyword').value;
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == 'OK') {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
//alert(marker.position);
lat = marker.getPosition().lat();
lon = marker.getPosition().lng();
console.log("위도 : "+ lat + ", 경도 : "+lon);
var innerHTML = `
<tr>
<td>` + address + `</td>
<td><input type="hidden" id="lat" name="lat" value="` +lat+ `"/>` + lat + `</td>
<td><input type="hidden" id="lon" name="lon" value="` +lon+ `"/>` + lon + `</td>
<td><button class="btn btn-primary wd-60 pd-0" style="height: 29.5px;" type="button" id="btnWeather" name="btnWeather" value="" onclick="weather();">날씨</button></td>
</tr>
`;
$("#positionList").html(innerHTML);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
/* html 지도 밑에 추가 */
<div class="table-responsive template-table-y">
<table class="table main-table-reference template-table word-keep-all mb-0" >
<colgroup>
<col style="width:auto">
<col style="width:auto">
<col style="width:auto">
<col style="width:10%">
</colgroup>
<thead>
<tr>
<th>도시명</th>
<th>위도</th>
<th>경도</th>
<th>날씨</th>
</tr>
</thead>
<tbody id="positionList">
<tr>
<td style="height: 50px;" colspan="4"> 조회 내역이 없습니다. </td>
</tr>
</tbody>
</table>
</div>
위도 경도는 얼럿창에 마크업의 position을 띄운 후
//alert(marker.position);
lat = marker.getPosition().lat();
lon = marker.getPosition().lng();
를 통해 가져왔다. (마크업 속성에 있어서 다행..)
/* 위도 경도를 통해 날씨 구현부분 */
function weather() {
var lat = $("#lat").val();
var lon = $("#lon").val();;
var apiURI ="http://api.openweathermap.org/data/2.5/weather?lat="+lat+"&lon="+lon+"&appid=내api키값";
$.ajax({
url: apiURI,
dataType: "json",
type: "GET",
async: "false",
success: function(resp) {
console.log(resp);
console.log("현재온도 : "+ (resp.main.temp- 273.15) );
console.log("현재습도 : "+ resp.main.humidity);
console.log("날씨 : "+ resp.weather[0].main );
console.log("상세날씨설명 : "+ resp.weather[0].description );
console.log("날씨 이미지 : "+ resp.weather[0].icon );
console.log("바람 : "+ resp.wind.speed );
console.log("나라 : "+ resp.sys.country );
console.log("도시이름 : "+ resp.name );
console.log("구름 : "+ (resp.clouds.all) +"%" );
}
})
}
그 후 히든으로 위도, 경도의 값을 담은 후 날씨 버튼을 클릭하면
그 값을 넘겨줘서 api 에 담아 보내줬다!
여기서 헷갈렸던건 날씨 api는 경도가 lon으로 넘겨줘야 하는 반면 구글의 마크업 속성엔 경도가 lng라는 점이다.
postman을 통해서 둘의 차이를 몰랐다면 계속 해맬뻔 했었다.
콘솔로 날씨가 찍히는 것을 확인했다.
이제 이걸 어떻게 ui에 표출할지 고민하면된다 ----> 작업 순서 3번까지 온 것이다!
ui를 어떻게 표출할까 고민하는 중 ...
일단 지도위에 마우스오버시 팝업 레이아웃을 띄우는 기능은 만들었는데
이걸 어떻게 연결 시킬지 고민하는 중이다.
<script type="text/javascript">
$(
function(){
$('.map').mouseover(function(e) { // 마우스 오버시 좌표를 얻고, 다음 코드를 실행한다.
$(this).mousemove(function(e) {
$('#layer #title').empty().append($(this).attr("city_name"));// layer안에있는 title의 값을 data의 wr_name 값으로 치환한다.
$('#layer #latitude').empty().append($(this).attr("lat_name")); // layer안에있는 latitude의 값을 data의 wr_name 값으로 치환한다.
$('#layer #longitude').empty().append($(this).attr("lon_name")); // layer안에있는 longitude의 값을 data의 lon_name값으로 치환한다.
var t=e.pageY-200; // 레이어를 띄울 곳 : 현재 마우스의 Y 좌표에 -200를 한값
var l=e.pageX-350; // 레이어를 띄울 곳 : 현재 마우스의 X 좌표에 -350를 한값
$('#layer').css({"top":t, "left":l,"position":"absolute","opacity":"0,8" }).show(); // 위에서 구한 좌표값으로 레이어를 띄운다.
});
});
$('.map').mouseout(function() { // 마우스 아웃시 실행한다.
$('#layer').hide(); // 레이어를 숨긴다.
});
}
);
</script>
/* html 소스 첨부 */
<!-- 지도맵 시작 -->
<div class="mg-t-35">
<div id="map" class="map" style="height: 480px;" city_name="검색한 도시명" lat_name="현재위도값" lon_name="현재경도값">
</div>
</div>
<!-- 지도맵 끝 -->
<!-- 지도맵 마우스 오버시 팝업 레이아웃 -->
<div id="layer" class="layer" style="top: 277px; left: 1212px; position: absolute; display: none;">
<div class="title">
<strong>검색이름 :</strong> <span id="title">도시명</span>
</div>
<div class="latitude">
<strong>위도 :</strong> <span id="latitude">마우스를 올려보세요</span>
</div>
<div class="longitude">
<strong>경도 :</strong> <span id="longitude">마우스를 올려보세요</span>
</div>
<div class="weather">
<strong>날씨 :</strong> <span id="weatherUi">날씨 표출 값</span>
</div>
</div>
<!-- 지도맵 마우스 오버시 팝업 레이아웃 끝 -->
날씨를 누르는게 번거로운 듯하여 로직 과정을 알았으니
검색하면 바로 해당 지역의 날씨를 마우스오버시 레이아웃에 가져오도록 바꿔봤다.
추가로 미세먼지 API랑 일주일 일기예보 API도 가져와봤다.
미세먼지는 openweathermap의 air_pollution을 사용했다. 공기오염수준을 1~5단계로 데이터를 주는데 숫자를 한글로 바꿔서 표출했다.
일기예보는 openweathermap onecall 사용했다. 오늘부터 향후 7일간의 날씨 데이터를 준다.
이제 페이지를 처음에 띄우면 나의 현위치를 구해서 기본값으로 표출되도록 하는 4번으로 넘어가보록 하겠다.
/* 현재 위치 구하기 */
function getLocation() {
if (navigator.geolocation) { // GPS를 지원하면
navigator.geolocation.getCurrentPosition(function(position) {
console.log(position.coords.latitude + ' ' + position.coords.longitude);
lat = position.coords.latitude; //전역변수에 구한 위도값을 담는다.
lon = position.coords.longitude; //전역변수에 구한 경도값을 담는다.
console.log("현재 lat : " + lat + ',' + "현재 lon : "+ lon);
initialize(lat, lon); /* initialize함수를 콜백 시키면서 변수를 보내준다-> 현위치 지도맵 함수 */
}, function(error) {
console.error(error);
}, {
enableHighAccuracy: false,
maximumAge: 0,
timeout: Infinity
});
} else {
alert('GPS를 지원하지 않습니다');
}
}
HTML5버전 웹에서 GPS기능을 제공 해준다. 자바스크립트에 window.navigator 객체 안에 GPS에 관한 정보가 들어있다.
그리고 나는 자바스크립트의 콜백함수의 개념을 모른채
함수안에 매개변수를 넣어 함수를 부르면서 사용하고 있었는데,
이러한 함수를 콜백함수라고 하나보다.
콜백함수는 자바스크립트에서 매우 중요한 개념이니 나중에 자바스크립트 카테고리에 따로 작성하도록 하겠다.
GPS 기능을 사용한 getLocation 함수를 페이지 로드시 바로 실행하게 만들면
이러한 권한 요청이 뜬다. 허용을 누르면 현재위치를 받아서 지도맵 초기화 함수 initialize을 실행하도록 하였다.
아래는 카카오 지도맵에 현재위치기능과 카카오의 마커표시를 한 소스이다.
나는 자바스크립트를 함수형 방식으로 많이 선언해서 내 방식대로 작성하였다.
/* 현재 위치 구하기 */
function getLocation() {
if (navigator.geolocation) { // GPS를 지원하면
navigator.geolocation.getCurrentPosition(function(position) {
console.log(position.coords.latitude + ' ' + position.coords.longitude);
var lat = position.coords.latitude;
var lon = position.coords.longitude;
console.log("현재 lat : " + lat + ',' + "현재 lon : "+ lon);
var locPosition = new kakao.maps.LatLng(lat, lon); // 마커가 표시될 위치를 geolocation으로 얻어온 좌표로 생성합니다
var message = '<div style="padding:5px;">여기에 계신가요?!</div>'; // 인포윈도우에 표시될 내용입니다
// 마커와 인포윈도우를 표시합니다
displayMarker(locPosition, message);
}, function(error) {
console.error(error);
}, {
enableHighAccuracy: false,
maximumAge: 0,
timeout: Infinity
});
} else {
alert('GPS를 지원하지 않습니다');
}
}
//지도에 마커와 인포윈도우를 표시하는 함수입니다
function displayMarker(locPosition, message) {
// 마커를 생성합니다
var marker = new kakao.maps.Marker({
map: map,
position: locPosition
});
var iwContent = message, // 인포윈도우에 표시할 내용
iwRemoveable = true;
// 인포윈도우를 생성합니다
var infowindow = new kakao.maps.InfoWindow({
content : iwContent,
removable : iwRemoveable
});
// 인포윈도우를 마커위에 표시합니다
infowindow.open(map, marker);
// 지도 중심좌표를 접속위치로 변경합니다
map.setCenter(locPosition);
}
웹에서 작동되는건 확인했는데 모바일에서도 작동되는지는 확인해봐야할 것 같다.
----> (추가 작성 내용) https 에서 구글 지도맵 에러 발생
Mixed content 문제 해결(https 사이트에서 http 사이트 요청 시 발생하는 보안 문제) (tistory.com)
Mixed content 문제 해결(https 사이트에서 http 사이트 요청 시 발생하는 보안 문제)
https 사이트에서 ajax를 사용해서 비동기로 http 사이트에 request를 요청해서 문제가 발생 했습니다. 암호화된 HTTPS 기반의 사이트에서 암호화되지 않은 HTTP 사이트에 요청을 보내서 Mixed content 에러
wellsw.tistory.com
헤더에 이 블로그에 작성된대로 <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
를 추가하니까 서버 반영 후에도 403 forbidden 에러나 또 다른 에러가 있었는데 하튼 모든 에러가 없어졌다.
구글 지도맵의 https 보안문제는 이렇게 하니 없어졌고,
서버 반영후 만일 http 에서 현재 위치(GPS) 문제는 html 파일에 날씨 팝업 만들기 (tistory.com) 를 참조하여 이러한 문제가 발생하는데 이 문제는 보류하였다.
----> 5번
그리고 날씨 검색후 팝업 레이어를 보면 검색한 타임존을 확인 할 수 있는데 어쩌면 날씨를 통해 지역 구분이 가능할 것 같다.
그렇다면 해당 지역에 몇개의 시설이 우리제품을 사용하는지도 확인 할 수 있을 것 이다.
(해당기능을 완성하게 되면 추가로 작성하겠다.)
참고 : 필자도 아직 공부 중이며 짧은 지식으로 쓴 글임을 유의하며 읽어주시길 바랍니다. 만일, 잘못된 정보나 지식이 있다면 알려주시길 바랍니다.
'프론트 > ajax 및 API' 카테고리의 다른 글
[Tools] API postman (0) | 2022.02.18 |
---|---|
[API] SNS 로그인 API 사용하기 (0) | 2022.02.17 |
[API] API 개념 (0) | 2022.02.17 |