본문 바로가기
  • 실행력이 모든걸 결정한다
OpenAPI/Javascript API

[OpenAPI] 네이버 지도 API(4) - 데이터베이스 연동

by 김코더 김주역 2021. 8. 13.
반응형

지난 포스팅에서는 다음과 같이 마커와 정보창을 손수 추가해줬다.

https://kimcoder.tistory.com/351

 

저번 예제에서는 마커를 2개만 썼기 때문에 큰 문제는 없었다. 그러나 나중에 마커의 수가 매우 많아지면, 코드의 수도 매우 길어지고 그만큼 유지 보수도 매우 힘들어질 것이다.

 

즉, 우리는 DB에서 데이터를 가져오는 기능을 수행하는 php파일을 작성하고,

javascript의 ajax를 이용해서 해당 php파일에 접근할 것이다.

 

 

1. DB 확인 (Mysql)

Mysql에 home테이블을 생성하고, (이름, 위도, 경도) 데이터 쌍을 가지는 레코드를 2개 추가했다.

 

(phpMyAdmin 사용법)

https://kimcoder.tistory.com/9

 

서버 호스팅 구매없이 DB외부접근 허용하기

필자가 몇 십 시간 삽을 팠던 내용이지만 여러분들은 이걸 보고 한 번 만에 성공했으면 좋겠다 Cafe24에서 웹호스팅서비스의 관리 주체는 Cafe24지만, (가상)서버 호스팅은 관리자 계정이 제공되어

kimcoder.tistory.com

 

 

 

2. Javascript Ajax 사용

1) Cross Domain 문제 ★

Ajax에서는 Cross Domain 문제가 발생한다.

Cross Domain 문제에 대해 간략하게 설명하자면, 동일 출처 정책(Same Origin Policy)에 의해 다른 출처에 요청하는 것을 보안 문제로 간주하고 이를 차단하는 것이다.

출처가 같아야 한다는 것은 프로토콜, 호스트, 포트 넘버가 모두 같아야 한다는 것이다.

필자는 Cross Domain 문제를 우회하기 위해 jsonp 형태의 데이터를 반환하는 방법을 사용했다.

 

 

2) jsonp의 사용

(1) Javascript 측의 요청 (jQuery 사용)

ajax의 dataType을 "jsonp"로 설정하고, jsonp 속성은 콜백 함수의 이름으로 설정하면 된다.

$(function(){
    $.ajax({
        url : "http://localhost/jsdbtest/test.php",
        dataType : "jsonp",
        jsonp : "callback",
    });
});

function callback(data) {
    ...
}

 

callback 함수 내용을 포함한 전체 소스 코드는 본 포스팅의 마지막에 첨부했다.

 

(2) PHP 측의 응답

jsonp 형식으로 반환하는 서버에서는 단순히 json 형태로 반환해서는 안 되고, 다음과 같이 javascript 측에서 요청(약속)한 이름으로 된 콜백 함수에 JSON 객체를 담아 반환해야 한다.

echo callback([JSON 형식]);

 

바로 뒤에서, 해당 콜백 함수를 반환하는 php파일을 작성할 것이다.

 

 

 

3. PHP 파일 생성

1) 저장 위치

필자의 웹서버 안에 htdocs/jsdbtest/test.php 경로로 저장했다.

 

 

2) JSON 설계 방식

 

 

3) PHP 소스 코드

주석 참고. 추가 설명 필요시 댓글로 질문 바람.

<?php
header("Content-Type:text/html;charset=utf-8"); // 한글 깨짐 방지

// DB 정보 설정
$mysql_hostname = "localhost";
$mysql_username = "root";
$mysql_password = "비밀번호";
$mysql_database = "mydb";

// DB 연결
$conn = new mysqli($mysql_hostname, $mysql_username, $mysql_password, $mysql_database);


// DB 연결 오류 예외 처리
if(mysqli_connect_error($conn)){
	echo mysqli_connect_error();
	exit();
}

// DB에서 데이터를 가져오는 과정에서의 한글 깨짐 방지
mysqli_query($conn, "set session character_set_connection=utf8;");
mysqli_query($conn, "set session character_set_results=utf8;");
mysqli_query($conn, "set session character_set_client=utf8;");

$sql = "select * from home";
$result = mysqli_query($conn, $sql);
$count = 0;
$num_rows = mysqli_num_rows($result);
$members = array();
while($row = mysqli_fetch_array($result)){
    $member = array("name" => $row['name'], "lat" => $row['lat'], "lng" => $row['lng']);  
    array_push($members, $member);
}
$jsondata['result'] = $members;

// json_encode($jsondata)를 사용 시 한글이 깨짐 문제 해결
// php버전 5.4미만 한글 변환 함수 han, to_han 출처 : https://ittravelkr.tistory.com/30
function han ($s) { return reset(json_decode('{"s":"'.$s.'"}')); } 
function to_han ($str) { return preg_replace('/(\\\u[a-f0-9]+)+/e','han("$0")',$str); } 

// php버전 5.4이상은 json_encode($jsondata, JSON_UNESCAPED_UNICODE); 사용
$output =  to_han (json_encode($jsondata));

// jsonp 형태의 응답
echo "callback(" . $output . ")";

?>

 

 

 

4. 전체 소스 코드

추가 설명 필요시 댓글로 질문 바람.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
    <title>집</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript" src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=pci..."></script>
</head>
<body>
    <div id="map" style="width:100%;height:100vh;margin:0 auto;"></div>

<script>
map = new naver.maps.Map('map', {
    center: new naver.maps.LatLng(36.31175, 127.3754709),
    zoom: 13
});

var markers = [];
var infowindows = [];

$(function(){
    $.ajax({
        url : "http://localhost/jsdbtest/test.php",
        dataType : "jsonp",
        jsonp : "callback",
    });
});

function callback(data) {
    for(let i=0; i<data.result.length; i++){
        markers.push(new naver.maps.Marker({
            map: map,
            position: new naver.maps.LatLng(parseFloat(data.result[i].lat), parseFloat(data.result[i].lng))
        }));
        infowindows.push(new naver.maps.InfoWindow({
            content: [
                '<div class="iw_inner">',
                '   <h3>',data.result[i].name,'(이)네 집</h3>',
                '</div>'
            ].join(''),
            zIndex: 10
        }));
    }
    for(let i=0; i<markers.length; i++){
        naver.maps.Event.addListener(markers[i], "click", function(e) {
            if (infowindows[i].getMap()) {
                infowindows[i].close();
            } else {
                infowindows[i].open(map, markers[i]);
            }
        });
    }
    infowindows[0].open(map, markers[0]);
}

</script>
</body>
</html>

 

 

 

5. 실행 결과

반응형

댓글