2022.12.14 - [정보기술] - (1) 구글 지도 API – 지도 만들기
2022.12.14 - [정보기술] - (2) 구글 지도 API - 단일 마커 표시하기
2022.12.14 - [정보기술] - (3) 구글 지도 API - 다중 마커 표시하기
2022.12.14 - [정보기술] - (4) 구글 지도 API - 정보창 표시하기
2022.12.14 - [정보기술] - (5) 구글 지도 API - 자동완성주소 검색하기
2022.12.14 - [정보기술] - (6) 번외 - 자동완성주소 검색에 관하여
2022.12.14 - [정보기술] - (7) 구글 지도 API - 특정 주소의 좌표 확인하기
2022.12.14 - [정보기술] - (8) 구글 지도 API - 좌표 DB 등록하기
2022.12.14 - [정보기술] - (9) 구글 지도 API - 검색 인터페이스 구현
2022.12.14 - [정보기술] - (10) 번외 - 검색지점 기준 반경거리 계산 (하버사인 공식)
2022.12.14 - [정보기술] - (11) 구글 지도 API - 좌표 DB 불러오기 (xml 이용)
2022.12.14 - [정보기술] - (12) 구글 지도 API - 위치기반 서비스 제공 (끝)
다음은 특정 지점의 좌표 DB를 등록하는 방법입니다. 먼저 정보전달을 목적으로 한 일반적인 플랫폼 웹 서비스의 흐름을 살펴 봅시다.
먼저 위치기반 서비스를 제공하는 플랫폼 서비스가 있다고 합시다. 그리고 광고를 통해 요리학원 세미나를 알리고 싶은 개인 사업자가 있다고 가정합시다. 이 개인 사업자는 광고를 대행해줄 플랫폼을 발견하고 회원가입을 합니다. 그리고 세미나 등록을 하기 위해 강의정보, 강의시간, 비용 등을 작성하여 게시글을 올립니다.
이후 요리학원 세미나에 관심있는 소비자는 평상시에 이런 정보가 올라오는 플랫폼웹에 접속하여 위치정보 검색을 통해 특정지역 근처의 요리학원 세미나를 검색합니다. 최종적으로 여러개의 세미나 중에 마음에 드는 세미나를 고르고 결제 이후 예약을 진행합니다.
이러한 과정을 이제 웹개발자의 관점에서 바라보도록 합시다.
본 포스팅의 제목이 “좌표 DB 등록하기”니까 위치기반 정보 제공자에게 제공될 웹서비스가 필요합니다.
그리고 저희들이 익히 여러 다양한 웹 서비스에서 경험했던 것처럼 등록하고자 하는 세미나에 대한 다양한 정보와 자동완성검색기능을 통한 위치 정보를 입력해줄 기능이 필요 하겠네요
필요한 기능을 정리해보자면
(1) 게시글 작성/등록하기
(2) 첨부 파일 올리기 (선택)
(3) 특정위치 정보 검색/등록하기
크게 세 가지로 나눌 수가 있겠네요.
게시글 작성/등록하기와 첨부 파일 올리기는 저희가 익히 알고 있는 cos.jar 라이브러리와 multipart request 등이 필요합니다. 관련 정보는 웹검색을 통해 비교적 쉽게 얻을 수 있으니 본 포스팅에서는 생략하겠습니다.
특정 위치 검색 및 위도/경도 좌표의 획득은 이전 포스팅에 작성하였으니 참고하시기 바랍니다.
해당 스크립트는 실제 서비스에 적용하려고 할 때, 게시글 작성하기나 세미나 등록하기 라는 jsp 페이지가 있으면 본문의 적절한 위치에 삽입하여 활용하시면 되겠습니다. 게시글 작성하기는 자바 클래스나 컨트롤러, 서블릿 등을 이용하는 것이 스마트한 방법이지만 jsp와 스크립틀릿(scriptlet)만을 이용하여도 충분히 구현할 수 있습니다.
이 때 정보를 받는 입력부(form-submit 사용)와 DB에 등록하기 위한 두 개의 jsp가 필요합니다. 편의성 register.jsp와 write.jsp로 가정하겠습니다.
먼저 등록부인 register.jsp의 스크립트 입니다.
이전 포스팅인 (7) 구글 지도 API – 특정 주소의 좌표 확인하기와 동일합니다만 약간의 차이라면 양식을 제출하기 위한 form-submit이 포함되었습니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Place Autocomplete</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 80%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#description {
font-family: Roboto;
font-size: 15px;
font-weight: 300;
}
#infowindow-content .title {
font-weight: bold;
}
#infowindow-content {
display: none;
}
#map #infowindow-content {
display: inline;
}
.pac-card {
margin: 10px 10px 0 0;
border-radius: 2px 0 0 2px;
box-sizing: border-box;
-moz-box-sizing: border-box;
outline: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
background-color: #fff;
font-family: Roboto;
}
#pac-container {
padding-bottom: 12px;
margin-right: 12px;
}
.pac-controls {
display: inline-block;
padding: 5px 11px;
}
.pac-controls label {
font-family: Roboto;
font-size: 13px;
font-weight: 300;
}
#pac-input {
background-color: #fff;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
margin-left: 12px;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 400px;
}
#pac-input:focus {
border-color: #4d90fe;
}
#title {
color: #fff;
background-color: #4d90fe;
font-size: 25px;
font-weight: 500;
padding: 6px 12px;
}
</style>
<script>
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 37.5546788, lng: 126.9706069},
zoom: 15
});
var card = document.getElementById('pac-card');
var input = document.getElementById('pac-input');
var types = document.getElementById('type-selector');
var strictBounds = document.getElementById('strict-bounds-selector');
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
var autocomplete = new google.maps.places.Autocomplete(input);
// Bind the map's bounds (viewport) property to the autocomplete object,
// so that the autocomplete requests use the current map bounds for the
// bounds option in the request.
autocomplete.bindTo('bounds', map);
// Set the data fields to return when the user selects a place.
autocomplete.setFields(
['address_components', 'geometry', 'icon', 'name']);
var infowindow = new google.maps.InfoWindow();
var infowindowContent = document.getElementById('infowindow-content');
infowindow.setContent(infowindowContent);
var marker = new google.maps.Marker({
map: map,
anchorPoint: new google.maps.Point(0, -29)
});
autocomplete.addListener('place_changed', function() {
infowindow.close();
marker.setVisible(false);
var place = autocomplete.getPlace();
if (!place.geometry) {
// User entered the name of a Place that was not suggested and
// pressed the Enter key, or the Place Details request failed.
window.alert("No details available for input: '" + place.name + "'");
return;
}
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
marker.setPosition(place.geometry.location);
marker.setVisible(true);
document.getElementById('latclick').value = marker.getPosition().lat();
document.getElementById('lngclick').value = marker.getPosition().lng();
var address = '';
if (place.address_components) {
address = [
(place.address_components[0] && place.address_components[0].short_name || ''),
(place.address_components[1] && place.address_components[1].short_name || ''),
(place.address_components[2] && place.address_components[2].short_name || '')
].join(' ');
}
document.getElementById('address').value = address;
document.getElementById('place_name').value = place.name;
infowindowContent.children['place-icon'].src = place.icon;
infowindowContent.children['place-name'].textContent = place.name;
infowindowContent.children['place-address'].textContent = address;
infowindow.open(map, marker);
});
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
function setupClickListener(id, types) {
var radioButton = document.getElementById(id);
radioButton.addEventListener('click', function() {
autocomplete.setTypes(types);
});
}
setupClickListener('changetype-all', []);
setupClickListener('changetype-address', ['address']);
setupClickListener('changetype-establishment', ['establishment']);
setupClickListener('changetype-geocode', ['geocode']);
document.getElementById('use-strict-bounds')
.addEventListener('click', function() {
console.log('Checkbox clicked! New state=' + this.checked);
autocomplete.setOptions({strictBounds: this.checked});
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap"
defer></script>
</head>
<body>
<form id="frm" name="frm" action="write.jsp" method="post">
<div class="pac-card" id="pac-card">
<div>
<div id="title">
Autocomplete search
</div>
<div id="type-selector" class="pac-controls">
<input type="radio" name="type" id="changetype-all" checked="checked">
<label for="changetype-all">All</label>
<input type="radio" name="type" id="changetype-establishment">
<label for="changetype-establishment">Establishments</label>
<input type="radio" name="type" id="changetype-address">
<label for="changetype-address">Addresses</label>
<input type="radio" name="type" id="changetype-geocode">
<label for="changetype-geocode">Geocodes</label>
</div>
<div id="strict-bounds-selector" class="pac-controls">
<input type="checkbox" id="use-strict-bounds" value="">
<label for="use-strict-bounds">Strict Bounds</label>
</div>
</div>
<div id="pac-container">
<input id="pac-input" type="text"
placeholder="Enter a location">
</div>
</div>
<div id="map"></div>
<div id="infowindow-content">
<img src="" width="16" height="16" id="place-icon">
<span id="place-name" class="title"></span><br>
<span id="place-address"></span>
</div>
<div>
위도 <input type="text" id="latclick" name="latclick" value="">
경도<input type="text" id="lngclick" name="lngclick" value="">
주소 <input type="text" id="address" name="address" value="">
장소 <input type="text" id="place_name" name="place_name" value="">
</div>
</body>
</form>
</html>
다음은 데이터를 받는 write.jsp 입니다.
register.jsp에서 전송된 위도 (name=”latclick”) 경도 (name=”lngclick”) 그리고 주소 (name=”address”) 장소 (name=”place_name”)를 request.getParameter를 통해 저장합니다.
이후 일반적인 DB 접속 및 쿼리문을 작성하여 해당 DB테이블의 칼럼에 저장합니다. 저 같은 경우 mysql을 이용하였기에 해당 구문을 활용하였고 maridaDB나 oracleDB의 경우도 쿼리구문만 살짝 변경하면 가능합니다.
이를 통해 해당 DB에 특정장소의 위치 정보를 저장할 수 있습니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page
import = "java.sql.Connection"
import = "java.sql.DriverManager"
import = "java.sql.SQLException"
import = "java.sql.Statement"
%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0">
<title> Autocomplete Place Write </title>
<style>
</style>
</head>
<body>
<div id="wrapper">
클래스 등록이 완료되었습니다!
<!-- 클래스 내용 DB Write -->
<%
request.setCharacterEncoding("UTF-8");
String lat = request.getParameter("latclick");
String lng = request.getParameter("lngclick");
String address = request.getParameter("address");
String place_name = request.getParameter("place_name");
Connection con = null;
Statement stmt = null;
//콘솔 출력 테스트 차례대로 위도, 경도, 주소, 장소명
System.out.println(lat);
System.out.println(lng);
System.out.println(address);
System.out.println(place_name);
try {
System.out.println("드라이버 로드 성공 !");
String url = "jdbc:mysql://(DB 아이피)/(DB 테이블)?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8";
String id = "DB 아이디";
String pass = "DB 비밀번호";
con = DriverManager.getConnection(url, id, pass);
System.out.println(con.toString());
System.out.println("JDBC Connector 연결 성공 !");
// input data
String sql = "insert into (DB 테이블) (칼럼명1, 칼럼명2, 칼럼명3, 칼럼명4) values (lat, lng, address, place_name);
stmt = con.createStatement();
System.out.println("SQLServerStatement 개체 생성 !");
stmt.executeUpdate(sql);
} catch(SQLException e) {
System.out.println("SQLException : " + e.getMessage());
} finally {
if(stmt != null) {
try {
stmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(con != null) {
try {
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
%>
</div>
</body>
</html>
다음 포스팅에서는 DB에서 데이터를 불러오는 법에 대해 알아보겠습니다.
2022.12.14 - [정보기술] - (9) 구글 지도 API - 검색 인터페이스 구현
(9) 구글 지도 API - 검색 인터페이스 구현
이전 포스팅에서는 특정장소의 정보를 DB에 저장하는 것을 알아보았습니다. 본 포스팅에서는 특정장소의 DB를 불러오는 방법에 대하여 알아봅시다. 이제 여기에서는 웹개발자의 개발방향이나
iftraveler.tistory.com
'정보기술' 카테고리의 다른 글
(10) 번외 - 검색지점 기준 반경거리 계산 (하버사인 공식) (0) | 2022.12.14 |
---|---|
(9) 구글 지도 API - 검색 인터페이스 구현 (0) | 2022.12.14 |
(7) 구글 지도 API - 특정 주소의 좌표 확인하기 (0) | 2022.12.14 |
(6) 번외 - 자동완성주소 검색에 관하여 (0) | 2022.12.14 |
(5) 구글 지도 API - 자동완성주소 검색하기 (0) | 2022.12.14 |
댓글