참고 : https://www.youtube.com/watch?v=BYT0zR2lbXQ&t=929s
https://developers.kakao.com/ 에서 시작하기 버튼을 눌러
api 사용 권한을 받기 위해 정보를 입력한다.
kakao map api 를 잘 사용하기 위한 가이드 홈페이지에 나와있는 순서 중에서 vue 파일 내에 step 1 에서 발급받은 javascript api key 를 넣어주어야 사용할 수 있다.
public 폴더 > index.html 폴더의 head 태그 안에 script 태그 코드를 삽입해준다.
지도를 띄우기 위해서는 지도를 담을 영역을 먼저 만들어준다.
<template>
<div ref="map"></div>
</template>
그 영역 안에서 지도를 띄우기 위해서는 지도의 중심좌표를 가리키는 center와 확대 축소의 정도를 가리키는 level 의 옵션이 필요하다. 이 옵션을 가지고 지도를 생성하고 리턴한다.
공식 가이드에 나와있는 container 는 var container = this.$refs.map;
로 지도를 담을 영역을 가리킨다.
mounted(){
let kakao = window.kakao;
var container = this.$refs.map;
const { center, level } = this.options;
this.mapInstance = new kakao.maps.Map(container, {
center: new kakao.maps.LatLng(center.lat, center.lng),
level,
}); //지도 생성 및 객체 리턴
}
전체코드는 마운트가 될 때 지도 영역이 나오도록 한다.
<template>
<div class="controll">
<button @click="zoom(1)">
<span class="material-symbols"> zoom_in </span>
</button>
<button @click="zoom(-1)">
<span class="material-symbols"> zoom_out </span>
</button>
</div>
</template>
methods: {
zoom(delta) {
const level = Math.max(3, this.mapOption.level + delta);
this.mapOption.level = level;
console.log("zoom", this.mapOption.level);
},
}
지도를 확대, 축소하기 위해 버튼 두 개를 생성하여 클릭시 zoom 함수가 구현된다.
zoom 함수는 현재 옵션의 level 에서 매개변수로 받아온 값 1 이나 -1값을 연산하여 옵션의 level 를 갱신해준다.
watch: {
"options.level"(cur, prev) {
console.log(`[LEVEL CHANGED] ${prev} => ${cur}`);
this.mapInstance.setLevel(cur);
},
}
watch 감시자를 통해 옵션의 level 의 변경이 감지가 되면 setLevel
메서드를 통해 매개변수로 전달해온 갱신된 level 값을 확대 수준을 설정한다.
💡 sass-lodaer 오류 해결하기
<style lang="scss">
button {
border: 1px solid transparent;
padding: 6px;
background-color: #efefefdd;
border-radius: 6px;
&:hover {
background-color: #ddd;
border-color: #ddd;
cursor: pointer;
}
&:active {
background-color: #aaa;
border-color: #aaa;
}
}
</style>
다음과 같이 lang="scss" 버전으로 사용하고 npm install sass-loader
를 설치를 해주었지만, 이와 같은 오류가 발생했다.
구글링을 해서 찾아보니 다음과 같이 npm install sass-loader
가 아닌 npm install -D sass-loader@^10 sass
를 설치해줌으로써 오류를 해결하였다.
지도의 중심을 변경하기 위해서는 옵션의 center 의 변경이 있어야 한다.
다음과 같이 세 개의 더미데이터를 이용해 가져온 값을 클릭시 지도의 중심이 변경하고자 한다.
//api.js
const api = {
harbor: {
all(callback) {
const harbors = [
{
seq: 398,
place: "제주항 국제 여객 터미널",
lat: 33.52456237850086,
lng: 126.54371888191963,
},
{
seq: 399,
place: "통영항",
lat: 34.83952733985843,
lng: 128.42015935198992,
},
{
seq: 400,
place: "부산 국제 크루즈 터미널",
lat: 35.07980714092641,
lng: 129.0798233676466,
},
];
callback({ success: true, harbors });
},
},
};
export default api;
import api from "./service/api";
mounted() {
api.harbor.all((res) => {
console.log("[항구목록]", res.harbors);
this.harbors = res.harbors;
});
},
따라서 마운트 될 때, api 를 가져와져와 결과값을 받아오면 harbors 배열값에 저장시킨다.
<div class="map-area">
<div class="harbors">
<div
class="harbor"
v-for="hbr in harbors"
:key="hbr.seq"
@click="showOnMap(hbr)">
<h3>{{ hbr.place }}</h3>
</div>
</div>
</div>
배열값을 v-for 을 이용해 바운딩하여 나열시킨다.
배열 안 각자의 객체 값은 아래와 같다.
{
seq: 400,
place: "부산 국제 크루즈 터미널",
lat: 35.07980714092641,
lng: 129.0798233676466,
},
methods: {
showOnMap(harbor) {
console.log(harbor);
this.mapOption.center = {
lat: harbor.lat,
lng: harbor.lng,
};
},
},
}
그 place 값을 클릭했을 때 이벤트 showOnMap 함수는 객체값의 lat 와 lng 을 옵션의 center 값으로 지정해준다.
위의 지도 확대 축소에서 확대 축소 정도를 나타내는 Level를 watch 감시자를 통해 설정해주었다면, 이도 마찬가지로 center 를 watch 감시자와 setCenter
메서드를 통해 설정해줄 수 있다.
watch:{
"options.center"(cur, prev) {
//console.log(`[NEW CENTER]`, cur.lat, cur.lng);
this.mapInstance.setCenter(new kakao.maps.LatLng(cur.lat, cur.lng));
},
},
<template>
<div>
<h3>kakao map demo(center, level)</h3>
<div class="controll">
<button @click="zoom(1)">
<span class="material-symbols"> zoom_in </span>
</button>
<button @click="zoom(-1)">
<span class="material-symbols"> zoom_out </span>
</button>
</div>
<div class="map-area">
<div class="harbors">
<div
class="harbor"
v-for="hbr in harbors"
:key="hbr.seq"
@click="showOnMap(hbr)"
>
<h3>{{ hbr.place }}</h3>
</div>
</div>
<KakaoMap class="kmap" :options="mapOption" />
</div>
</div>
</template>
<script>
import KakaoMap from "./components/map/KakaoMap.vue";
import api from "./service/api";
export default {
components: {
KakaoMap,
},
data() {
return {
mapOption: {
center: {
lat: 33.450701,
lng: 126.570667,
},
level: 8,
},
harbors: [],
};
},
mounted() {
api.harbor.all((res) => {
console.log("[항구목록]", res.harbors);
this.harbors = res.harbors;
});
},
methods: {
zoom(delta) {
const level = Math.max(3, this.mapOption.level + delta);
this.mapOption.level = level;
console.log("zoom", this.mapOption.level);
},
showOnMap(harbor) {
console.log(harbor);
this.mapOption.center = {
lat: harbor.lat,
lng: harbor.lng,
};
},
},
};
</script>
<style lang="scss">
button {
border: 1px solid transparent;
padding: 6px;
background-color: #efefefdd;
border-radius: 6px;
&:hover {
background-color: #ddd;
border-color: #ddd;
cursor: pointer;
}
&:active {
background-color: #aaa;
border-color: #aaa;
}
}
.map-area {
display: flex;
.harbors {
.harbor {
padding: 10px;
border: 1px solid transparent;
&:hover {
background-color: aliceblue;
border-color: #6a9dff;
cursor: pointer;
}
&:active {
background-color: rgb(166, 197, 224);
border-color: #4471c5;
}
h4 {
margin: 0;
}
}
}
.kmap {
flex: 1 1 auto;
}
}
</style>
<template>
<div ref="map"></div>
</template>
<script>
let kakao = window.kakao;
export default {
props: ["options"],
data() {
return {
mapInstance: null,
};
},
mounted() {
console.log(this.options);
kakao = kakao || window.kakao;
console.log(this.$refs.map);
var container = this.$refs.map;
const { center, level } = this.options;
this.mapInstance = new kakao.maps.Map(container, {
center: new kakao.maps.LatLng(center.lat, center.lng),
level,
}); //지도 생성 및 객체 리턴
},
watch: {
"options.level"(cur, prev) {
console.log(`[LEVEL CHANGED] ${prev} => ${cur}`);
this.mapInstance.setLevel(cur);
},
"options.center"(cur, prev) {
console.log(`[NEW CENTER]`, cur.lat, cur.lng);
this.mapInstance.setCenter(new kakao.maps.LatLng(cur.lat, cur.lng));
},
},
};
</script>
<style>
.kmap {
height: 600px;
}
</style>
const api = {
harbor: {
all(callback) {
const harbors = [
{
seq: 398,
place: "제주항 국제 여객 터미널",
lat: 33.52456237850086,
lng: 126.54371888191963,
},
{
seq: 399,
place: "통영항",
lat: 34.83952733985843,
lng: 128.42015935198992,
},
{
seq: 400,
place: "부산 국제 크루즈 터미널",
lat: 35.07980714092641,
lng: 129.0798233676466,
},
];
callback({ success: true, harbors });
},
},
};
export default api;
vue 를 공부하면서 api 도 활용할 수 있는 방법으로 공부해보면 좋겠다싶었고, 그 중에서도 한 번도 사용해보지 않았던 지도를 활용하는 방법을 배운다는 생각에 들뜨기도 한다. 다만 지도를 활용할 수 있는 방안도 많고, 그간과는 조금 다르게 option api 를 이용해서 작성하는 터라 어렵게 느껴지기도 했다. 그치만 공식 문서와 유튜브를 통해 하나씩 야금야금 따라하고 정리하다보면 내 것으로 만들 수 있을 것이라 생각한다.