문제 상황
제거 버튼을 클릭했을 때, 내가 선택한 장소의 마커 배열인 markers에서 지우려했으나 분명 서로 같은 장소임에도 어떤 장소는 제거가 되고, 어떤 장소는 제거가 안 되는 문제가 발생했다.
문제 상황 관련 코드
1. markers 배열에 넣는 marker 객체에 마커의 위치인 position도 함께 넣었으니 getPosition()으로 해당 장소가 어딘지 분별 가능하다.
2. 그래서 제거 버튼 클릭 이벤트 핸들러에 이벤트가 발생한 항목의 placePosition을 넘겼다.
3. 넘어온 placePosition 값과 marker.getPosition() 값이 같은 항목 = 같은 장소가 된다.
4. 그래서 markers.findIndex()로 같은 장소에 해당하는 요소의 인덱스를 반환해서 해당 인덱스를 markers 배열에서 삭제해주었다.
-> 그런데 어떤 장소는 배열 내에서 잘 지워지고, 어떤 장소는 추가되어 있음에도 markerIndex가 -1로 나타나면서 지워지지 않았다! 즉, 조건을 만족하지 않아서 해당 요소가 없다고 나타타는 것!
해결 방법
안 지워지는 장소와 잘 지워지는 장소의 marker.getPosition()과 placePosition을 콘솔에 찍어봤다.
안 지워지는 장소는 marker.getPosition()과 placePosition 두 값이 다른 것으로 확인된다! -> 이것 때문에 equals 조건이 안 맞아서 삭제가 안 된 것!
1. 소수점 이하 아주 작은 차이로 다르다고 판단. 거의 동일한 값이지만 다르게 나오는 것 -> 실수 표현 시 부동소수점 오차 문제 때문!
2. 그렇다면 허용 오차 범위를 줘서 오차 범위 내면 같은 장소라고 판단하도록 수정하자.
3. 그럼 오차 범위는 어느정도로 설정하지?
오차 범위 설정은 지번까지 똑같은 근접한 장소의 경도 위도를 찍어보았다.
La = 경도 값 차이를 보면 126.990482777322 - 126.99057555769706 = -0.00009278037506
Ma = 위도 값 차이를 보면 37.5324787842175 - 37.53242563258956 = 0.00005315162794
차이를 살펴보면 소수점 아래 다섯 번째 자릿수부터 달라진다. 그럼 오차 범위 설정도 소수점 아래 다섯 번째 ~ 열한 번째 자릿수 사이인 0.00000001 정도로 지정하면 될 것이다.
4. 오차 범위는 + 또는 - 로 나올 수도 있으니 절댓값으로 비교해야하기에 abs를 붙여주었다.
const tolerance = 0.00000001; // 허용 오차 범위 설정
const markerIndex = markers.findIndex(marker => {
const markerPos = marker.getPosition();
return Math.abs(markerPos.La - placePosition.La) < tolerance &&
Math.abs(markerPos.Ma - placePosition.Ma) < tolerance;
});
위 처럼 코드를 변경하면 정상적으로 제거되는 모습을 확인 할 수 있다!
🔽 제거 버튼 이벤트 핸들러 전체 코드
function handleRemoveBtnClick(event, place, placePosition) {
event.stopPropagation();
// 배열의 각 요소 p의 id가 인자로 전달된 place의 id와 다른 요소만 filter해서 selectedPlaces에 남김 (넘어온 place를 배열에서 삭제)
selectedPlaces = selectedPlaces.filter(p => p.id !== place.id);
// findIndex는 배열에 각 요소에 대해 조건을 만족하는 첫 번째 요소의 인덱스 반환
// markers 배열에서 해당 장소 위치에 해당하는 marker 요소 제거
const tolerance = 0.00000001; // 허용 오차 범위 설정
const markerIndex = markers.findIndex(marker => {
const markerPos = marker.getPosition();
return Math.abs(markerPos.La - placePosition.La) < tolerance &&
Math.abs(markerPos.Ma - placePosition.Ma) < tolerance;
});
if (markerIndex !== -1) { // 해당 장소 위치의 마커가 존재한다면
markers[markerIndex].setMap(null); // 지도에서 마커 제거
markers.splice(markerIndex, 1); // 배열에서 마커 제거. 인덱스부터 1개의 요소 삭제
}
}
'🔫 트러블슈팅' 카테고리의 다른 글
[AWS/S3] S3 버킷 읽기 권한 문제를 버킷 정책 등록으로 해결하기 (0) | 2024.10.10 |
---|---|
[Spring Boot] JSON 데이터와 Multipart 파일 함께 처리 시 Current request is not a multipart request 에러 (0) | 2024.10.02 |
[카카오 지도 API] 마커 인덱스가 index+1 값으로 표시되는 문제 (0) | 2024.09.13 |
[카카오 지도 API] 검색 결과 목록의 페이지별 마커 인덱스 겹침 문제 (0) | 2024.09.13 |
[Spring Boot] BindingResult를 통한 유효성 검증 시 잘못된 BindingResult 위치 (0) | 2024.06.13 |