구글맵 지도 기능 구현 순서
1. Google Geocoding API 키 설정:
- console.cloud.google.com에 접속하여 API 및 서비스로 이동합니다.
- API 및 서비스 사용 설정을 선택한 후 geocode를 검색하여 활성화하고 API 키를 생성합니다.
- 생성한 API 키를 .env 파일에 추가합니다. 예: NEXT_PUBLIC_GOOGLE_GEOCODING_API_KEY=YOUR_API_KEY
2.새 컴포넌트 생성:
- components 폴더에 PropertyMap.jsx 파일을 생성합니다.
- PropertyMap 함수 컴포넌트를 만들고 property를 매개변수로 받습니다.
- 기본적으로 div 태그에 "map" 텍스트를 넣습니다.
- use client 지시자를 추가합니다.
3.필요한 패키지 설치:
- 터미널에서 다음 명령어를 실행하여 패키지를 설치합니다
npm install react-geocode mapbox-gl react-map-gl
4. 상태 설정:
- useState를 사용하여 lat, lng, viewport, loading, geocodeError 상태를 정의합니다.
- 초기 상태 값을 설정합니다.
5. Google Geocoding API 설정:
setDefaults 함수를 사용하여 API 키와 기본 설정을 추가합니다.
API 키는 환경 변수에서 가져옵니다: process.env.NEXT_PUBLIC_GOOGLE_GEOCODING_API_KEY
6.위도 및 경도 가져오기:
useEffect를 사용하여 컴포넌트가 마운트될 때 fromAddress 함수를 호출하여 주소로부터 위도와 경도를 가져옵니다.
비동기 함수 fetchCoords를 만들어 try-catch-finally 블록을 사용하여 API 요청을 처리합니다.
property 객체에서 주소 정보를 가져와 fromAddress 함수에 전달합니다.
응답에서 위도와 경도를 추출하여 상태를 업데이트합니다.
7.로딩 및 에러 처리:
loading 상태가 true일 경우 "loading..." 텍스트를 출력합니다.
geocodeError 상태가 true일 경우 "No location data found" 텍스트를 출력합니다.
8.PropertyMap 컴포넌트 활용:
상세 페이지 컴포넌트에서 PropertyMap 컴포넌트를 가져와 div 태그 대신 사용하고 property를 전달합니다.
"use client";
import { PropertyProps } from "@/app/properties/[id]/page";
import React from "react";
import { useEffect, useState } from "react";
import Geocode, { OutputFormat, setDefaults } from "react-geocode";
import Map, { Marker } from "react-map-gl";
import Image from "next/image";
import pin from "@/assets/images/pin.svg";
import Spinner from "@/components/Spinner";
import 'mapbox-gl/dist/mapbox-gl.css'
import { PropertyCardProps } from "./PropertyCard";
type MarkerProps = {
latitude: number;
longitude: number;
offsetLeft?: number;
offsetTop?: number;
draggable?: boolean;
// Add other properties here
};
const PropertyGoogleMap: React.FC<PropertyCardProps> = ({ property }) => {
const [lat, setLat] = useState<number | null>(null);
const [lng, setLng] = useState<number | null>(null);
const [viewport, setViewport] = useState({
latitude: 0,
longitude: 0,
zoom: 12,
width: "100%",
height: "500px",
});
const [loading, setLoading] = useState(true);
const [geocodeError, setGeocodeError] = useState(false);
setDefaults({
key: process.env.NEXT_PUBLIC_GOOGLE_GEOCODING_API_KEY,
language: "ko",
region: "KR",
outputFormat: OutputFormat.JSON,
});
useEffect(() => {
// Geocode.setKey(process.env.NEXT_PUBLIC_GOOGLE_GEOCODING_API_KEY as string);
// Geocode.setLanguage("ko");
// Geocode.setRegion("KR");
// Geocode.setLocationType("ROOFTOP");
const fetchCoords = async () => {
setLoading(true);
try {
let addressText=`${property.location.address1}
${property.location.address2} ${property.location.address3} ${property.location.zipcode}`;
addressText= '경기도 수원시 덕영대로 535번길'
const res = await Geocode.fromAddress(addressText);
if (res.results.length === 0) {
setGeocodeError(true);
return;
}
const { lat, lng } = res.results[0].geometry.location;
setLat(lat);
setLng(lng);
setViewport(prevViewport => ({
...prevViewport,
latitude: lat,
longitude: lng,
}));
} catch (error) {
console.log("에러 =============>",error);
setGeocodeError(true);
} finally {
setLoading(false);
}
};
fetchCoords();
}, [property]);
if (loading) return <Spinner loading={loading} />;
if (geocodeError) {
return <div className="text-xl">No location data found</div>;
}
return (
!loading && ( <Map
mapboxAccessToken={process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN}
// mapLib={mapboxgl}
initialViewState={{
longitude:lng!,
latitude:lat!,
zoom:15
}}
style={{ width: 600, height:400 }}
mapStyle="mapbox://styles/mapbox/streets-v11"
>
{lat && lng && (
<Marker latitude={lat} longitude={lng} offset={[-10,-20]} >
<Image src={pin} alt="Location Pin" width={40} height={40}/>
</Marker>
)}
</Map>
)
);
};
export default PropertyGoogleMap;
setDefaults({
key: process.env.NEXT_PUBLIC_GOOGLE_GEOCODING_API_KEY,
language: "ko",
region: "KR",
outputFormat: OutputFormat.JSON,
});
setDefaults 함수는 react-geocode 라이브러리에 존재하지 않습니다.
대신 react-geocode는 setApiKey, setLanguage, setRegion, setLocationType과 같은 개별적인 설정 함수를 제공합니다.
따라서 setDefaults 대신 개별 설정 함수들을 사용해야 합니다.
2. Mapbox 지도 표시
Mapbox 설정
1)Mapbox API 키 설정:
Mapbox에 가입하고 대시보드에서 토큰을 생성합니다.
.env 파일에 NEXT_PUBLIC_MAPBOX_TOKEN으로 저장합니다.
NEXT_PUBLIC_MAPBOX_TOKEN=pk.abcdef1234567890
2)필요한 패키지 설치:
react-map-gl과 mapbox-gl 패키지를 이미 설치했습니다.
3)지도 컴포넌트 작성:
PropertyMap 컴포넌트를 수정하여 Mapbox 지도를 표시합니다.
useEffect에서 좌표를 가져와 상태를 업데이트합니다.
지도 렌더링 코드
1)필요한 모듈 가져오기:
"use client";
import { PropertyProps } from "@/app/properties/[id]/page";
import React, { useEffect, useState } from "react";
import Geocode from "react-geocode";
import Map, { Marker } from "react-map-gl";
import Image from "next/image";
import pin from "@/assets/images/pin.svg";
import Spinner from "@/components/Spinner";
2)PropertyMap 컴포넌트:
const PropertyMap: React.FC<PropertyProps> = ({ property }) => {
const [lat, setLat] = useState<number | null>(null);
const [lng, setLng] = useState<number | null>(null);
const [viewport, setViewport] = useState({
latitude: 0,
longitude: 0,
zoom: 12,
width: "100%",
height: "500px",
});
const [loading, setLoading] = useState(true);
const [geocodeError, setGeocodeError] = useState(false);
useEffect(() => {
Geocode.setApiKey(process.env.NEXT_PUBLIC_GOOGLE_GEOCODING_API_KEY as string);
Geocode.setLanguage("ko");
Geocode.setRegion("KR");
Geocode.setLocationType("ROOFTOP");
const fetchCoords = async () => {
try {
const res = await Geocode.fromAddress(`${property.location.address1} ${property.location.address2} ${property.location.address3} ${property.location.zipcode}`);
if (res.results.length === 0) {
setGeocodeError(true);
return;
}
const { lat, lng } = res.results[0].geometry.location;
setLat(lat);
setLng(lng);
setViewport(prevViewport => ({
...prevViewport,
latitude: lat,
longitude: lng,
}));
} catch (error) {
console.log(error);
setGeocodeError(true);
} finally {
setLoading(false);
}
};
fetchCoords();
}, [property]);
if (loading) return <Spinner />;
if (geocodeError) {
return <div className="text-xl">No location data found</div>;
}
return (
<Map
initialViewState={viewport}
style={{ width: viewport.width, height: viewport.height }}
mapStyle="mapbox://styles/mapbox/streets-v11"
mapboxAccessToken={process.env.NEXT_PUBLIC_MAPBOX_TOKEN}
>
{lat && lng && (
<Marker latitude={lat} longitude={lng} anchor="bottom">
<Image src={pin} alt="location" width={40} height={40} />
</Marker>
)}
</Map>
);
};
export default PropertyMap;
3) CSS 파일 추가:
- mapbox-gl의 CSS 파일을 임포트하여 스타일 문제를 해결합니다.
import 'mapbox-gl/dist/mapbox-gl.css';
요약
- API 키 설정: .env 파일에 Google Geocoding과 Mapbox 키 추가.
- 패키지 설치: react-geocode, react-map-gl 등 필요한 패키지 설치.
- 지도 컴포넌트: PropertyMap 컴포넌트 작성, 좌표를 가져와 Mapbox 지도에 마커 표시.
- CSS 추가: mapbox-gl CSS 파일 임포트.














댓글 ( 0)
댓글 남기기