본문 바로가기

Frontend/jQuery & JSTL

12/05 회고

반응형

라디오버튼

라디오 버튼만 만들어 놓는다면 선택지를 고르면 무조건 선택되고 null로 되돌아갈 수 없다 ∵ 보통은 초기화 버튼을 같이 만들어 둠

type :  정의(radio) / id : 고유값 / name : 같은 선택지( name이 다르면 다른 그룹으로 생각함) / value : 선택 값 / checked : 선택됨(사용안하면 초기 선택값이 없음) 

<div id="changeMode" class="changeMode">
	<label for="total" class="pointer">
		<input type="radio" id="total" name="mode" value="total"> 전체 
	</label>
	<label for="period" class="pointer">
		<input type="radio" id="period" name="mode" value="period" checked> 기간 
	</label>
</div>

 

이벤트 리스너

//요소가 가진 값이 반경될때 => 라디오버튼
$("#total, #period").on("change", function () {
	mapReload($(this).val());
	console.log("mode Change");
});

//요소 자체의 값이 반경될때 => 드롭박스
$(".changeMode").on("change", function () {
	mapReload($(this).val());
	console.log("mode Change");
});

 

stack 메모리 과부하

데이터가 1101건 밖에 없는데 이렇게 에러가 발생했다.

function calculatePercentile(data, percentile) {
	const sortedData = data.slice().sort((a, b) => a - b);
	const index = (percentile / 100) * (sortedData.length - 1);
	const integerPart = Math.floor(index);
	const decimalPart = index - integerPart;
	let percentileValue;
	if (decimalPart === 0) {
		percentileValue = sortedData[integerPart];
	} else {
		percentileValue =
			(1 - decimalPart) * sortedData[integerPart] +
			decimalPart * sortedData[integerPart + 1];
	}
	const minValue = sortedData[0];
	const maxValue = sortedData[sortedData.length - 1];

	return {
		percentile: percentileValue,
		min: minValue,
		max: maxValue,
	}
}

원 코드이다. 여기서 둘째줄의 data를 slicing해서 sort하는 동작에서 해당 에러가 발생했다.

문제점을 구글링 하다 보니 대부분의 상황은 재귀함수를 잘못사용해서 무한루프에 빠지는 경우였다.

수정코드는 다음과 같다.

...
return setTimeout({
	percentile: percentileValue,
    min: minValue,
	max: maxValue,
},0);
...

슬라이싱 결과를 return하기 전에 timeOut을 걸었다.

setTimeout에서 0을 하면 이론상은 즉시 응답이지만 node의 경우에는 1ms, 일반적인 브라우저에서는 4ms의 딜레이가 기본적으로 깔려있다고 한다. 따라서 이벤트 동작을 수행하면서 stack메모리가 다 차기전에 web으로 전달하여 조금은 숨을 쉴수있는 구조로 변경해준것이다.

 

해당 내용을 이해하게 해준 출처 : https://blog.naver.com/dlaxodud2388/222187409586

 

[JavaScript 오류] 'RangeError : Maxmum call stack size exceeded' 발생원인 및 해결

이 오류의 경우 대부분 아래와 같이 함수를 재귀호출하여 발생하는 오류이다. 이 코드를 실행하게 되면 아...

blog.naver.com

 

하지만 해결법은 아니었던듯... 다시 마주한 RangeError.....

찾다보니 위의 문제와는 별개로 main 메서드를 다시 호출하고 있던 부분에서 재귀 호출하면서 부수적으로 보였던것같다.

 

 

MyBatis사용법

name이 4글자인 경우와 6글자인 경우의 다른 조건

