FrontEnd/Vue

[Vue] Vue3 기반 프로젝트에서 카카오맵 API를 통해 지도를 뿌려보자. (1) 지도 가져오기

모찌바라기 2022. 3. 7. 19:52
728x90
반응형

 

 

예전에 카카오맵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파일을 넣어주기만 하면 ... 기존과 똑같이 잘 뜨는 것을 확인 할 수 있다~

 

728x90
반응형