Google Maps Web: Claude Code 활용 가이드
google maps web: Claude Code 활용. 실용적인 팁과 코드 예시를 포함합니다.
地図機能をClaude Code로통합する
店舗검색、配達追跡、不動産검색など、地図機能を必要とする애플리케이션は数多くあります。Claude Code를 활용하면 Google Maps APIやMapboxの통합、マーカー표시、ジオコーディングを효율적으로구현할 수 있습니다。
Google Maps React컴포넌트
> Google Maps APIをReact앱に통합して。
> 複数マーカー표시、情報ウィンドウ、現在地취득、
> 住所검색(ジオコーディング)를 구현해줘。
// src/components/GoogleMap.tsx
'use client';
import { useRef, useEffect, useState, useCallback } from 'react';
import { Loader } from '@googlemaps/js-api-loader';
interface MapMarker {
id: string;
position: { lat: number; lng: number };
title: string;
description?: string;
}
interface Props {
markers: MapMarker[];
center?: { lat: number; lng: number };
zoom?: number;
onMarkerClick?: (marker: MapMarker) => void;
}
export function GoogleMap({
markers,
center = { lat: 35.6812, lng: 139.7671 }, // 東京駅
zoom = 13,
onMarkerClick,
}: Props) {
const mapRef = useRef<HTMLDivElement>(null);
const [map, setMap] = useState<google.maps.Map | null>(null);
const [infoWindow, setInfoWindow] = useState<google.maps.InfoWindow | null>(null);
useEffect(() => {
const loader = new Loader({
apiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_KEY!,
version: 'weekly',
libraries: ['places'],
});
loader.load().then(() => {
if (!mapRef.current) return;
const mapInstance = new google.maps.Map(mapRef.current, {
center,
zoom,
styles: [
{ featureType: 'poi', stylers: [{ visibility: 'simplified' }] },
],
});
setMap(mapInstance);
setInfoWindow(new google.maps.InfoWindow());
});
}, []);
useEffect(() => {
if (!map || !infoWindow) return;
markers.forEach((markerData) => {
const marker = new google.maps.Marker({
position: markerData.position,
map,
title: markerData.title,
animation: google.maps.Animation.DROP,
});
marker.addListener('click', () => {
infoWindow.setContent(`
<div style="padding:8px">
<h3 style="font-weight:bold;margin-bottom:4px">${markerData.title}</h3>
${markerData.description ? `<p style="color:#666">${markerData.description}</p>` : ''}
</div>
`);
infoWindow.open(map, marker);
onMarkerClick?.(markerData);
});
});
}, [map, markers, infoWindow, onMarkerClick]);
return <div ref={mapRef} className="w-full h-96 rounded-xl" />;
}
住所검색(ジオコーディング)
// src/lib/geocoding.ts
export async function geocodeAddress(address: string) {
const geocoder = new google.maps.Geocoder();
const result = await geocoder.geocode({ address });
if (result.results.length === 0) {
throw new Error('住所が見つかりませんでした');
}
const location = result.results[0].geometry.location;
return {
lat: location.lat(),
lng: location.lng(),
formattedAddress: result.results[0].formatted_address,
};
}
export async function reverseGeocode(lat: number, lng: number) {
const geocoder = new google.maps.Geocoder();
const result = await geocoder.geocode({
location: { lat, lng },
});
return result.results[0]?.formatted_address || '住所不明';
}
店舗검색컴포넌트
// src/components/StoreLocator.tsx
'use client';
import { useState } from 'react';
import { GoogleMap } from './GoogleMap';
import { geocodeAddress } from '@/lib/geocoding';
interface Store {
id: string;
name: string;
address: string;
position: { lat: number; lng: number };
phone: string;
hours: string;
}
export function StoreLocator({ stores }: { stores: Store[] }) {
const [searchQuery, setSearchQuery] = useState('');
const [selectedStore, setSelectedStore] = useState<Store | null>(null);
const [mapCenter, setMapCenter] = useState({ lat: 35.6812, lng: 139.7671 });
const handleSearch = async () => {
try {
const result = await geocodeAddress(searchQuery);
setMapCenter({ lat: result.lat, lng: result.lng });
} catch {
alert('住所が見つかりませんでした');
}
};
const markers = stores.map((store) => ({
id: store.id,
position: store.position,
title: store.name,
description: store.address,
}));
return (
<div className="grid md:grid-cols-3 gap-6">
<div className="md:col-span-1 space-y-4">
<div className="flex gap-2">
<input
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder="住所・地名で検索"
className="flex-1 border rounded-lg px-3 py-2"
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
/>
<button onClick={handleSearch} className="bg-blue-600 text-white px-4 rounded-lg">
検索
</button>
</div>
<div className="space-y-2 max-h-96 overflow-y-auto">
{stores.map((store) => (
<div
key={store.id}
onClick={() => {
setSelectedStore(store);
setMapCenter(store.position);
}}
className={`p-3 rounded-lg cursor-pointer border ${
selectedStore?.id === store.id ? 'border-blue-500 bg-blue-50' : 'hover:bg-gray-50'
}`}
>
<h4 className="font-medium">{store.name}</h4>
<p className="text-sm text-gray-500">{store.address}</p>
<p className="text-sm text-gray-400">{store.hours}</p>
</div>
))}
</div>
</div>
<div className="md:col-span-2">
<GoogleMap
markers={markers}
center={mapCenter}
zoom={14}
onMarkerClick={(m) => setSelectedStore(stores.find((s) => s.id === m.id) || null)}
/>
</div>
</div>
);
}
現在地の취득
// src/hooks/useGeolocation.ts
import { useState, useEffect } from 'react';
export function useGeolocation() {
const [position, setPosition] = useState<{ lat: number; lng: number } | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (!navigator.geolocation) {
setError('このブラウザでは位置情報が利用できません');
return;
}
navigator.geolocation.getCurrentPosition(
(pos) => setPosition({ lat: pos.coords.latitude, lng: pos.coords.longitude }),
(err) => setError(err.message),
{ enableHighAccuracy: true, timeout: 10000 }
);
}, []);
return { position, error };
}
関連글
데이터可視化との연동は데이터可視化の구현、APIキーの관리は보안監査도 참고하세요.
Google Maps Platform 의 공식 문서(developers.google.com/maps)で最新のAPI레퍼런스を확인할 수 있습니다。
#Claude Code
#Google Maps
#map
#Mapbox
#geolocation
Related Posts
Use Cases
Use Cases
Claude Code로 리팩토링을 자동화하는 방법
Claude Code를 활용해 코드 리팩토링을 효율적으로 자동화하는 방법을 알아봅니다. 실전 프롬프트와 구체적인 리팩토링 패턴을 소개합니다.
Use Cases
Use Cases
Claude Code로 사이드 프로젝트 개발 속도를 극대화하는 방법 [예제 포함]
Claude Code를 활용해 개인 프로젝트 개발 속도를 획기적으로 높이는 방법을 알아봅니다. 실전 예제와 아이디어부터 배포까지의 워크플로를 포함합니다.
Use Cases
Use Cases
Complete CORS Configuration Guide: Claude Code 활용 가이드
complete cors configuration guide: Claude Code 활용. 실용적인 팁과 코드 예시를 포함합니다.