[Vue] Vue3 기반 프로젝트에서 카카오맵 API를 통해 지도를 뿌려보자. (1) 지도 가져오기
예전에 카카오맵API를 통해 지도를 가져온 적이 있는데.. ( 해당 글 참조 )
당시에는 Vue환경이 아닌 반푼이었다. 그냥 javascript로 가져오고 검색은 ajax나 axios를 쓰기만 하고..
그래서 이번에 컴포넌트, 웹팩, Vuex 같은 것들 복습 하는 겸 Vue3 기반 프로젝트로 카카오맵을 만들어 보려고 한다.
아래 그림의 흐름대로 구현할 생각이다. 이 그림을 잘 기억해두자.
그럼 바로 시작해보자~~ ( API키 갖고 오고 이런 건 생략하겠다. 궁금한 사람은 위 링크에서 참조하자. )
MapHeader.vue
<template>
<header class="p-3 bg-dark text-white">
<div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
<svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap"><use xlink:href="#bootstrap"/></svg>
</a>
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
<li><a href="#" class="nav-link px-2 text-secondary">Home</a></li>
<li><a href="#" class="nav-link px-2 text-white">Features</a></li>
<li><a href="#" class="nav-link px-2 text-white">Pricing</a></li>
<li><a href="#" class="nav-link px-2 text-white">FAQs</a></li>
<li><a href="#" class="nav-link px-2 text-white">About</a></li>
</ul>
<form class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3">
<input type="search" class="form-control form-control-dark" placeholder="Search..." aria-label="Search">
</form>
<div class="text-end">
<button type="button" class="btn btn-outline-light me-2">검색</button>
</div>
</div>
</div>
</header>
</template>
mapHeader.vue에는 검색기능을 넣을 생각인데, 오늘 글에서는 아무 기능도 안하니 그냥 넘어가도록 하자.
-----------------------------------------------------------------------------------------------------------------------------------
MapBody.vue
<template>
<div>
<div id="kakaoMap"></div>
</div>
</template>
<script>
export default {
data () {
return {
map : null
}
},
mounted() {
const script = document.createElement("script");
script.src = '//dapi.kakao.com/v2/maps/sdk.js?autoload=false&appkey=ca49c8f9d56------c47166311';
document.head.appendChild(script);
/*
스크립트가 로드 되기전에 kakao객체에 접근하여 kakao객체를 찾지 못해 발생하는 에러를
방지하기 위해 스크립트가 로드 된 뒤에 실제 지도를 그리도록 함
*/
script.onload = () => { kakao.maps.load(()=>{
var container = document.getElementById('kakaoMap'); //지도를 담을 영역의 DOM 레퍼런스
var options = { //지도를 생성할 때 필요한 기본 옵션
center: new kakao.maps.LatLng(33.450701, 126.570667), //지도의 중심좌표.
level: 3 //지도의 레벨(확대, 축소 정도)
};
//eslint-disable-next-line no-unused-vars
var map = new kakao.maps.Map(container, options); //지도 생성 및 객체 리턴
})
}
},
}
</script>
<style scoped>
#kakaoMap {width:1500px;height:800px; position: relative; left:300px; margin-top: 60px;}
</style>
오늘 가장 중요한 녀석이다. 실제로 컴포넌트가 mounted될 때 카카오맵API를 통해 지도를 가져와 map를 생성하고
지도에 표출해주는 부분.. 그럼 한번 자세히 보자..
기억할 지 모르겠지만, Vue환경이 아닌 일반 javascript환경에서는 <script>를 넣어주기만 하면 됬었다. 아래와 같이..
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=[API키 넣는 곳]"></script>
근데 Vue의 컴포넌트에서는 이렇게 할 수 없다.. <script>를 넣을 수 없기 때문.. 그래서 당황..
그래서 javascript의 함수를 이용해서 직접 <script>를 생성해준다.
//스크립트 태그 생성
const script = document.createElement("script");
//스크립트 태그에 src 속성 추가
script.src = '//dapi.kakao.com/v2/maps/sdk.js?autoload=false&appkey=[API키]';
//헤더에 해당 스크립트를 추가
document.head.appendChild(script);
이렇게 하면 헤더에 스크립트가 추가 된다. 그리고 맵을 생성하면 되야 되는데.. 이렇게만 하면 안된다.
왜냐하면, 스크립트 객체가 로드 되기전에 kakao객체를 찾아버리고, 당연히 에러가 난다.
그래서 스크립트 객체가 로드 된 후 kakao객체를 사용할 수 있도록 다음 함수를 추가한다.
script.onload = () => { kakao.maps.load(()=>{
// kakao맵 생성 코드 넣음
});
이렇게 하면 스크립트가 로드 된 뒤에 맵을 생성한다.
-----------------------------------------------------------------------------------------------------------------------------------
MapFooter.vue
<template>
<footer class="blog-footer">
<p>Blog template built for <a href="https://getbootstrap.com/">Bootstrap</a> by <a href="https://twitter.com/mdo">@mdo</a>.</p>
<p>
<a href="#">Back to top</a>
</p>
</footer>
</template>
<style scoped>
.blog-footer {margin-top: 50px;}
p {text-align: center;}
</style>
MapFooter.vue도 그냥 꾸미기용이니, 넘어가도록 하자.
-----------------------------------------------------------------------------------------------------------------------------------
App.vue
<template>
<div>
<map-header/>
<map-body/>
<map-footer/>
</div>
</template>
<script>
import MapHeader from './components/MapHeader.vue'
import MapBody from './components/MapBody.vue'
import MapFooter from './components/MapFooter.vue'
export default {
name: 'App',
components: {
MapHeader,
MapBody,
MapFooter
}
}
</script>
-----------------------------------------------------------------------------------------------------------------------------------
main.js
import { createApp } from 'vue'
import "bootstrap/dist/css/bootstrap.min.css"
import "bootstrap"
import App from './App.vue'
createApp(App).mount('#app')
-----------------------------------------------------------------------------------------------------------------------------------
이렇게 까지 하면 아래와 같은 결과화면을 확인할 수 있다..
이제 웹팩을 통해 헤더/바디/푸터를 번들링 해보겠다. 웹팩이 필요 없다는 사람은 그냥 위의 내용만 봐도 충분하다.
웹팩에 대한 기본내용은 ( 해당 링크 ) 를 확인하도록 하자.
웹팩 번들링
==================================================================
1. webpack.config.js 파일 생성
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader'); // .vue 로더 추가
module.exports = {
mode: "development",
// main.js를 가지고 번들링함 ( main.js에 헤더,바디,푸터 컴포넌트를 가진 인스턴스가 존재 및 마운트해주기 때문에)
entry : "./src/main.js",
output : { // entry에서 설정한 js파일을 웹팩에서 번들링한 결과 js파일.
path : path.resolve(__dirname, 'mapBundle'), // 결과물을 저장할 경로,
filename : 'mapBundle.js' // 결과물 이름
},
module: {
rules: [{
test: /\.vue$/,
use: 'vue-loader' // .vue파일 호환 가능하도록 규칙설정
},
{
test : /\.css$/,// css 호환 설정
use : ['vue-style-loader', 'css-loader']
}
],
},
plugins: [ new VueLoaderPlugin() ]
}
이렇게 한 뒤,
아래 명령어를 통해 웹팩을 빌드해준다.
npx webpack --config webpack.config.js
그럼 번들링이 완료되며, mapBundle.js이 생성된다.
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="../mapBundle/mapBundle.js"></script>
</body>
</html>
이렇게 원하는 html파일에 번들링 된 js파일을 넣어주기만 하면 ... 기존과 똑같이 잘 뜨는 것을 확인 할 수 있다~