이번 프로젝트에서 프론트엔드 개발 중 가장 구현 난이도가 높았던 것 중 하나는 바로 지도 기능이었다.
팀원들에게 내가 맡아서 구현하겠다고 큰소리를 쳤지만, 솔직히 자바스크립트를 이번 프로젝트에서 처음 다뤄본 나로서는 구글링과 AI의 많은 도움을 받았던 것 같다.
따라서 복습 차원에서 정리해보려고 하니 참고해주길 바란다!
1. 지도 생성하기
우선 우리팀은 네이버 지도 API를 사용하기로 결정했기 때문에, 먼저 위의 링크에서 클라이언트 ID를 발급받았다. 이 클라이언트 ID를 사용하려면 스크립트를 로딩해주어야 한다.
<script src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId={클라이언트 ID}&submodules=geocoder"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
다음으로 지도를 생성하고 옵션을 설정해주었다.
function initMap(lat, lng) {
currentLocation = { lat, lng };
map = new naver.maps.Map("map", {
center: new naver.maps.LatLng(lat, lng),
zoom: 15,
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
mapDataControl: false,
});
2. 사용자의 현재 위치 불러오기
setCurrentLocation() 함수를 사용해 사용자의 현재 위치를 불러올 수 있다.
만약 불러오는데 실패했을 경우 미리 지정된 위치(서울 시청)로 표시된다.
function setCurrentLocation() {
return new Promise((resolve, reject) => {
function success(position) {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
currentLocation = { lat, lng };
resolve({ lat, lng });
} // 위치 불러오기 성공
function error() {
const lat = 37.5666103;
const lng = 126.9783882;
currentLocation = { lat, lng };
resolve({ lat, lng });
} // 위치 불러오기 실패
사용자의 현재 위치가 마커로 표시될때, 마커를 아래와 같이 커스터마이징 할 수 있다.
var currentLocationIcon = {
content: '<img src="' + staticUrl + 'image/now-marker.svg" alt="Current Location" style="width: 14px; height: 14px;">',
size: new naver.maps.Size(14, 14),
anchor: new naver.maps.Point(7, 7)
};
currentLocationMarker = new naver.maps.Marker({
position: new naver.maps.LatLng(lat, lng),
map: map,
icon: currentLocationIcon
});
3. 다중 마커 표시하기
우리 서비스는 여행 계획을 네 가지 장소 카테고리(PLAY, EAT, STAY, OTHERS)로 분류하여 DB에 저장하는 방식인데, 이 저장된 장소의 위치와 정보를 불러와 각 카테고리에 맞는 마커로 지도에 표시해야 했다.
function addTravelPlanMarkers() {
// travel_plans 목록에서 각 여행 계획에 대해 반복문 실행
{% for plan in travel_plans %}
// 여행 계획에 주소가 있는 경우에 마커 추가
{% if plan.address %}
// 주소를 이용해 좌표를 얻기 위해 네이버 지도 API의 지오코딩 서비스 호출
naver.maps.Service.geocode({
query: '{{ plan.address }}' // 여행 계획의 주소를 쿼리로 사용
}, function(status, response) {
// 지오코딩이 성공적으로 완료된 경우
if (status === naver.maps.Service.Status.OK) {
// 첫번째 주소의 좌표 가져오기
var result = response.v2.addresses[0];
var lat = result.y;
var lng = result.x;
// 마커 옵션 설정
var markerOptions = {
position: new naver.maps.LatLng(lat, lng), // 마커 위치를 위도와 경도로 설정
map: map, // 마커를 표시할 지도 설정
icon: getMarkerIcon('{{ plan.category }}') // 여행 계획의 카테고리에 따라 마커 아이콘 설정
};
// 마커를 생성하고 지도에 추가
var marker = new naver.maps.Marker(markerOptions);
markers.push(marker); // 마커를 markers 배열에 저장
다음으로 앞서 현재 위치를 표시할 때 마커를 커스터마이징했던 방식과 유사하게 카테고리별로 다른 마커 이미지를 불러오도록 설정했다.
function getMarkerIcon(category) {
const iconPaths = {
'play': staticUrl + 'image/play-marker.svg',
'eat': staticUrl + 'image/eat-marker.svg',
'stay': staticUrl + 'image/stay-marker.svg',
'others': staticUrl + 'image/others-marker.svg'
};
// 주어진 카테고리가 iconPaths 객체에 존재하는 경우
if (category in iconPaths) {
return {
content: `<img src="${iconPaths[category]}" alt="${category} marker" style="width: 35px; height: 35px;">`,
size: new naver.maps.Size(35, 35),
anchor: new naver.maps.Point(17.5, 35)
};
}
// 카테고리가 iconPaths에 없는 경우(기본 아이콘 반환)
return {
content: `<img src="${staticUrl}image/default-marker.svg" alt="default marker" style="width: 35px; height: 35px;">`,
size: new naver.maps.Size(35, 35),
anchor: new naver.maps.Point(17.5, 35)
};
}
차이점이 있다면, getMarkerIcon 함수는 다양한 카테고리에 대해 동적으로 마커 아이콘을 설정할 수 있어 재사용성이 높은 반면, 현재 위치를 표시하는 방식은 특정 마커에 대해 고정된 아이콘을 설정하므로 재사용성이 낮다는 것이다.
추가적으로 마커를 클릭했을 때 이벤트 함수를 추가하여 정보창이 표시되도록 했다.
프로젝트를 마치며..
사실 구현 당시에는 그냥 복붙한 코드들도 많고 var을 막 선언해서 쓰기도 했다..! 또 동기 비동기 처리도 아직 제대로 이해하지 못했다고 생각한다.. 그래서 다음 학기에는 자바스크립트를 한번 제대로 공부해보려고 한다!
여러분도 하시는 프로젝트 모두 화이팅입니다 :)
'프로젝트 > 오디' 카테고리의 다른 글
#1 CSS 변수로 디자인 시스템 구축하기 (2) | 2024.08.24 |
---|