728x90
사용자가 100개 이상의 북마커를 관리하며,
- 사용자 반경 500m 내의 북마커만 지도에 표시
- 지도 화면에 보이는 북마커만 표시
이 두 가지 버전을 토글 버튼으로 전환하는 기능을 구현하는 방법을 정리해볼게.
1. 개요 (전체 흐름)
- 프론트엔드:
- navigator.geolocation.watchPosition()으로 사용자의 위치를 실시간으로 감지
- 카카오맵 API를 사용하여 지도를 표시하고 북마커 렌더링
- 토글 버튼 클릭 시 반경 500m 또는 화면 내 북마커 모드 전환
- 백엔드 (NestJS):
- geolib을 사용하여 반경 500m 이내의 북마커 필터링
- 클라이언트에서 요청 시 현재 지도 화면 내 북마커만 반환
2. 백엔드 (NestJS) 구현
(1) geolib을 사용하여 반경 500m 내 북마커 필터링
import { Controller, Get, Query } from '@nestjs/common';
import { getDistance, isPointWithinRadius } from 'geolib';
// 북마커 데이터 (DB에서 가져올 수도 있음)
const BOOKMARKS = [
{ id: 1, name: "A 북마커", latitude: 37.5665, longitude: 126.9780 },
{ id: 2, name: "B 북마커", latitude: 37.5651, longitude: 126.9768 },
{ id: 3, name: "C 북마커", latitude: 37.5642, longitude: 126.9755 },
// ... 100개 이상 추가
];
@Controller('bookmarks')
export class BookmarkController {
// 반경 500m 내 북마커 필터링
@Get('nearby')
getNearbyBookmarks(
@Query('latitude') latitude: string,
@Query('longitude') longitude: string
) {
const userLocation = { latitude: parseFloat(latitude), longitude: parseFloat(longitude) };
const nearbyBookmarks = BOOKMARKS.filter(marker =>
isPointWithinRadius(
{ latitude: marker.latitude, longitude: marker.longitude },
userLocation,
500 // 500m 이내 필터링
)
);
return nearbyBookmarks;
}
// 현재 지도 화면 내 북마커 필터링
@Get('visible')
getVisibleBookmarks(
@Query('minLat') minLat: string,
@Query('maxLat') maxLat: string,
@Query('minLng') minLng: string,
@Query('maxLng') maxLng: string
) {
return BOOKMARKS.filter(marker =>
marker.latitude >= parseFloat(minLat) &&
marker.latitude <= parseFloat(maxLat) &&
marker.longitude >= parseFloat(minLng) &&
marker.longitude <= parseFloat(maxLng)
);
}
}
📌 두 가지 API 제공:
- /bookmarks/nearby → 사용자 반경 500m 이내 북마커 반환
- /bookmarks/visible → 현재 지도 화면에 보이는 북마커 반환
3. 프론트엔드 (카카오맵 API) 구현
(1) 카카오맵 API 로드
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=YOUR_KAKAO_MAP_API_KEY"></script>
(2) 지도 표시 + 토글 버튼 생성
<button id="toggleMode">모드 변경</button>
<div id="map" style="width: 100%; height: 500px;"></div>
(3) JavaScript로 지도 초기화
let map;
let markers = [];
let mode = "nearby"; // 기본 모드는 반경 500m
function initMap() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(position => {
const userLat = position.coords.latitude;
const userLng = position.coords.longitude;
const mapContainer = document.getElementById('map');
const mapOptions = {
center: new kakao.maps.LatLng(userLat, userLng),
level: 5
};
map = new kakao.maps.Map(mapContainer, mapOptions);
// 초기 모드의 북마커 로드
loadBookmarks(userLat, userLng);
// 지도 이동 이벤트 리스너 추가
kakao.maps.event.addListener(map, 'bounds_changed', () => {
if (mode === "visible") {
loadVisibleBookmarks();
}
});
// 토글 버튼 클릭 시 모드 변경
document.getElementById("toggleMode").addEventListener("click", () => {
mode = mode === "nearby" ? "visible" : "nearby";
loadBookmarks(userLat, userLng);
});
});
}
}
window.onload = initMap;
4. 북마커 로드 함수
(1) 반경 500m 내 북마커 로드
function loadNearbyBookmarks(userLat, userLng) {
fetch(`https://your-api.com/bookmarks/nearby?latitude=${userLat}&longitude=${userLng}`)
.then(response => response.json())
.then(bookmarks => {
clearMarkers();
bookmarks.forEach(bookmark => addMarker(bookmark));
});
}
(2) 지도 화면 내 북마커 로드
function loadVisibleBookmarks() {
const bounds = map.getBounds();
const minLat = bounds.getSouthWest().getLat();
const maxLat = bounds.getNorthEast().getLat();
const minLng = bounds.getSouthWest().getLng();
const maxLng = bounds.getNorthEast().getLng();
fetch(`https://your-api.com/bookmarks/visible?minLat=${minLat}&maxLat=${maxLat}&minLng=${minLng}&maxLng=${maxLng}`)
.then(response => response.json())
.then(bookmarks => {
clearMarkers();
bookmarks.forEach(bookmark => addMarker(bookmark));
});
}
(3) 공통 마커 추가 및 삭제 함수
function addMarker(bookmark) {
const marker = new kakao.maps.Marker({
position: new kakao.maps.LatLng(bookmark.latitude, bookmark.longitude),
map: map
});
markers.push(marker);
}
function clearMarkers() {
markers.forEach(marker => marker.setMap(null));
markers = [];
}
5. 최종 동작 방식
- 사용자가 토글 버튼 클릭 시 mode 변경 (nearby ↔ visible)
- nearby 모드
- 현재 사용자 위치 기준 500m 이내 북마커 표시
- visible 모드
- 현재 지도 화면에 보이는 북마커만 표시
- 지도 이동 시 자동 업데이트
6. 최적화 및 추가 고려사항
✅ 백엔드 캐싱 적용:
- 요청이 많아지면 Redis 같은 캐시 시스템 활용 가능
✅ 프론트엔드 위치 업데이트 간격 조정: - 너무 자주 업데이트하면 배터리 소모 증가 (예: 10초마다 업데이트)
✅ 사용자 위치 기반 마커 클러스터링 적용: - 지도에 너무 많은 마커가 표시되면 성능 저하 가능, 카카오맵 클러스터 기능 활용
7. 결론
🚀 NestJS와 카카오맵 API를 활용하여
✅ 반경 500m 내 북마커 표시
✅ 현재 지도 화면 내 북마커 표시
✅ 토글 버튼으로 모드 전환
하는 기능을 깔끔하게 구현할 수 있어!
'게임서버-스파르타코딩NodeJs_7기 > CH6 최종 프로젝트' 카테고리의 다른 글
발키에서 북마커 일부만 가져오기 (0) | 2025.02.27 |
---|---|
사용자와 북마커 계획 (0) | 2025.02.26 |
위치 기반 북마크 도착 이벤트 기능 구현 계획 (0) | 2025.02.26 |
발키에서 복수 데이터 읽어오기 (0) | 2025.02.25 |
마커로 길찾기 (0) | 2025.02.20 |