
📕 GET 요청 처리 및 데이터베이스 조회
- GET 함수 정의
export async function GET(request: NextRequest, { params }: { params: { id: string } }) {
const supabase = createClient();
const { id: post_id } = params;
이 함수는 GET 요청을 처리한다.
함수는 request 객체와 params 객체를 인수로 받는다.
params 객체에서 id를 추출하여 post_id로 할당한다.
이 post_id는 데이터베이스에서 특정 게시물과 관련된 데이터를 조회하는 데 사용된다.
- 데이터베이스에서 데이터 가져오기
try {
const { data: placesData, error: placesError } = await supabase
.from('schedule')
.select('lat, long, places, day')
.eq('post_id', post_id);
supabase 클라이언트를 사용하여 schedule 테이블에서 특정 post_id와 연관된 데이터를 조회한다.
select 메서드를 사용해 lat(위도), long(경도), places(장소 이름), day(날짜) 필드를 선택하여 가져온다.
eq 메서드를 사용해 post_id가 주어진 post_id와 일치하는 데이터를 필터링한다.
이 요청의 결과로 placesData에 조회된 데이터가, placesError에 오류가 저장된다.
📕 상태 초기화 및 데이터 패칭
- 상태 및 스크립트 초기화
const clientId = process.env.NEXT_PUBLIC_NCP_CLIENT_ID!;
const isScriptLoaded = useNaverMapScript(clientId);
const params = useParams();
const postId = Array.isArray(params.id) ? params.id[0] : params.id;
const [selectedDay, setSelectedDay] = useState<string>('Day 1');
const [mapInstance, setMapInstance] = useState<any>(null);
clientId: 네이버 지도 API를 사용하기 위한 클라이언트 ID를 환경 변수에서 가져온다.
useNaverMapScript: 네이버 지도 API 스크립트를 로드하는 커스텀 훅으로, 스크립트 로딩 상태를 관리한다.
useParams: 현재 페이지의 URL 파라미터에서 postId를 가져와 특정 게시물의 데이터를 조회한다.
useState: selectedDay는 사용자가 선택한 날짜를 관리하며, mapInstance는 지도 객체를 관리한다.
- 데이터 패칭 함수 정의
const fetchPostAndPlaces = async (postId: string): Promise<PostAndPlacesData> => {
const response = await axios.get(`/api/detail/map/${postId}`);
const data = response.data;
const parsedPlaces: PlaceData[] = data.places.map((item: any) => ({
lat: item.lat,
long: item.long,
places: item.places,
day: item.day || 'Unknown Day'
}));
const sortedPlaces = parsedPlaces.sort((a, b) => {
const dayA = parseInt(a.day.replace('Day ', ''));
const dayB = parseInt(b.day.replace('Day ', ''));
return dayA - dayB;
}));
return { places: sortedPlaces };
};
fetchPostAndPlaces: 주어진 postId를 사용해 API에서 관련된 장소 데이터를 가져온다.
parsedPlaces: API에서 받은 데이터를 적절한 형식으로 변환한다.
sortedPlaces: 날짜(day)를 기준으로 장소 데이터를 정렬하여, 일정을 올바른 순서로 보여준다.
- 데이터 패칭 및 상태 관리
const { data, error, isLoading } = useQuery<PostAndPlacesData>({
queryKey: ['postAndPlaces', postId],
queryFn: () => fetchPostAndPlaces(postId),
});
useQuery
: React Query를 사용하여 데이터를 비동기로 패칭한다.
로딩 중인지(isLoading), 에러가 발생했는지(error), 데이터를 성공적으로 가져왔는지(data) 상태를 관리한다.
📕 지도 초기화 및 마커 관리
- 지도 초기화 및 마커 설정
useEffect(() => {
if (isScriptLoaded && data && data.places.length > 0) {
if (!selectedDay || selectedDay !== 'Day 1') {
setSelectedDay('Day 1');
}
const selectedPlaceData = data.places.find((place) => place.day === 'Day 1');
if (selectedPlaceData) {
const map = new window.naver.maps.Map('map', {
center: new window.naver.maps.LatLng(selectedPlaceData.lat[0], selectedPlaceData.long[0]),
zoom: 10,
});
setMapInstance(map);
updateMarkers(map, selectedPlaceData);
window.naver.maps.Event.addListener(map, 'click', () => {
map.setCenter(new window.naver.maps.LatLng(selectedPlaceData.lat[0], selectedPlaceData.long[0]));
map.setZoom(12);
});
}
}
}, [isScriptLoaded, data]);
useEffect
: 네이버 지도 API 스크립트가 로드되고 데이터가 존재할 때 지도를 초기화한다.
기본적으로 'Day 1'에 해당하는 장소를 중심으로 지도를 설정한다.
updateMarkers
: 초기화된 지도에 장소들을 마커로 표시한다.
마커 클릭 시 해당 장소로 지도가 이동하며 줌이 조정된다.
- 마커 업데이트 함수
const updateMarkers = (map: any, selectedPlaceData: PlaceData | undefined) => {
if (!map || !selectedPlaceData) return;
map.markers?.forEach((marker: any) => marker.setMap(null));
const newMarkers = selectedPlaceData.lat
.map((lat, index) => {
if (index < selectedPlaceData.long.length) {
const markerContent = `
<div class="w-6 h-6 web:w-11 web:h-11 text-white bg-primary-300 flex items-center p-2 justify-center border-2 border-white rounded-full">
${index + 1}
</div>
`;
return new window.naver.maps.Marker({
position: new window.naver.maps.LatLng(lat, selectedPlaceData.long[index]),
map: map,
title: selectedPlaceData.places[index].title,
icon: {
content: markerContent,
anchor: new window.naver.maps.Point(12, 12),
},
});
}
})
.filter((marker) => marker !== undefined);
map.markers = newMarkers;
};
updateMarkers
: 기존의 마커들을 제거한 후, 새롭게 마커를 추가한다.
마커는 lat(위도)와 long(경도) 값을 기반으로 위치가 설정된다.
- 선택한 날에 따른 마커 업데이트
useEffect(() => {
if (mapInstance && data && selectedDay) {
const selectedPlaceData = data.places.find((place) => place.day === selectedDay);
updateMarkers(mapInstance, selectedPlaceData);
}
}, [mapInstance, data, selectedDay]);
useEffect
: 사용자가 선택한 날짜(selectedDay)에 따라 지도에 표시되는 마커를 업데이트한다.
사용자가 다른 날짜를 선택할 때마다 호출된다.
🖥️ 결과물