🔫 트러블슈팅

[JavaScript] 변수 흐름과의 싸움🤨#3

별이⭐ 2024. 10. 18. 20:56
아래 글에서 이어짐!

2024.10.17 - [🔫 트러블슈팅] - [JavaScript] 변수 흐름과의 싸움🤨#2

2024.10.16 - [🔫 트러블슈팅] - [JavaScript] 변수 흐름과의 싸움🤨#1

 

이번엔 날짜를 줄였을 때 발생하는 문제 2개를 제대로 동작하도록 바꿔보자!

문제가 발생하기 전 수정 페이지 초기 화면

 

문제 상황 - 1

초기 화면에서 여행 종료일을 8월 30일에서 29일으로 줄였을 때의 정상적인 동작은

1. 해운대블루라인파크라는 글자 앞에 인덱스가 3이 되어야하고, 해리단길은 4가 되어야한다.
2. 아래 span placeNumber 클래스 태그를 보면 id 값이 동백섬은 1-2로 되어있고 해운대블루라인파크는 2-1로 되어있는데 원래는 [일차]-[몇번째장소]기 때문에 해운대블루라인파크는 1-3이 되어야한다.

 

아래 캡쳐를 보면 정상적으로 동작되지 않고 있다.

 

 

해결 방법 - 1

작성된 코드를 살펴보자. 아래 코드는 날짜 변경 시 일정을 조정하는 함수인 updateTripDates() 내에 포함된 코드이다.

날짜 범위를 줄였을 때 if문이 실행된다.

// 만약 새로운 날짜 범위가 기존 날짜보다 짧다면, 남는 날짜의 장소들을 마지막 날로 합침
if (newDateIndex < existingTripData.length) {
	// 새로운 날짜 범위에 포함되지 않는 남은 날짜들(existingTripData[newDateIndex] 이후)에 있는 모든 장소들을 모아서 lastTripLocations에 저장
    const lastTripLocations = existingTripData
		    .slice(newDateIndex)    				// 기존 데이터에서 새로운 날짜 범위 이후의 데이터를 잘라냄
        	.flatMap(data => data.tripLocations);   // 잘라낸 데이터에서 각 날짜의 장소들(tripLocations)을 추출하여 하나의 배열로 만듦
        
    // 새로운 날짜 범위에서 마지막 날에 해당하는 trip-locations 요소를 찾음    
    const lastDayElement = newTripDatesContainer.querySelector('.trip-date:last-child .trip-locations');
    
    // 남은 날짜들의 장소들(lastTripLocations)을 하나씩 마지막 날에 추가
    lastTripLocations.forEach((loc, index) => {
        lastDayElement.insertAdjacentHTML(
		        'beforeend',    // lastDayElement의 마지막 자식 요소로 새로운 장소 요소를 추가
		        createTripLocationHtml(loc, newDateIndex + 1, index + 1));  // 남은 날짜의 장소(loc)를 HTML로 생성하여 추가
    });
}

// 날짜 카운트 업데이트 (Day 숫자 업데이트)
updateDayCount();

 

콘솔에 existingTripData, tripDateData, newDateIndex 를 찍어보자.

 

existingTripData은 날짜 변경 전 기존 날짜, 장소 데이터가 저장되어있다.

let newDateIndex = 0;
// 시작 날짜부터 종료 날짜까지 반복하며 날짜를 생성
for (let date = new Date(startDate); date <= endDate; date.setDate(date.getDate() + 1)) {
    // 현재 날짜에 해당하는 기존 여행 데이터가 있으면 가져옴, 없으면 빈 객체 사용
    const tripDateData = existingTripData[newDateIndex] || {};
    const dayNum = newDateIndex + 1;

    // 기존 addTripDate 함수 호출하여 새로운 날짜를 추가
    addTripDate({
        tripDate: date.toISOString().split('T')[0],
        tripLocations: tripDateData.tripLocations || []
    });

    newDateIndex++;
}

 

newDateIndex은 0부터 시작해서 기존 날짜 범위에 있는 데이터들을 추가해주는 addTripDate()을 호출 한 뒤 +1 된다.

tripDateData은 const tripDateData = existingTripData[newDateIndex] || {}; 이렇게 날짜 변경 후 현재 날짜에 해당하는 기존 데이터가 있으면 가져오고, 없으면 빈 객체로 만들어진다.

 

그럼 종료일을 8월 30일에서 29일로 줄였기 때문에 8월 30일 데이터들인 해운대블루라인파크와 해리단길을 8월 29일에 추가해야하는데, 그 때 if (newDateIndex < existingTripData.length)이 true기 때문에 if문 내부를 실행하게된다.

 

아까 봤던 if문 내부와 문서 구조를 다시 살펴보자.

// 만약 새로운 날짜 범위가 기존 날짜보다 짧다면, 남는 날짜의 장소들을 마지막 날로 합침
if (newDateIndex < existingTripData.length) {
	// 새로운 날짜 범위에 포함되지 않는 남은 날짜들(existingTripData[newDateIndex] 이후)에 있는 모든 장소들을 모아서 lastTripLocations에 저장
    const lastTripLocations = existingTripData
		    .slice(newDateIndex)    				// 기존 데이터에서 새로운 날짜 범위 이후의 데이터를 잘라냄
        	.flatMap(data => data.tripLocations);   // 잘라낸 데이터에서 각 날짜의 장소들(tripLocations)을 추출하여 하나의 배열로 만듦
        
    // 새로운 날짜 범위에서 마지막 날에 해당하는 trip-locations 요소를 찾음    
    const lastDayElement = newTripDatesContainer.querySelector('.trip-date:last-child .trip-locations');
    
    // 남은 날짜들의 장소들(lastTripLocations)을 하나씩 마지막 날에 추가
    lastTripLocations.forEach((loc, index) => {
        lastDayElement.insertAdjacentHTML(
		        'beforeend',    // lastDayElement의 마지막 자식 요소로 새로운 장소 요소를 추가
		        createTripLocationHtml(loc, newDateIndex + 1, index + 1));  // 남은 날짜의 장소(loc)를 HTML로 생성하여 추가
    });
}

 

