목차 | |
1. | 현재 위치 |
2. | 날씨 |
1. 현재 위치
▣ Geolocation API
: Geolocation API는 웹 브라우저에서 사용자의 위치 정보를 가져올 수 있는 표준 API이다.
GPS, Wi-Fi, 셀룰러 네트워크, IP 주소 등의 데이터를 활용하여 사용자의 현재 위치를 확인한다.
◈ 특징
- 사용자 동의 필수: 브라우저는 사용자의 위치 정보를 수집하기 전 동의를 요구한다.
- 다양한 위치 수집 소스: GPS, Wi-Fi, 셀룰러 네트워크, IP 주소 등 여러 소스로부터 정보를 수집한다.
- 높은 정확도 지원: enableHighAccuracy 옵션을 통해 정확도를 조정할 수 있다.
- 브라우저 지원: 대부분의 현대 브라우저에서 지원되며, 모바일에서도 동작한다.
◈ Geolocation API 사용 방법
: 주로 두 가지 주요 메서드를 통해 사용된다.
1. getCurrentPosition: 한 번만 위치를 가져온다.
2. watchPosition: 위치가 변할 때마다 지속적으로 위치 정보를 제공한다.
◈ Geolocation API 옵션 설명
navigator.geolocation.getCurrentPosition 및
navigator.geolocation.watchPosition 메서드에는 선택할 수 있는 옵션들이 있다.
- enableHighAccuracy: 고정밀 모드를 활성화한다. 배터리 소모가 높아질 수 있다.
- timeout: 위치 정보를 가져올 때까지 기다리는 최대 시간을 밀리초 단위로 설정한다.
- maximumAge: 캐시된 위치 정보가 제공될 수 있는 최대 시간을 밀리초 단위로 설정한다.
◈ 카카오맵 API 연동 및 키워드 검색
1. 카카오 개발자 페이지 가입 및 앱 키 발급
- 카카오 개발자 페이지에 회원가입하고, 앱을 생성하여 JavaScript 키를 발급받는다.
2. 카카오맵 API 스크립트 추가
- index.html 파일에 다음 스크립트를 추가한다.
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=YOUR_APP_KEY&libraries=services"></script>
- YOUR_APP_KEY 부분에 발급받은 JavaScript 키를 입력한다.
▶ 코드
◈ index.html
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultrap.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout}">
<body>
<div layout:fragment="content">
<div class="container-md">
<!-- 카카오맵 API 로딩 (HTTPS 사용)-->
<script type="text/javascript"
th:src="@{https://dapi.kakao.com/v2/maps/sdk.js?appkey=자신의 API 키 입력}"></script>
<button onclick="getLocation()">주변 인기 장소 찾기</button>
<p id="status">위치를 찾지 못했습니다</p>
<!-- <h1>Geolocation API로 현재 위치 가져오기</h1>-->
<div id="map" style="width:500px;height:400px;"></div>
<ul id="places"></ul>
<script th:src="@{/js/currentLocationMap.js}"></script>
</div>
</div>
</body>
</html>
◈ currentLocationMap.js
let map;
let ps;
function getLocation() {
const status = document.getElementById("status");
// Geolocation API 지원 여부 확인
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude, accuracy } = position.coords;
status.textContent = `위도: ${latitude}, 경도: ${longitude}, 정확도: ${accuracy}미터`;
// 지도를 해당 위치로 이동
const mapContainer = document.getElementById('map');
const mapOption = {
center: new kakao.maps.LatLng(latitude, longitude), // 지도의 중심 좌표 설정
level: 7 // 지도 확대 수준(레벨) 설정
};
map = new kakao.maps.Map(mapContainer, mapOption);
// 마커 표시
const marker = new kakao.maps.Marker({
position: new kakao.maps.LatLng(latitude, longitude)
});
marker.setMap(map);
// // 장소 검색 객체 생성
// ps = new kakao.maps.services.Places();
// // 주변 나들이 장소 검색
// const placesList = document.getElementById("places");
// ps.keywordSearch("관광지", (data, status, pagination) => {
// if (status === kakao.maps.services.Status.OK) {
// placesList.innerHTML = "";
// data.forEach((place) => {
// const listItem = document.createElement("li");
// listItem.textContent = `${place.place_name} (${place.address_name})`;
// placesList.appendChild(listItem);
// // 지도에 마커 추가
// const placeMarker = new kakao.maps.Marker({
// position: new kakao.maps.LatLng(place.y, place.x),
// map: map
// });
// });
// } else {
// placesList.textContent = "주변 관광지를 찾을 수 없습니다.";
// }
// }, {
// location: new kakao.maps.LatLng(latitude, longitude),
// radius: 5000 // 5km 내에서 검색
// });
},
(error) => {
status.textContent = `위치 정보를 가져올 수 없습니다: ${error.message}`;
},
{
enableHighAccuracy: true, // 정확도 우선 모드
timeout: 10000, // 10초 이내에 응답 없으면 에러 발생
maximumAge: 0 // 항상 최신 위치 정보 수집
}
);
} else {
status.textContent = "브라우저가 위치 서비스를 지원하지 않습니다.";
}
}
// kakao map API로 지도 띄우기
/* var container = document.getElementById('map');
var options = {
center: new kakao.maps.LatLng(33.450701, 126.570667),
level: 3
};
var map = new kakao.maps.Map(container, options);*/
▷ 출력
2. 날씨
▣ Geocoder API 2.0
- open weather map의 현재 날씨 정보 API를 사용하기 위해서는 요청에 위도, 경도를 포함해야 한다.
- 내 주소 (혹은 날씨를 알고 싶어하는 주소)의 위도, 경도를 알기 위해 사용한다.
◈ Geocoder API 사용 방법
- 해당 사이트에 접속 후 회원가입을 한다.
https://www.vworld.kr/v4po_main.do
- 상단의 메뉴바를 클릭
- 오픈 API > 인증키발급을 클릭
- 약관 동의 후 이용 정보 작성 (아래는 예시)
● 서비스명: 날씨 웹 서비스 예제 프로젝트
● 서비스 분류: 교육
● 서비스 유형: 웹사이트
● 서비스 URL : localhost:8089
● 서비스 설명
● 개요: 날씨 웹 서비스 예제 프로젝트
● 서비스 대상: 로컬(개인)
● 목적: open weather map API와 연동하여 주소 입력을 통한 날씨 정보를 가져오는 프로젝트
● 활용 API : 지오코더 API (반드시 선택!)
● 사용기관: 민간, 개인
- 인증키 발급 확인
- https://www.vworld.kr/dev/v4dv_geocoderguide2_s001.do
- 위의 사이트의 요청 URL 참고
https://api.vworld.kr/req/address?service=address&request=getCoord&key=[발급받은 인증키]&type=ROAD&address=[위치정보를 원하는 주소]
- 요청 파라미터
● service = address (필수)
● request = getCoord (필수)
● key = [발급받은 인증키] (필수)
● type: 검색 주소 유형 (필수)
● type = PARCEL : 지번 주소로 검색
● type = ROAD : 도로명 주소로 검색 (여기서는 도로명 주소로 검색함)
● address (필수)
● 위치 정보를 원하는 주소 기입
● (여기서는 도로명 주소로 선택 후 대략적인 도로명 주소만 기입해도 가능함)
● refine = true (기본값)으로 설정되어 있기 때문
● 대략적인 도로명 주소도 정제되어 완벽한 주소로 변환함
● ex) 인하대학교 > 인천광역시 미추홀구 인하로 100 (용현동)으로 정제됨
▶ 코드
◈ index.html
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultrap.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout}">
<body>
<div layout:fragment="content">
<div class="container-md">
<!-- 카카오맵 API 로딩 (HTTPS 사용)-->
<script type="text/javascript"
th:src="@{https://dapi.kakao.com/v2/maps/sdk.js?appkey=자신의 API key를 입력}"></script>
<button onclick="getLocation()">주변 인기 장소 찾기</button>
<p id="status">위치를 찾지 못했습니다</p>
<!-- <h1>Geolocation API로 현재 위치 가져오기</h1>-->
<div id="map" style="width:500px;height:400px;"></div>
<ul id="places"></ul>
<script th:src="@{/js/currentLocationMap.js}"></script>
<hr>
<form th:action="@{/address}" method="post">
<input name="address" placeholder="도로명 주소를 입력해주세요."/>
<button type="submit">입력</button>
</form>
<div th:unless="${weather == null}">
<li th:text="'날씨 : ' + ${weather['weather_main']}"></li>
<li th:text="'날씨 설명 : ' + ${weather['weather_description']}"></li>
<li th:text="'온도 : ' + ${weather['temperature']}"></li>
<li th:text="'습도 : ' + ${weather['humidity']}"></li>
</div>
<hr>
<script>
</script>
</div>
</div>
</body>
</html>
◈ bundle.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.2.11'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.project'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
implementation 'org.apache.tika:tika-core:2.4.1'
implementation 'org.apache.tika:tika-parsers:2.4.1'
implementation 'net.coobird:thumbnailator:0.4.17'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
// providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// JSON 데이터를 처리하기 위한 라이브러리 추가
implementation group: 'org.json', name: 'json', version: '20231013'
}
tasks.named('test') {
useJUnitPlatform()
}
◈ WeatherService.java
package com.project.joonggo.service;
import org.json.JSONObject;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@Service
public class WeatherService {
// 위도와 경도를 Map<String, String> 형태로 반환하는 메서드
public Map<String, String> returnLanLon(String address){
Map<String, String> coordinates = new HashMap<>();
String apiKey = ""; // Geocoder API 2.0에서 발급받은 API 키 작성할 것
try{
// 주소 인코딩 (인코딩 X 시 400 에러 발생함)
String encodedAddress = URLEncoder.encode(address, StandardCharsets.UTF_8.toString());
String apiUrl = "https://api.vworld.kr/req/address?service=address&request=getCoord&key=" + apiKey + "&type=ROAD&address=" + encodedAddress;
// URL 객체 생성
URL url = new URL(apiUrl);
// 연결 설정
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// 응답 코드 확인
if(conn.getResponseCode() == HttpURLConnection.HTTP_OK){
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder response = new StringBuilder();
String inputLine;
// 응답 내용 읽기
while ((inputLine = in.readLine()) != null){
response.append(inputLine);
}
in.close();
// JSON 응답 파싱
JSONObject jsonResponse = new JSONObject(response.toString());
if(jsonResponse.getJSONObject("response").getString("status").equals("OK")) {
String x = jsonResponse.getJSONObject("response").getJSONObject("result").getJSONObject("point").getString("x");
String y = jsonResponse.getJSONObject("response").getJSONObject("result").getJSONObject("point").getString("y");
coordinates.put("lat", y);
coordinates.put("lon", x);
}
}else{
System.out.println("Error: " + conn.getResponseCode());
}
} catch (Exception e) {
e.printStackTrace();
}
return coordinates;
}
// 날씨 정보를 Map<String, String> 형태로 반환하는 메서드
public Map<String, String> returnWeather(Map<String, String> lanLon){
String apiKey = ""; // Open Weather Map 날씨 API에서 발급받은 API 키 작성할 것
// 넘어온 위도, 경도를 포함한 url
String apiUrl = "https://api.openweathermap.org/data/2.5/weather?lat=" + lanLon.get("lat") + "&lon=" + lanLon.get("lon") + "&appid=" + apiKey;
Map<String, String> weather = new HashMap<>();
try {
// URL 객체 생성
URL url = new URL(apiUrl);
// 연결 설정
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// 응답 코드 확인
if(conn.getResponseCode() == HttpURLConnection.HTTP_OK){
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder response = new StringBuilder();
String inputLine;
// 응답 내용 읽기
while((inputLine = in.readLine()) != null){
response.append(inputLine);
}
in.close();
// JSON 응답 파싱
JSONObject jsonResponse = new JSONObject(response.toString());
weather.put("weather_main", jsonResponse.getJSONArray("weather").getJSONObject(0).getString("main"));
weather.put("weather_description", jsonResponse.getJSONArray("weather").getJSONObject(0).getString("description"));
BigDecimal temp = jsonResponse.getJSONObject("main").getBigDecimal("temp");
BigDecimal tempCelsius = BigDecimal.valueOf(temp.doubleValue() - 273.15).setScale(2, RoundingMode.HALF_UP); // 소수점 둘째 자리에서 반올림
weather.put("temperature", String.valueOf(tempCelsius));
int humidity = jsonResponse.getJSONObject("main").getInt("humidity");
weather.put("humidity", Integer.toString(humidity) + "%");
} else {
System.out.println("Error: " + conn.getResponseCode());
}
} catch (Exception e) {
e.printStackTrace();
}
return weather;
}
}
◈ WeatherController.java
package com.project.joonggo.controller;
import com.project.joonggo.service.WeatherService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
@Controller
@RequiredArgsConstructor
public class WeatherController {
private final WeatherService weatherService;
@GetMapping
public String home(){
return "index";
}
@PostMapping("/address")
public String showWeather(@RequestParam("address") String address, Model model){
Map<String, String> lanLon = weatherService.returnLanLon(address);
model.addAttribute("weather", weatherService.returnWeather(lanLon));
return "index";
}
}
▷ 출력
▣ 참고 자료 출처
- Geolocation API
https://velog.io/@sujung_shin/Geolocation-API로-현재-위치-가져오기-웹사이트에서-사용자-위치-기반-서비스-만들기
- Geocoder API 2.0 Key, Open Weather Map 날씨 API
'Project > AWS-Final' 카테고리의 다른 글
최종 프로젝트(6) - AWS 풀스택 과정 95일차 (0) | 2024.12.12 |
---|---|
최종 프로젝트(5) - AWS 풀스택 과정 94일차 (0) | 2024.12.11 |
최종 프로젝트(3) - AWS 풀스택 과정 92일차 (0) | 2024.12.09 |
최종 프로젝트(2) - AWS 풀스택 과정 91일차 (0) | 2024.12.06 |
최종 프로젝트(1) - AWS 풀스택 과정 90일차 (0) | 2024.12.05 |