import { useEffect, useState } from 'react' import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet' import { Icon } from 'leaflet' import { Attraction } from '../types' import 'leaflet/dist/leaflet.css' interface MapProps { attractions: Attraction[] } // 커스텀 마커 아이콘 설정 const attractionIcon = new Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }) const Map = ({ attractions }: MapProps) => { const [isMounted, setIsMounted] = useState(false) // 클라이언트 사이드에서만 렌더링 (SSR 에러 방지) useEffect(() => { setIsMounted(true) }, []) // 구마모토 중심 좌표 const kumamotoCenter: [number, number] = [32.8031, 130.7079] // 타일 서버 URL (Docker 컨테이너 또는 기본 OSM) const tilesUrl = import.meta.env.VITE_MAP_TILES_URL || 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' const isCustomTiles = !!import.meta.env.VITE_MAP_TILES_URL // 서버 사이드에서는 로딩 화면 표시 if (!isMounted) { return (

🗺️ 구마모토 지도

지도를 불러오는 중...

) } return (

🗺️ 구마모토 지도

OpenStreetMap contributors' } maxZoom={18} /> {attractions.map((attraction) => ( attraction.coordinates && (

{attraction.nameKo}

{attraction.description}

📍 {attraction.location}

{attraction.website && ( 웹사이트 방문 )}
) ))}
{isCustomTiles ? ( <> 🎯 구마모토 전용 지도 서버 사용 중!
• 빠른 로딩 속도와 오프라인 지원
• Google Maps API 키 불필요
• 구마모토 지역 최적화된 지도 데이터
) : ( <> 🌍 OpenStreetMap 사용 중
• 무료 오픈소스 지도 서비스
• API 키 불필요
• Docker 지도 서버 실행 시 더 빠른 성능 제공
)}
) } export default Map