Kakao 지도 API 신청 (앱 키 발급)
애플리케이션 추가하기
Web 플랫폼 등록
앱 키 발급
프로젝트 생성
기본 설정
application.yml 설정
Kakao 지도 API 연동, 위치 찾기 구현
컨트롤러, 프론트 페이지 추가
컨트롤러 생성
메인 페이지 생성
Kakao 지도 API 가이드 링크
프로젝트 구조
GitHub 링크
실행화면
kakao developers 사이트에 접속하여 로그인을 합니다.
사이트 링크 : https://developers.kakao.com
로컬에서 API 요청 할 경우 "http://localhost:8080" 입력하시면 됩니다.
Kakao 지도 API는 JavaScript 키를 사용합니다.
검색란에 의존성 키워드를 입력하여 의존성을 추가합니다. (녹색 영역 참조)
application.properties파일의 확장자를 application.yml 확장자로 변경합니다.
spring:
application:
name: map
#mustache UTF-8
server:
servlet:
encoding:
force: true
---
#mustache 설정
spring:
mustache:
cache: false
servlet:
expose-request-attributes: true #mustache에서 csrf 토큰 변수 오류 발생 때문에 추가
expose-session-attributes: true #세션
controller 패키지를 생성 후 MainController 클래스 파일을 생성합니다.
패키지 위치 : com.example.map.controller
package com.example.map.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
/**
* 메인 페이지
* @return
*/
@GetMapping("/")
public String index() {
return "index";
}
}
templates에 index.mustache 파일을 생성합니다.
JavaScript 키 설정: <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=[JavaScript 키]&libraries=services"></script>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>메인 페이지</title>
<style>
.container {
width: 800px !important;
}
.map_wrap {
position:relative;
width:100%;
height:650px;
}
.title {
font-weight:bold;
display:block;
}
.hAddr {
position:absolute;
left:10px;
top:10px;
border-radius: 2px;
background:#fff;
background:rgba(255,255,255,0.8);
z-index:1;
padding:5px;
}
#centerAddr {
display:block;
margin-top:2px;
font-weight: normal;
}
.bAddr {
padding:5px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12 pt-5">
<div class="card mb-4">
<h5 class="card-header text-center">메인 페이지</h5>
<div class="card-body">
<div>
찾기 : <input type="text" value="" id="keyword" size="15">
<button type="button" class="btn btn-outline-dark btn-sm" onclick="searchPlaces();">검색</button>
</div>
<div class="text-center">
<div class="map_wrap">
<div id="map" style="width:100%;height:100%;position:relative;overflow:hidden;"></div>
<div class="hAddr">
<span class="title">지도중심기준 행정동 주소정보</span>
<span id="centerAddr"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=2442a1b67c88c27cf4ad4a7939973aa5&libraries=services"></script>
<script>
$(document).ready(function(){
// 마커를 클릭하면 장소명을 표출할 인포윈도우 입니다
var infowindow = new kakao.maps.InfoWindow({zIndex:1});
var mapContainer = document.getElementById('map'), // 지도를 표시할 div
mapOption = {
center: new kakao.maps.LatLng(37.56431006014851, 126.97672880129785), // 지도의 중심좌표
level: 3 // 지도의 축소, 확대 레벨 1 ~ 14
};
// 지도를 생성합니다
var map = new kakao.maps.Map(mapContainer, mapOption);
// 일반 지도와 스카이뷰로 지도 타입을 전환할 수 있는 지도타입 컨트롤을 생성합니다
var mapTypeControl = new kakao.maps.MapTypeControl();
// 지도에 컨트롤을 추가해야 지도위에 표시됩니다
// kakao.maps.ControlPosition은 컨트롤이 표시될 위치를 정의하는데 TOPRIGHT는 오른쪽 위를 의미합니다
map.addControl(mapTypeControl, kakao.maps.ControlPosition.TOPRIGHT);
// 지도 확대 축소를 제어할 수 있는 줌 컨트롤을 생성합니다
var zoomControl = new kakao.maps.ZoomControl();
map.addControl(zoomControl, kakao.maps.ControlPosition.RIGHT);
// 장소 검색 객체를 생성합니다
var ps = new kakao.maps.services.Places();
// 기본값 장소 설정
ps.keywordSearch('서울역', placesSearchCB);
getInfo = function() {
// 지도의 현재 중심좌표를 얻어옵니다
var center = map.getCenter();
// 지도의 현재 레벨을 얻어옵니다
var level = map.getLevel();
// 지도타입을 얻어옵니다
var mapTypeId = map.getMapTypeId();
// 지도의 현재 영역을 얻어옵니다
var bounds = map.getBounds();
// 영역의 남서쪽 좌표를 얻어옵니다
var swLatLng = bounds.getSouthWest();
// 영역의 북동쪽 좌표를 얻어옵니다
var neLatLng = bounds.getNorthEast();
// 영역정보를 문자열로 얻어옵니다. ((남,서), (북,동)) 형식입니다
var boundsStr = bounds.toString();
var message = '지도 중심좌표는 위도 ' + center.getLat() + ', <br>';
message += '경도 ' + center.getLng() + ' 이고 <br>';
message += '지도 레벨은 ' + level + ' 입니다 <br> <br>';
message += '지도 타입은 ' + mapTypeId + ' 이고 <br> ';
message += '지도의 남서쪽 좌표는 ' + swLatLng.getLat() + ', ' + swLatLng.getLng() + ' 이고 <br>';
message += '북동쪽 좌표는 ' + neLatLng.getLat() + ', ' + neLatLng.getLng() + ' 입니다';
//console.log(message);
}
// 검색
searchPlaces = function() {
if (!$("#keyword").val().replace(/^\s+|\s+$/g, '')) {
alert('키워드를 입력하세요.');
$("#keyword").val("");
$("#keyword").focus();
return false;
}
// 장소검색 객체를 통해 키워드로 장소검색을 요청합니다
ps.keywordSearch($("#keyword").val(), placesSearchCB);
getInfo();
}
$("#keyword").keyup(function(e){
if (e.keyCode == 13) {
searchPlaces();
}
});
// 키워드 검색 완료 시 호출되는 콜백함수 입니다
function placesSearchCB (data, status, pagination) {
if (status === kakao.maps.services.Status.OK) {
// 검색된 장소 위치를 기준으로 지도 범위를 재설정하기위해
// LatLngBounds 객체에 좌표를 추가합니다
var bounds = new kakao.maps.LatLngBounds();
for (var i=0; i<data.length; i++) {
displayMarker(data[i]);
bounds.extend(new kakao.maps.LatLng(data[i].y, data[i].x));
}
// 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다
map.setBounds(bounds);
map.setLevel(6);
}
}
// 지도에 마커를 표시하는 함수입니다
function displayMarker(place) {
// 마커를 생성하고 지도에 표시합니다
var marker = new kakao.maps.Marker({
map: map,
position: new kakao.maps.LatLng(place.y, place.x)
});
// 마커에 클릭이벤트를 등록합니다
kakao.maps.event.addListener(marker, 'click', function() {
// 마커를 클릭하면 장소명이 인포윈도우에 표출됩니다
infowindow.setContent('<div style="padding:5px;font-size:12px;">' + place.place_name + '</div>');
infowindow.open(map, marker);
});
}
// 주소-좌표 변환 객체를 생성합니다
var geocoder = new kakao.maps.services.Geocoder();
var marker = new kakao.maps.Marker(), // 클릭한 위치를 표시할 마커입니다
infowindow = new kakao.maps.InfoWindow({zindex:1}); // 클릭한 위치에 대한 주소를 표시할 인포윈도우입니다
// 현재 지도 중심좌표로 주소를 검색해서 지도 좌측 상단에 표시합니다
searchAddrFromCoords(map.getCenter(), displayCenterInfo);
// 지도를 클릭했을 때 클릭 위치 좌표에 대한 주소정보를 표시하도록 이벤트를 등록합니다
kakao.maps.event.addListener(map, 'click', function(mouseEvent) {
searchDetailAddrFromCoords(mouseEvent.latLng, function(result, status) {
if (status === kakao.maps.services.Status.OK) {
var detailAddr = !!result[0].road_address ? '<div>도로명주소 : ' + result[0].road_address.address_name + '</div>' : '';
detailAddr += '<div>지번 주소 : ' + result[0].address.address_name + '</div>';
var content = '<div class="bAddr">' +
'<span class="title">법정동 주소정보</span>' +
detailAddr +
'</div>';
// 마커를 클릭한 위치에 표시합니다
marker.setPosition(mouseEvent.latLng);
marker.setMap(map);
// 인포윈도우에 클릭한 위치에 대한 법정동 상세 주소정보를 표시합니다
infowindow.setContent(content);
infowindow.open(map, marker);
}
});
});
// 중심 좌표나 확대 수준이 변경됐을 때 지도 중심 좌표에 대한 주소 정보를 표시하도록 이벤트를 등록합니다
kakao.maps.event.addListener(map, 'idle', function() {
searchAddrFromCoords(map.getCenter(), displayCenterInfo);
});
function searchAddrFromCoords(coords, callback) {
// 좌표로 행정동 주소 정보를 요청합니다
geocoder.coord2RegionCode(coords.getLng(), coords.getLat(), callback);
}
function searchDetailAddrFromCoords(coords, callback) {
// 좌표로 법정동 상세 주소 정보를 요청합니다
geocoder.coord2Address(coords.getLng(), coords.getLat(), callback);
}
// 지도 좌측상단에 지도 중심좌표에 대한 주소정보를 표출하는 함수입니다
function displayCenterInfo(result, status) {
if (status === kakao.maps.services.Status.OK) {
var infoDiv = document.getElementById('centerAddr');
for(var i = 0; i < result.length; i++) {
// 행정동의 region_type 값은 'H' 이므로
if (result[i].region_type === 'H') {
infoDiv.innerHTML = result[i].address_name;
break;
}
}
}
}
});
</script>
</body>
</html>
https://apis.map.kakao.com/web/guide/