지도 제작 웹사이트 GentleMap
Table of Contents
Vue.js & Firebase 기반으로 주소가 담긴 Excel 파일을 파싱하여 지도를 만들어주는 반응형 웹 어플리케이션 GentleMap을 개발한 이야기를 공유합니다.
프로젝트 소개
사이드 프로젝트로 전체 개발 기간은 3개월 정도 소요되었고, 혼자서 개발하였습니다.
최종 결과물은 https://gentle-map.devstory.co.kr에서 이용하실 수 있습니다.
개발 동기
100명의 자원 봉사자들과 팀을 이루어 120가구에 반찬을 나누는 사랑의 반찬나눔 봉사와 취약계층 60가구를 대상으로 화재감지기 설치 봉사를 진행하였는데, 당시 Android 지도 앱을 만들어 봉사활동을 편하게 진행할 수 있었습니다.
이후 다른 사람들도 비슷한 니즈를 가지고 있을것이라 생각이 들어 누구든지 손쉽게 지도를 만들 수 있는 웹 플랫폼인 Gentle Map을 만들어 보았습니다.
기능 소개
- Excel 데이터를 지도상에 시각화
- 활동하는 팀 수에 맞추어 동선이 최소화되도록 마커 자동 분배
- 관심있는 팀의 마커만 볼 수 있는 마커 필터링 기능
- 모든 마커의 상태가 실시간으로 동기화 되어 진행상황로 실시간으로 모니터링 가능
- 카카오톡 계정을 이용한 소셜 로그인 기능
- 카카오톡 링크 이용하여 손쉽게 프로젝트 초대 기능
- 프로젝트 참가자는 회원가입 없이 비밀번호만으로 참여 가능
- 별도의 어플리케이션 설치 없이 모바일 웹을 이용하여 이용 가능
- 모바일에서도 이용가능한 반응형 디자인
- HTML5의 Geolocation을 이용한 GPS 기능
개발 내용
Vue.js 기반의 반응형 웹 어플리케이션과 Firebase 기반의 백엔드로 설계하였습니다.
✔︎ FrontEnd
✔︎ BackEnd
Design
처음에는 GPS 기능 때문에 모바일 어플리케이션 형태를 고려하다가, HTML5 Geolocation 성능이 생각보다 괜찮아 모바일 환경에서도 별도의 설치 없이 이용가능하도록 반응형 웹사이트로 구현하였습니다.
UI는 Element와 Vusax를 조합하여 사용하였습니다. 두 라이브러리 모두 테마 변경 기능과 반응형 디자인을 지원합니다.
✔︎ Element와 Vuesax 사용시 주의할 점 (2019.08 기준)
- Element의 Dialog 컴포넌트는 모바일에 지원이 안됨
- Vuesax Dialog 컴포넌트 위에 Element의 Select 컴포넌트 사용시 선택창이 보이지 않음
- Vuesax는 Safari에서 Select 컴포넌트가 작동하지 않음
- Vuesax는 Safari에서 Button 컴포넌트의 클릭 effect 효과가 사라지지 않음
Kakao API
이번 프로젝트에서는 로그인, 지도, 주소 좌표변환 및 공유 등 다양한 Kakao API를 이용하여 개발하였습니다.
✔︎ 이용한 Kakao API 목록
- Kakao Map : 지도 및 주소 좌표변환 기능
- Kakao Login : 카카오톡 소셜 로그인
- Kakao Link : 프로젝트 초대 기능
지도 API는 Google Map, Naver Map, Kakao Map을 검토하였는데, Web Dynamic Map은 Kakao에서만 월 30만회 무료 사용량을 제공하여 Kakao Map을 선택하였습니다. (20.05.02 기준으로 네이버도 월 천만건 무료로 풀렸네요)
프로젝트를 생성 및 관리를 위해선 로그인이 필요합니다. 이때 회원가입 과정을 손쉽게 할 수 있도록 Kakao 소셜 로그인 기능을 이용하였는데, Firebase에서는 카카오톡 소셜 로그인을 정식적으로 지원하지 않기 때문에 Firebase Functions에 Custom Token을 발급하는 함수를 만들고, 클라이언트에서 signInWithCustomToken을 이용하여 로그인하도록 구현하였습니다.
Hosting
HTML5 Geolocation을 이용하기 위해선, HTTPS가 필요합니다. Firebase Hosting에서는 기본적으로 SSL을 제공해주기 때문에 별도로 인증서를 구매하지 않고 HTTPS를 이용할 수 있습니다. 또한 Custom Domain도 HTTPS가 지원되기 때문에 gentle-map.devstory.co.kr 를 연결하여 호스팅하였습니다.
Firestore
마커 상태를 새로고침 없이 실시간으로 동기화 되도록 Firestore를 이용하였습니다. 초기에 마커들의 상태를 하나의 Document 안에 배열로 구현하였는데, Firestore에서는 배열의 특정 원소만을 업데이트하는 기능을 지원하지 않아 변경된 배열 전체를 업데이트하도록 구현하였습니다. 그런데 짧은 시간 안에 두 유저가 업데이트를 요청하는 경우, 아래 sequence diagram 처럼 늦게 요청한 유저의 요청값이 이전 유저의 값으로 동기화되어 화면상 결과가 데이터베이스와 달라지는 문제가 발생하였습니다.
해당 문제는 마커의 상태 변경시, 관심 마커 이외에 모든 마커를 함께 업데이트하기 때문에 발생하는 문제입니다. 따라서 전체 마커를 하나의 문서에 속한 배열이 아닌, 마커 하나당 개별 문서로 구현하고 각 문서 별 리스너를 등록해주어 마커들의 상태 값을 개별적으로 업데이트 할 수 있도록 구현하여 문제를 해결하였습니다.
Firebase Functions & Authentication
유저에 따른 Firestore 접근 규칙을 설정하려면 Firebase Authentication과 로그인 기능이 연동되어야합니다. Firebase Authentication에서 카카오톡 소셜 로그인을 지원하지 않기 때문에, Firebase Functions에 Node.js 기반의 Custom Token 발급 함수를 만들고, 클라이언트에서 signInWithCustomToken을 이용하여 로그인하도록 구현하였습니다.
1 | // 도쿄리전 사용 |
전체 로그인 순서는 먼저 카카오톡에 로그인 한 뒤, Firebase Functions에서 토큰을 발급받고, 해당 토큰으로 signInWithCustomToken를 호출하여 최종 로그인을 하게 됩니다. 이후 Firestore에 접근하는 경우 아래와 같은 규칙에 따라 권한을 확인하게 됩니다.
1 | service cloud.firestore { |
마치며
Firebase와 Vue를 이용하여 반응형에 실시간 동기화까지 구현된 지도 서비스를 구현해 보았습니다. 다만 SPA의 한계로 SEO가 안되는 점이 아쉬웠는데, 다음번 프로젝트에서는 SSR Framework를 고려해 보도록 하겠습니다.