...
AND ( (LENGTH(#{name}) = 4 AND A.name LIKE CONCAT('_','_',#{name}))
	OR (LENGTH(#{name}) = 6 AND A.name LIKE CONCAT(#{name}))
)
...

 

데이터는 그대로 사용하는데 참조하는 값만 변경 하려고 한다.

데이터 차이값을 해당 연도를 참고 한것과 모든 연도를 값을 참고하여 시각화 하고 싶다고 한다.

해서 JSON데이터를 미리 안고 있는 상황에서 버튼을 이용해 데이터가 바뀌는 것처럼 보이게 하고 싶었다.

 

원 코드

...
var sidoColorArea2 = [];
for (let i = 0 ; i < allDatas2.features.length; i++){
	if(allDatas2.features[i].properties.SIDO_KOR_NAME == allDatas2.features[i].properties.SIGUNGU_KOR_NAME){
		if(allDatas2.features[i].properties.PEOPLE != 0){
			sidoColorArea2.push(allDatas2.features[i].properties.OLD_RATE);
		}
	}
}
              	  
function calculatePercentile2(data, percentile) {
	const sortedData2 = data.slice().sort((a, b) => a - b);
	const index2 = (percentile / 100) * (sortedData2.length - 1);
	const integerPart2 = Math.floor(index2);
	const decimalPart2 = index2 - integerPart2;
	let percentileValue2;
	if (decimalPart2 === 0) {
		percentileValue2 = sortedData2[integerPart2];
	} else {
		percentileValue2 =
			(1 - decimalPart2) * sortedData2[integerPart2] +
			decimalPart2 * sortedData2[integerPart2 + 1];
	}
	const minValue2 = sortedData2[0];
	const maxValue2 = sortedData2[sortedData2.length - 1];

	return {
		percentile2: percentileValue2,
		min2: minValue2,
		max2: maxValue2,
	};
}

const minValue2 = calculatePercentile2(sidoColorArea2, 20).min2;
const avg12 = calculatePercentile2(sidoColorArea2, 20).percentile2.toFixed(1);
const avg22 = calculatePercentile2(sidoColorArea2, 40).percentile2.toFixed(1);
const avg32 = calculatePercentile2(sidoColorArea2, 60).percentile2.toFixed(1);
const avg42 = calculatePercentile2(sidoColorArea2, 80).percentile2.toFixed(1);
const maxValue2 = calculatePercentile2(sidoColorArea2, 80).max2;
        			  
avgList12.innerHTML = minValue2 + " ~ " + avg12;
avgList22.innerHTML = avg12 + " ~ " + avg22;
avgList32.innerHTML = avg22 + " ~ " + avg32;
avgList42.innerHTML = avg32 + " ~ " + avg42;
avgList52.innerHTML = avg42 + " ~ " + maxValue2;
...

 

수정 코드

...
function mapReload(term) {
	if (term == "period") {
		sidoColorArea = [];
		tlSidoColorArea = [];
		for (let i = 0; i < allDatas.features.length; i++) {
			if (allDatas.features[i].properties.SIDO_KOR_NAME == allDatas.features[i].properties.SIGUNGU_KOR_NAME) {
				if (allDatas.features[i].properties.PEOPLE != 0) {
					sidoColorArea.push(allDatas.features[i].properties.OLD_RATE);
				}
			} else if(allDatas.features[i].properties.SIDO_KOR_NAME == '제주특별자치' && allDatas.features[i].properties.SIGUNGU_KOR_NAME == '제주특별자치도'){
				sidoColorArea.push(allDatas.features[i].properties.OLD_RATE);
			}
		}

			minValue = calculatePercentile(sidoColorArea, 20).min;
		avg1 = calculatePercentile(sidoColorArea, 20).percentile.toFixed(1);
		avg2 = calculatePercentile(sidoColorArea, 40).percentile.toFixed(1);
		avg3 = calculatePercentile(sidoColorArea, 60).percentile.toFixed(1);
		avg4 = calculatePercentile(sidoColorArea, 80).percentile.toFixed(1);
		maxValue = calculatePercentile(sidoColorArea, 80).max;
                                    
		avgList1.innerHTML = minValue + " ~ " + avg1;
		avgList2.innerHTML = avg1 + " ~ " + avg2;
		avgList3.innerHTML = avg2 + " ~ " + avg3;
		avgList4.innerHTML = avg3 + " ~ " + avg4;
		avgList5.innerHTML = avg4 + " ~ " + maxValue;
                                    
		sidoArea(sido, data);

	} else {
		sidoColorArea = [];
		for (let i = 0; i < allDatas.features.length; i++) {
			if (allDatas.features[i].properties.SIDO_KOR_NAME == allDatas.features[i].properties.SIGUNGU_KOR_NAME) {
				if (allDatas.features[i].properties.PEOPLE != 0) {
					sidoColorArea.push(allDatas.features[i].properties.OLD_RATE);
				}
			}
		}
		for (let i = 0; i < totalLegend.features.length; i++) {
			if (totalLegend.features[i].properties.SIDO_KOR_NAME == totalLegend.features[i].properties.SIGUNGU_KOR_NAME) {
				if (totalLegend.features[i].properties.PEOPLE != 0) {
					tlSidoColorArea.push(totalLegend.features[i].properties.OLD_RATE);
				}
			} else if(allDatas.features[i].properties.SIDO_KOR_NAME == '제주특별자치' && allDatas.features[i].properties.SIGUNGU_KOR_NAME == '제주특별자치도'){
				sidoColorArea.push(allDatas.features[i].properties.OLD_RATE);
			}
		}
                                	
		minValue = calculatePercentile(tlSidoColorArea, 20).min;
		avg1 = calculatePercentile(tlSidoColorArea, 20).percentile.toFixed(1);
		avg2 = calculatePercentile(tlSidoColorArea, 40).percentile.toFixed(1);
		avg3 = calculatePercentile(tlSidoColorArea, 60).percentile.toFixed(1);
		avg4 = calculatePercentile(tlSidoColorArea, 80).percentile.toFixed(1);
		maxValue = calculatePercentile(tlSidoColorArea, 80).max;
                                     
		avgList1.innerHTML = minValue + " ~ " + avg1;
		avgList2.innerHTML = avg1 + " ~ " + avg2;
		avgList3.innerHTML = avg2 + " ~ " + avg3;
		avgList4.innerHTML = avg3 + " ~ " + avg4;
		avgList5.innerHTML = avg4 + " ~ " + maxValue;
                                     
		sidoArea(sido, data);
	}                             
}
...

 

근데 중복된 부분도 너무 많고 가독성이 떨어져 간략화 하였다.

function calculatePercentile(data, percentile) {
    const sortedData = data.slice().sort((a, b) => a - b);
    const index = (percentile / 100) * (sortedData.length - 1);
    const integerPart = Math.floor(index);
    const decimalPart = index - integerPart;
    let percentileValue;
    if (decimalPart === 0) {
        percentileValue = sortedData[integerPart];
    } else {
        percentileValue =
            (1 - decimalPart) * sortedData[integerPart] +
            decimalPart * sortedData[integerPart + 1];
    }
    const minValue = sortedData[0];
    const maxValue = sortedData[sortedData.length - 1];

    // 배열로 값을 반환
    return [percentileValue, minValue, maxValue];
}

function mapReload(term) {
    sidoColorArea = [];
    tlSidoColorArea = [];

    const filterData = (data) => {
        for (let i = 0; i < data.features.length; i++) {
            const feature = data.features[i];
            if (feature.properties.SIDO_KOR_NAME == feature.properties.SIGUNGU_KOR_NAME ||
                (feature.properties.SIDO_KOR_NAME == '제주특별자치' && feature.properties.SIGUNGU_KOR_NAME == '제주특별자치도')) {
                if (feature.properties.PEOPLE != 0) {
                    term === "period" ? sidoColorArea.push(feature.properties.OLD_RATE) : tlSidoColorArea.push(feature.properties.OLD_RATE);
                }
            }
        }
    };

    const updateUI = (values) => {
        // 배열의 각 요소를 따로 변수로 할당
        const [percentileValue, minValue, maxValue] = values.map(val => val.toFixed(1));

        avgList1.innerHTML = `${minValue} ~ ${percentileValue}`;
        avgList2.innerHTML = `${percentileValue} ~ ${minValue}`;
        avgList3.innerHTML = `${minValue} ~ ${maxValue}`;
        avgList4.innerHTML = `${minValue} ~ ${percentileValue}`;
        avgList5.innerHTML = `${percentileValue} ~ ${maxValue}`;
    };

    filterData(allDatas);
    term === "period" ? updateUI(calculatePercentile(sidoColorArea, 80)) : (filterData(totalLegend), updateUI(calculatePercentile(tlSidoColorArea, 80)));

    sidoArea(sido, data);

    console.log(sidoColorArea);
    console.log(tlSidoColorArea);
}

mapReload("period");
$("#total, #period").on("change", function () {
    mapReload($(this).val());
    console.log("mode Change");
});

 

반응형

'Frontend > jQuery & JSTL' 카테고리의 다른 글

12/21 회고  (0) 2023.12.21
12/07 회고  (0) 2023.12.07
[JSTL] 페이지 작업  (0) 2023.11.22
[jQuery] tab관리 작업  (0) 2023.11.17
[JSTL] data와 li요소 항목 비교해서 표시하기  (0) 2023.11.16