내부 구조가 이렇게 되어있어서 trip-locations 아래에 있는 trip-location에 해운대해수욕장 같은 장소정보가 들어간다.

지금 id="1-1" 처럼 표현되는 span 태그 내의 id가 잘못들어가고 있는거니, createTripLocationHtml()에 넘겨주는 전달인자가 잘못된 것이 원인이라고 볼 수 있다.

createTripLocationHtml(loc, newDateIndex + 1, index + 1)); 이렇게 넘겨주는 것을

createTripLocationHtml(tripLocationData, dayNum, placeIndex) 이렇게 받는다.

그럼 dayNum이 newDateIndex + 1이 되는 것이고, placeIndex가 index + 1이 되는 것이다.

createTripLocationHtml에서 span 태그 id를 지정하는 방법은 const uniqueId = ${dayNum}-${placeIndex}; 이렇게 정의한다.

 

#2-1이 아닌 1-3이 되어야 정상

 

즉, 1-3이 되어야할 id가 2-1이 되고 있으니,

newDateIndex는 이미 1일차면 1, 2일차면 2로 알맞게 증가되고 있기 때문에 +1이 아닌 그대로 넘겨주고, placeIndex가 되는 값은 index + 1에 이미 해당 날짜에 존재하는 데이터의 길이를 더해주면 된다.

즉, createTripLocationHtml(loc, newDateIndex, existingTripData.length + index + 1));

이렇게 지정해주면 알맞게 해결된다!

 

알맞게 해결된 모습

 

 

문제 상황 - 2

문제 상황 1에서 선택된 장소들을 저장하는 객체 selectedPlaces에는 selectedPlaces[1]으로 나타나는 1일차 장소 배열에는 해운대해수욕장과 동백섬만 저장되어있고, selectedPlaces[1]에 함께 저장되어있어야할 해운대블루라인파크와 해리단길은 아예 추가되지 않은 것을 볼 수 있다.

지도에 나타나는 마커를 저장하는 markers 객체에도 마찬가지로 해운대블루라인파크와 해리단길은 아예 추가되지 않았다.

markers 배열에 원래 1일차 장소였던 해운대해수욕장과 동백섬만 있기 때문에 두 군데만 지도에 표시된다.

 

해결 방법 - 2

createTripLocationHtml()은 단지 HTML만 생성해주는 함수이고, selectedPlaces와 markers에 데이터를 추가하는 건 addTripDate()에서 이루어진다.

그렇기 때문에 if문에 selectedPlaces와 markers에 데이터 추가하는 부분도 넣어줘야한다.

 

코드에 데이터 추가하는 부분을 작성해주었다.

// 남은 날짜들의 장소들(lastTripLocations)을 하나씩 마지막 날에 추가
lastTripLocations.forEach((loc, index) => {
    lastDayElement.insertAdjacentHTML(
        'beforeend',    // lastDayElement의 마지막 자식 요소로 새로운 장소 요소를 추가
        createTripLocationHtml(loc, newDateIndex, existingTripData.length + index + 1)  // 남은 날짜의 장소(loc)를 HTML로 생성하여 추가
        // newDateIndex은 장소 uniqueId의 dayNum이 되고, existingTripData.length + index + 1은 장소 순서가 됨(lastTripLocations의 index는 0부터 시작하므로 +1 해줌)
    );

    // selectedPlaces 객체에 데이터 추가
    if (!selectedPlaces[newDateIndex]) {
        selectedPlaces[newDateIndex] = [];
    }
    selectedPlaces[newDateIndex].push({
        placeName: loc.placeName,
        latitude: loc.latitude,
        longitude: loc.longitude
    });

    // 지도에 마커 추가
    const placePosition = new kakao.maps.LatLng(loc.latitude, loc.longitude);
    addSelectedMarker(placePosition, existingTripData.length + index + 1, newDateIndex);
    // 마커 번호 재정렬
    reorderMarkers(markers, newDateIndex);
    // 지도 범위 재설정
    setBounds(placePosition);
    // 지도에 선 표시
    drawLinePath(newDateIndex, placePosition);
});

 

코드 수정 후 확인해보면 제대로 나타난다!

 

수정 후 로그에 찍힌 걸 보면 selectedPlaces[2]는 없는데 markers[2]는 남아있는 이유는

selectedPlaces은 selectedPlaces = {}; 로 아예 싹 다 비우고 addTripDate() 내부에서 push하고, 또 selectedPlaces[newDateIndex].push로 추가해주는 반면에,

markers는 clearAllMarker()로 markers 초기화하는데 clearAllMarker() 내부에서 markers[dayNum] = []; 이렇게 지정해주기 때문에 markers[2]의 내부만 초기화된다.

근데 뭐 markers[2]가 있어도 상관 없기 때문에 신경쓰지 않았다…!

 

 


 

자바스크립트 코드가 눈에 익숙하지 않아서 파악하는게 좀 힘들었지만 해결하면 바로바로 보여서 나름 재밌었다🫠

나중에 또 헤맬까봐 정리해두기 완료....!🫢