Download presentation
Presentation is loading. Please wait.
Published byRidwan Santoso Modified 6년 전
1
위치기반서비스 서버 만들기 12장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
○ 본 강의 자료는 이지스퍼블리싱에서 제공하는 강의 교안입니다. ○ 본 강의 교안은 아래 출판 서적의 내용을 기준으로 구성되었습니다. 또한 다수의 기타 서적이나 사이트를 참조하였습니다. 레퍼런스를 참조하십시오. 2017, 정재곤, “Do it! Node.js 프로그래밍 (개정판)”, 이지스퍼블리싱 - 강의 교안에 사용된 화면 캡처나 실습 자료의 경우에는 문서 업데이트에 따라 변경될 수 있습니다.
2
위치를 이용하는 서버를 어떻게 만드는지 알아보자.
강의 주제 및 목차 강의 주제 위치를 이용하는 서버를 어떻게 만드는지 알아보자. 목 차 1 커피숍 위치 저장하기 2 가장 가까운 커피숍 찾기 3 영역 안의 커피숍 찾기 4 반경 안의 커피숍 찾기 5 지도에 커피숍의 위치 표시하기
3
1. 커피숍 위치 저장하기 난이도 소요시간 20분
4
커피숍 위치 정보 다루기 사용자의 위치 정보를 사용해 다양한 부가 정보를 제공 커피숍 찾기 기능을 만드는 과정 기 능 설명
커피숍의 위치 정보 확인 특정 지역의 커피숍 이름이나 전화번호, 위치 등의 정보를 확인해야 합니다. 그중에 커피숍의 위치 정보는 경위도 좌표로 알고 있어야 합니다. 커피숍의 위치 정보 저장 위치 정보를 포함한 커피숍 정보를 서버에 저장해야 합니다. 서버의 데이터베이스에 저장합니다. 커피숍을 위치로 조회 가까운 커피숍을 경위도 좌표로 조회해야 합니다.
5
데이터베이스에 저장하는 방식 near, within, within(circle)과 같은 기능 제공
6
커피숍 스키마 만들기 데이터베이스 스키마 추가 – coffeeshop_schema.js var Schema = { };
Schema.createSchema = function(mongoose) { var CoffeeShopSchema = mongoose.Schema({ name : {type : String, index : 'hashed', 'default' : ''}, address : {type : String, 'default' : ''}, tel : {type : String, 'default' : ''}, geometry : { 'type' : {type : String, 'default' : "Point"}, coordinates : [{type : "Number"}] }, created_at : {type : Date, index : {unique : false}, 'default' : Date.now}, updated_at : {type : Date, index : {unique : false}, 'default' : Date.now} });
7
커피숍 스키마의 속성과 공간 인덱싱 위치 좌표는 geometry 속성에 넣고 공간 인덱싱을 해야 성능에 문제가 없음 …….
CoffeeShopSchema.index({geometry : '2dsphere'});
8
메소드 추가하고 설정에 정보 추가 메소드는 findAll 메소드만 추가하고 새로 만든 스키마 정보를 config.js 파일에 추가 CoffeeShopSchema.static('findAll', function(callback) { return this.find({ }, callback); }); module.exports = { server_port : 3000, db_url : 'mongodb://localhost:27017/local', db_schemas : [ {file : './user_schema', collection : 'users6', schemaName : 'UserSchema', modelName : 'UserModel'}, {file : './coffeeshop_schema', collection : 'coffeeshop', schemaName : 'CoffeeShopSchema', modelName : 'CoffeeShopModel'} ],
9
커피숍 데이터 추가 함수 작성 라우팅 함수들을 만들기 위해 coffeeshop.js 파일을 만들고 add 함수 추가
var add = function(req, res) { console.log('coffeeshop 모듈 안에 있는 add 호출됨.'); var paramName = req.param('name'); var paramAddress = req.param('address'); var paramTel = req.param('tel'); var paramLongitude = req.param('longitude'); var paramLatitude = req.param('latitude'); var database = req.app.get('database'); if (database.db) { addCoffeeShop(database, paramName, paramAddress, paramTel, paramLongitude, paramLatitude, function(err, result) { if (err) { ….. }
10
커피숍 데이터 추가 함수 작성 라우팅 함수들을 만들기 위해 coffeeshop.js 파일을 만들고 add 함수 추가
if (result) { console.dir(result); res.writeHead('200', {'Content-Type' : 'text/html;charset=utf8'}); res.write('<h2>커피숍 추가 성공</h2>'); res.end(); } else { res.write('<h2>커피숍 추가 실패</h2>'); } }); res.write('<h2>데이터베이스 연결 실패</h2>'); };
11
데이터베이스에 추가하는 함수 작성 데이터베이스에 커피숍 데이터를 추가하는 addcoffeeShop 함수 작성
var addCoffeeShop = function(database, name, address, tel, longitude, latitude, callback) { console.log('addCoffeeShop 호출됨.'); var coffeeshop = new database.CoffeeShopModel({name : name, address : address, tel : tel, geometry : { type : 'Point', coordinates : [longitude, latitude] } ); coffeeshop.save(function(err) { if (err) { callback(err, null); return; console.log("커피숍 데이터 추가함."); callback(null, coffeeshop);
12
커피숍 리스트 조회 함수 추가 데이터베이스에서 커피숍 리스트 조회하는 함수 추가
var list = function(req, res) { console.log('coffeeshop 모듈 안에 있는 list 호출됨.'); var database = req.app.get('database'); if (database.db) { database.CoffeeShopModel.findAll(function(err, results) { if (err) { ….. } if (results) { console.dir(results); res.writeHead('200', {'Content-Type' : 'text/html;charset=utf8'}); res.write('<h2>커피숍 리스트</h2>'); res.write('<div><ul>'); for (var i = 0; i < results.length; i++) { var curName = results[i]._doc.name; var curLongitude = results[i]._doc.geometry.coordinates[0]; var curLatitude = results[i]._doc.geometry.coordinates[1]; 경도 좌표 : results[i]._doc.geometry.coordinates[0 위도 좌표 : results[i]._doc.geometry.coordinates[1]
13
라우팅 설정 방식 라우팅 함수 정보 등록 route_info : [
{file : './coffeeshop', path : '/process/addcoffeeshop', method : 'add', type : 'post'} ,{file : './coffeeshop', path : '/process/listcoffeeshop', method : 'list', type : 'post'} ],
14
웹페이지 작성 커피숍 정보를 추가하는 웹페이지 작성
<form method="post" action="/process/addcoffeeshop"> <table> <tr> <td><label>이름</label></td> <td><input type="text" name="name" value="스타벅스 삼성역점" /></td> </tr> <td><label>주소</label></td> <td><input type="text" name="address" value="서울특별시 강남구 테헤란로103길 9 제일빌딩" /></td> <td><label>경도</label></td> <td><input type="text" name="longitude" value=" " /></td> <td><label>위도</label></td> <td><input type="text" name="latitude" value=" " /></td>
15
지도에서 경위도 좌표 확인 경위도 좌표를 확인할 수 있는 사이트 있음 ▶
16
웹페이지 작성 커피숍 리스트를 조회하는 웹페이지 작성 <h1>커피숍 리스트</h1> <br>
<form method="post" action="/process/listcoffeeshop"> <table> <tr> <td><label>아래 [전송] 버튼을 누르세요.</label></td> </tr> </table> <input type="submit" value="전송" name="" /> </form>
17
커피숍 추가 후 데이터 확인 로그 및 데이터베이스 확인
▶
18
2. 가장 가까운 커피숍 찾기 난이도 소요시간 20분
19
커피숍을 위치로 찾는 방법 가장 가까운 커피숍 찾기, 영역으로 커피숍 찾기, 반경으로 커피숍 찾기
20
스키마에 메소드 추가 가장 가까운 커피숍을 찾을 수 있는 findNear 메소드 추가 // 가장 가까운 커피숍 조회
CoffeeShopSchema.static('findNear', function(longitude, latitude, maxDistance, callback) { console.log('CoffeeShopSchema의 findNear 호출됨.'); this.find().where('geometry').near( {center : {type : 'Point', coordinates : [parseFloat(longitude), parseFloat(latitude)] }, maxDistance : maxDistance }).limit(1).exec(callback); }); ……. find().where(속성 이름).near(조회 조건)
21
라우팅 함수 추가 가장 가까운 커피숍을 찾기 위한 라우팅 함수 추가
var findNear = function(req, res) { console.log('coffeeshop 모듈 안에 있는 findNear 호출됨.'); var paramLongitude = req.param('longitude'); var paramLatitude = req.param('latitude'); var maxDistance = 1000; var database = req.app.get('database'); if (database.db) { database.CoffeeShopModel.findNear(paramLongitude, paramLatitude, maxDistance, function(err, results) { if (err) { ….. } if (results) { console.dir(results); res.writeHead('200', {'Content-Type' : 'text/html;charset=utf8'}); res.write('<h2>가까운 커피숍</h2>'); res.write('<div><ul>');
22
라우팅 함수 추가 가장 가까운 커피숍을 찾기 위한 라우팅 함수 추가
for (var i = 0; i < results.length; i++) { var curName = results[i]._doc.name; var curAddress = results[i]._doc.address; var curTel = results[i]._doc.tel; var curLongitude = results[i]._doc.geometry.coordinates[0]; var curLatitude = results[i]._doc.geometry.coordinates[1]; res.write(' <li>#' + i + ' : ' + curName + ', ' + curAddress + ', ' + curTel + ', ' + curLongitude + ', ' + curLatitude + '</li>'); } res.write('</ul></div>'); res.end(); } else { res.writeHead('200', {'Content-Type' : 'text/html;charset=utf8'}); res.write('<h2>가까운 커피숍 조회 실패</h2>');
23
웹페이지 작성 가까운 커피숍 검색 요청을 위한 웹페이지 작성 <p>삼성역 3번 출구 버스 정류장</p>
<br> <form method="post" action="/process/nearcoffeeshop"> <table> <tr> <td><label>경도</label></td> <td><input type="text" name="longitude" value=" " /></td> </tr> <td><label>위도</label></td> <td><input type="text" name="latitude" value=" " /></td> </table> <input type="submit" value="전송" name="" /> </form>
24
설정에 등록 후 확인 config.js 파일에 라우팅 함수 등록 후 확인 route_info : [
{file : './coffeeshop', path : '/process/addcoffeeshop', method : 'add', type : 'post'} ,{file : './coffeeshop', path : '/process/listcoffeeshop', method : 'list', type : 'post'} ,{file : './coffeeshop', path : '/process/nearcoffeeshop', method : 'findNear', type : 'post'} ], ▶
25
3. 영역 안의 커피숍 찾기 난이도 소요시간 30분
26
스키마에 메소드 추가 앞에서 했던 과정과 같은 과정으로 진행 find().where(속성 이름).within(조회 조건)
// 일정 범위 안의 커피숍 조회 CoffeeShopSchema.static('findWithin', function(topleft_longitude, topleft_latitude, bottomright_longitude, bottomright_latitude, callback) { console.log('CoffeeShopSchema의 findWithin 호출됨.'); this.find().where('geometry').within( {box : [[parseFloat(topleft_longitude), parseFloat(topleft_latitude)], [parseFloat(bottomright_longitude), parseFloat(bottomright_latitude)]] }).exec(callback); }); find().where(속성 이름).within(조회 조건)
27
라우팅 함수 추가 커피숍 검색을 위한 라우팅 함수 추가 var findWithin = function(req, res) {
console.log('coffeeshop 모듈 안에 있는 findWithin 호출됨.'); var paramTopLeftLongitude = req.param('topleft_longitude'); var paramTopLeftLatitude = req.param('topleft_latitude'); var paramBottomRightLongitude = req.param('bottomright_longitude'); var paramBottomRightLatitude = req.param('bottomright_latitude'); var database = req.app.get('database'); if (database.db) { database.CoffeeShopModel.findWithin(paramTopLeftLongitude, paramTopLeftLatitude, paramBottomRightLongitude, paramBottomRightLatitude, function(err, results) { if (err) { ….. } ……. module.exports.findWithin = findWithin;
28
웹 페이지 작성 검색 요청을 위한 웹페이지 작성 <p>삼성역 3번 출구와 4번 출구 부근의 영역 (사각형 박스)</p> <br> <form method="post" action="/process/withincoffeeshop"> <table> <tr> <td><label>왼쪽 윗부분의 경도</label></td> <td><input type="text" name="topleft_longitude" value=" " /></td> </tr> <td><label>왼쪽 윗부분의 위도</label></td> <td><input type="text" name="topleft_latitude" value=" " /></td> <td><label>오른쪽 아랫부분의 경도</label></td> <td><input type="text" name="bottomright_longitude" value=" " /></td>
29
설정에 추가 후 확인 라우팅 함수를 config.js 파일에 추가 후 기능 동작 확인 route_info : [
{file : './coffeeshop', path : '/process/addcoffeeshop', method : 'add', type : 'post'} ,{file : './coffeeshop', path : '/process/listcoffeeshop', method : 'list', type : 'post'} ,{file : './coffeeshop', path : '/process/nearcoffeeshop', method : 'findNear', type : 'post'} ,{file : './coffeeshop', path : '/process/withincoffeeshop', method : 'findWithin', type : 'post'} ], ……. ▶
30
4. 반경 안의 커피숍 찾기 난이도 소요시간 30분
31
스키마에 메소드 추가 앞에서 했던 과정과 같은 과정으로 진행 // 일정 반경 안의 커피숍 조회
CoffeeShopSchema.static('findCircle', function(center_longitude, center_latitude, radius, callback) { console.log('CoffeeShopSchema의 findCircle 호출됨.'); // change radian : 1/6371 -> 1km this.find().where('geometry').within( {center : [parseFloat(center_longitude), parseFloat(center_latitude)], radius : parseFloat(radius/ ), unique : true, spherical : true }).exec(callback); });
32
라우팅 함수 추가 커피숍 검색을 위한 라우팅 함수 추가 var findCircle = function(req, res) {
console.log('coffeeshop 모듈 안에 있는 findCircle 호출됨.'); var paramCenterLongitude = req.param('center_longitude'); var paramCenterLatitude = req.param('center_latitude'); var paramRadius = req.param('radius'); var database = req.app.get('database'); if (database.db) { database.CoffeeShopModel.findCircle(paramCenterLongitude, paramCenterLatitude, paramRadius, function(err, results) { if (err) { ….. } ……. module.exports.findCircle = findCircle;
33
웹 페이지 작성 검색 요청을 위한 웹페이지 작성 <p>삼성역 3번 출구 버스 정류장 반경 100m (원)</p> <br> <form method="post" action="/process/circlecoffeeshop"> <table> <tr> <td><label>중심점 경도</label></td> <td><input type="text" name="center_longitude" value=" " /></td> </tr> <td><label>중심점 위도</label></td> <td><input type="text" name="center_latitude" value=" " /></td> <td><label>반경</label></td> <td><input type="text" name="radius" value="100" /></td> </table>
34
설정에 추가 후 확인 라우팅 함수를 config.js 파일에 추가 후 기능 동작 확인 route_info : [ …….
,{file : './coffeeshop', path : '/process/withincoffeeshop', method : 'findWithin', type : 'post'} ,{file : './coffeeshop', path : '/process/circlecoffeeshop', method : 'findCircle', type : 'post'} ], ▶
35
5. 지도에 커피숍의 위치 표시하기 난이도 소요시간 30분
36
구글맵으로 내 위치 표시 내 위치를 표시할 수 있음 <!DOCTYPE html> <html>
<head> <meta charset="UTF-8"> <meta name="viewport" id="viewport" content="width=device-width, height=device-height, initial-scale=1“ > <title>구글맵 1</title> <style> * { margin: 0; padding: 0; } … <body onload="onLoad()"> <p>구글맵으로 내 위치 표시하기</p> <div id="map"></div> </body>
37
자바스크립트 코드 추가 구글맵 라이브러리 로딩하여 사용
<script src=" <script> function onLoad() { initMap(); } var map; var centerLocation = {lat: , lng: }; function initMap() { map = new google.maps.Map(document.getElementById('map'), { center: centerLocation, zoom: 17 }); var marker = new google.maps.Marker({ position:centerLocation, icon:'mylocation.png', animation:google.maps.Animation.BOUNCE marker.setMap(map);
38
구글맵 라이브러리 라이브러리 사용하고 API Key 발급받아 등록해야 함
속성 설명 center 지도가 어느 지역을 보여줄 것인지를 좌표로 지정합니다. 자바스크립트 객체 안에 lat와 lng 속성으로 좌표 값을 넣어줍니다. 예) {lat: , lng: } zoom 지도 확대 수준을 지정합니다. 구글맵은 이미지를 받아오는 방식이기 때문에 확대 수준(zoom level)에 따라 서버에 이미지가 만들어져 있습니다. 값이 클수록 더 자세한 지도 이미지를 받아오게 됩니다.
39
내 위치 표시 지도를 띄우면 내 위치가 표시됨 ▶
40
가장 가까운 커피숍 찾아 보여주기 웹페이지 작성
<form method="post" action="/process/nearcoffeeshop2"> <table> <tr> <td><label>경도</label></td> <td><input type="text" name="longitude" value=" " ></td> </tr> <td><label>위도</label></td> <td><input type="text" name="latitude" value=" " ></td> </table> <input type="submit" value="전송" name="" > </form>
41
새로운 라우팅 함수 만들고 등록 findNear2 함수 만들어 등록 if (database.db) {
database.CoffeeShopModel.findNear(paramLongitude, paramLatitude, maxDistance, function(err, results) { if (err) { ….. } if (results) { console.dir(results); if (results.length > 0) { res.render('findnear.ejs', {result: results[0]._doc, paramLatitude: paramLatitude, paramLongitude: paramLongitude}); } else { res.writeHead('200', {'Content-Type':'text/html;charset=utf8'}); res.write('<h2>가까운 커피숍 데이터가 없습니다.</h2>'); res.end(); }
42
템플레이트 파일 작성 라우팅 함수에서 사용하는 findnear.ejs 파일 작성 <script>
function onLoad() { initMap(); } var map; var centerLocation = {lat: <%= paramLatitude %>, lng: <%= paramLongitude %>}; var coffeeLocation = {lat: <%= result.geometry.coordinates[1] %>, lng: <%= result.geometry.coordinates[0] %>}; function initMap() { map = new google.maps.Map(document.getElementById('map'), { center: centerLocation, zoom: 17 });
43
템플레이트 파일 작성 라우팅 함수에서 사용하는 findnear.ejs 파일 작성
var myMarker = new google.maps.Marker({ position:centerLocation, icon:'/public/mylocation.png', animation:google.maps.Animation.BOUNCE }); myMarker.setMap(map); var coffeeMarker = new google.maps.Marker({ position:coffeeLocation, icon:'/public/coffee.png' coffeeMarker.setMap(map); } </script>
44
지도에 표시되는 결과 확인 요청 후 응답으로 지도가 표시되는지 확인
▶
45
일정 범위 안의 커피숍 검색 이전 과정과 마찬가지로 진행 뷰 엔진으로 응답 문서 만들어지도록 구성
if (results.length > 0) { res.render('findwithin.ejs', {result: results[0]._doc, paramLongitude: paramLongitude, paramLatitude: paramLatitude, paramTopLeftLongitude: paramTopLeftLongitude, paramTopLeftLatitude: paramTopLeftLatitude, paramBottomRightLongitude: paramBottomRightLongitude, paramBottomRightLatitude: paramBottomRightLatitude});
46
템플레이트 파일 작성 라우팅 함수에서 사용하는 findwithin.ejs 파일 작성 // 사각형 검색 영역을 위한 좌표
var coords =new google.maps.LatLngBounds( {lat:<%= paramTopLeftLatitude %>, lng:<%= paramTopLeftLongitude %>}, {lat:<%= paramBottomRightLatitude %>, lng:<%= paramBottomRightLongitude %>} ); …. // 검색하려는 영역 표시 var rectangle = new google.maps.Rectangle({ bounds:coords, strokeColor:"#0000FF", strokeOpacity:0.8, strokeWeight:2, fillColor:"#0000FF", fillOpacity:0.4 }); rectangle.setMap(map);
47
지도에 표시되는 결과 확인 요청 후 응답으로 지도가 표시되는지 확인
▶
48
참고 문헌 [ References] 기본 서적
2017, 정재곤, “Do it! Node.js 프로그래밍 (개정판)”, 이지스퍼블리싱 Node.js Site
Similar presentations