The Debugging Chronicles : "코드의 미학"
[카카오 지도 API] 2. 화면에 보이는 곳에만 필터링하여 마커 찍기(Next.js,TypeScript) 본문
FrontEnd
[카카오 지도 API] 2. 화면에 보이는 곳에만 필터링하여 마커 찍기(Next.js,TypeScript)
sweetseonah1004 2025. 1. 14. 17:21
2.5주 동안 카카오지도와 씨름하면서 가장 힘들었던 필터링하여 적용하기
2. 화면에 보이는 곳에만 필터링하여 마커 찍기
이전 글 참고.
https://sweetseonah1004.tistory.com/203
화면 반경 내에 마커를 찍었다.
하지만 반경이 화면의 크키를 넘어서
불필요한 데이터까지 가지고 오고 있었다.
원이 찍그러졌지만
R 반지름 값을 중심으로 원의 반경내의 데이터들을 다 가지고 와서 마커를 찍는 다면
너무 많은 불필요한 값들이 오고 있다.
그래서 필터링이 필요했다.
아이디어는
getAllFranchises라는 함수에서
getFranchiesAll API 로부터 응답값을 받아오고,
받아온 데이터를 상태(setAllList)로 업데이트 한다.
getAllFranchises함수가 쓰여지는 곳 마다
업데이트 된 함수인 getAllFranchises 의 결과 값으로 필터링하는 getAllFranchisesAndFilter 함수로 대체되도록 하는 것이다.
const filterLocation = (
allList: AllFranchiseResult,
swLat: number, // 남서쪽 위도
swLng: number, // 남서쪽 경도
neLat: number, // 북동쪽 위도
neLng: number // 북동쪽 경도
) => {
// 필터링 조건에 맞는 데이터를 반환합니다.
const result = allList.result.filter((element) => {
// null 또는 undefined 체크
if (!element.geo_lat || !element.geo_lng) {
return false; // 좌표 정보가 없으면 제외
}
const lat = parseFloat(element.geo_lat); // 위도 값
const lng = parseFloat(element.geo_lng); // 경도 값
// 좌표 범위 내의 데이터만 필터링
return (
lat >= swLat && lat <= neLat && // 위도: 남 → 북
lng >= swLng && lng <= neLng // 경도: 서 → 동
);
});
return result;
};
const getAllFranchisesAndFilter = (
updatedParams: AllFranchiseParam,
swLatLng: kakao.maps.LatLng,
neLatLng: kakao.maps.LatLng
) => {
return getAllFranchises(updatedParams)
.then((rs) => {
if (!rs || !rs.result || rs.result.length === 0) {
return null;
}
//데이터 필터링
const filteredData = filterLocation(
rs,
swLatLng.getLat(),
swLatLng.getLng(),
neLatLng.getLat(),
neLatLng.getLng()
);
// 리스트 업데이트
setAllList({
result: filteredData,
total: filteredData.length.toString(),
});
return filteredData;
})
.catch((error) => {
return null;
});
};
그리고 함수가 사용되었던 곳 중에 하나인
체크박스 상태에 따라 데이터 가져오기
// 체크박스 상태에 따라 데이터 가져오기
useEffect(() => {
const fetchFilteredData = async (typeValue:string) => {
resetList('all');
// 지도 범위 가져오기
const bounds = await getMapBounds();
const swLatLng = bounds.getSouthWest(); // 남서쪽 좌표
const neLatLng = bounds.getNorthEast(); // 북동쪽 좌표
// 파라미터 업데이트 및 데이터 요청
setAllFranchiseParams((prev) => {
const updatedParams = {
...prev,
geo_lat: mapCenter.lat,
geo_lng: mapCenter.lng,
type: typeValue,
};
getAllFranchisesAndFilter(updatedParams, swLatLng, neLatLng);
return updatedParams;
});
};
if (isInitialRender) {
setIsInitialRender(false); // 이후로는 실행되지 않음
return;
}
if (fillters.franchise && fillters.no_franchise) {
// 가맹점, 비가맹점 모두 선택
fetchFilteredData('3');
} else if (fillters.franchise && !fillters.no_franchise) {
// 가맹점만 선택
fetchFilteredData('1');
} else if (!fillters.franchise && fillters.no_franchise) {
// 비가맹점만 선택
fetchFilteredData('2');
} else {
// 가맹점, 비가맹점 둘다 선택 안됨
resetList('company');
resetList('franchise');
resetList('all');
}
}, [fillters]);
그리고 적용하기 제일 애를 먹은 시/도 , 구/군 셀렉트 박스
const selectCity = async (event: SelectChangeEvent) => {
setFranchiesList({
result: [],
total: '0',
});
let selectedCityName = event.target.value as string;
let searchCityName = selectedCityName;
// "광주" 선택 시 검색은 "광주광역시"로, UI는 "광주"로 유지
if (selectedCityName === "광주") {
searchCityName = "광주광역시"; // 검색용
}
const currentSelectedCity = searchCityName;
// UI에는 "광주"로 표시
setSelectedCity(selectedCityName);
setSelectedGu('');
await getLocationCodes(selectedCityName);
let updatedParams = {
...allFranchiseParams,
city: selectedCityName,
location: '',
};
setAllFranchiseParams(updatedParams);
if (searchCityName === '') {
setAllFranchiseParams((prev) => {
const updatedParams = {
...prev,
city: '',
location: '',
};
// 지도 위치 변경 없이 데이터만 업데이트
getAllFranchises(updatedParams);
return updatedParams;
});
}else{
// ✅ 검색어가 있을 때만 주소 검색 실행
const res = await kakaoAddressSearch(searchCityName);
if (currentSelectedCity !== searchCityName) {
return;
}
if (res.result === true && res.latitude && res.longitude) {
const latitude = parseFloat(res.latitude);
const longitude = parseFloat(res.longitude);
if (isNaN(latitude) || isNaN(longitude)) {
return;
}
handleCenterChange(latitude.toString(), longitude.toString());
moveMapCenter(latitude.toString(), longitude.toString());
// 지도 범위를 가져와서 SW/NE 좌표 계산
const bounds = await getMapBounds();
const swLatLng = bounds.getSouthWest(); // 남서쪽 좌표
const neLatLng = bounds.getNorthEast(); // 북동쪽 좌표
let distance = getDistance(
swLatLng?.getLat(),
swLatLng?.getLng(),
neLatLng?.getLat(),
neLatLng?.getLng(),
) / 2;
updatedParams = {
...updatedParams,
geo_lat: latitude.toString(),
geo_lng: longitude.toString(),
radius: distance < 1 ? 1 : setRadiusAccurate(distance),
};
await getAllFranchisesAndFilter(updatedParams, swLatLng, neLatLng);
} else {
handleCenterChange('37.5665', '126.9780');
moveMapCenter('37.5665', '126.9780');
const bounds = await getMapBounds();
const swLatLng = bounds.getSouthWest();
const neLatLng = bounds.getNorthEast();
await getAllFranchisesAndFilter(updatedParams, swLatLng, neLatLng);
}
setShouldUpdateCenter(true);
}
};
const selectGu = async (event: SelectChangeEvent) => {
setFranchiesList({
result: [],
total: '0',
});
let newLocation = event.target.value as string;
let searchCity = selectedCity;
// "광주" → "광주광역시"로 변환 (구/군 목록 조회 및 검색 시)
if (selectedCity === "광주") {
searchCity = "광주광역시";
}
let searchLocation = `${searchCity} ${newLocation}`;
// 선택한 구/군 업데이트 (UI에는 원래대로 유지)
setSelectedGu(newLocation);
// 파라미터 업데이트 (검색용 city는 광주광역시, UI는 광주)
let updatedParams = {
...allFranchiseParams,
city: selectedCity, // 검색 시 "광주광역시" 사용
location: newLocation, // 선택한 구/군
};
setAllFranchiseParams(updatedParams);
if (newLocation === '') {
setAllFranchiseParams((prev) => {
const updatedparams = {
...prev,
city: selectedCity,
location: '',
};
getAllFranchises(updatedparams);
return updatedparams;
});
} else {
// 선택한 구/군 주소 검색
const res = await kakaoAddressSearch(searchLocation);
if (res.result === true && res.latitude && res.longitude) {
const latitude = parseFloat(res.latitude);
const longitude = parseFloat(res.longitude);
if (isNaN(latitude) || isNaN(longitude)) {
return;
}
// 지도 중심 이동
handleCenterChange(latitude.toString(), longitude.toString());
moveMapCenter(latitude.toString(), longitude.toString());
// 지도 범위를 가져와서 SW/NE 좌표 계산
const bounds = await getMapBounds();
const swLatLng = bounds.getSouthWest(); // 남서쪽 좌표
const neLatLng = bounds.getNorthEast(); // 북동쪽 좌표
let distance =
getDistance(
swLatLng?.getLat(),
swLatLng?.getLng(),
neLatLng?.getLat(),
neLatLng?.getLng(),
) / 2;
// 파라미터 업데이트 (좌표, 반경 포함)
updatedParams = {
...updatedParams,
geo_lat: latitude.toString(),
geo_lng: longitude.toString(),
radius: distance < 1 ? 1 : setRadiusAccurate(distance),
};
// 필터링된 데이터 요청
await getAllFranchisesAndFilter(updatedParams, swLatLng, neLatLng);
} else {
handleCenterChange('37.5665', '126.9780');
moveMapCenter('37.5665', '126.9780');
// 지도 범위를 가져와서 SW/NE 좌표 계산
const bounds = await getMapBounds();
const swLatLng = bounds.getSouthWest(); // 남서쪽 좌표
const neLatLng = bounds.getNorthEast(); // 북동쪽 좌표
await getAllFranchisesAndFilter(updatedParams, swLatLng, neLatLng);
}
}
setShouldUpdateCenter(true); // 지도 중심 이동 활성화
};
'FrontEnd' 카테고리의 다른 글
[카카오 지도 API ] 1. 반경 값 구하기(Next.js, TypeScript) (0) | 2025.01.14 |
---|---|
[웹 브라우저] Network panel 파헤치기 (0) | 2025.01.03 |
개발자 도구 - Application Panel (0) | 2024.12.30 |
웹에 최적화된 안내창 (1) | 2024.09.04 |
이미지(파일) 업로드 (0) | 2024.08.27 |