프로젝트
문제해결_ 공공 데이터의 배신 ( 숫자여야만 하는데…)
warrior.p
2024. 3. 12. 16:59
- 간혹 실시간 데이터나 과거 데이터의 일부지역 의 미세먼지 값이 null 또는 ‘ - ‘로 들어올때가 있어서 그래프와 계산 로직에 악영향을 준다. 그래서 실시간 데이터 값이 숫자가 아닌 경우는 다른 지역의 데이터로 대체해주는 것을 피할 수 없었다.
- 실시간 미세먼지 수치에서는 일부지역에서 숫자가 아닌 값이 들어와서 그럴때는 강릉의 value를 넣어줬다.
const { data, isError, isLoading, refetch } = useQuery(
'dustData',
fetchDustData,
{
// onSuccess ->useQuery에서 사용함. 비동기 요청 성공시 실행되는 콜백함수 정의!
onSuccess: data => {
// 데이터 fetch 성공 시, Recoil Atom 업데이트, 5개 지역 로컬스토리지 저장
if (data && data.length > 0) {
const fiveSpot = filterGangwonDustData(data);
// 데이터가 제대로 나지 않을 경우 강릉 데이터로 교체
const gangneungData = fiveSpot.find(([name]) => name === '주문진읍');
// 강릉 데이터가 없을 수 있으므로 없으면 0을
const gangneungValue = gangneungData ? gangneungData.value : '0';
// 각각의 recoil atom 업데이트
fiveSpot.forEach(([name, value]) => {
// 데이터의 value가 숫자가 아닐 경우
const replaceValue = isNaN(parseInt(value, 10))
? gangneungValue
: parseInt(value, 10);
switch (name) {
case '고성(DMZ)':
setGoseongCurrent([name, replaceValue]);
break;
case '양양읍':
setYangyangCurrent([name, replaceValue]);
break;
case '평창읍':
setPyeongchangCurrent([name, replaceValue]);
break;
case '주문진읍':
setGangneungCurrent([name, replaceValue]);
break;
case '금호동':
setSokchoCurrent([name, replaceValue]);
break;
default:
break;
}
});
const bestSpot = findGoodSpot(fiveSpot);
setCurrentSpot(bestSpot);
- 실시간의 경우 과거 데이터를 찾기가 애매하여 다른 지역의 데이터로 대체를 하였는데, 과거 데이터의 경우 다른지역의 데이터가 아닌 이전의 숫자값으로 제대로 들어온 해당 지역의 데이터로 대체 해주었다.
// 데이터가 숫자가 아닐 경우 정상적인 pm10Value의 값을 찾는 로직
const findLastValue = data => {
for (let i = data.length - 1; i >= 0; i--) {
const value = parseInt(data[i].pm10Value, 10);
if (!isNaN(value)) {
return data[i].pm10Value;
}
}
// 도저히 안되면 그냥 0...
return '0';
};
const fetchDataQueries = Object.entries(locationAtoms).map(([msrstnName]) => {
return {
queryKey: ['pastDustData', msrstnName],
queryFn: async () => {
// 로컬 스토리지에서 데이터 검증
const cachedData = loadDataWithDailyCheck(msrstnName);
// 유효한 캐시된 데이터 반환, API 호출 없이 해당 데이터 반환
if (cachedData.isValid) {
return cachedData.data;
} else {
// API 호출하여 새로운 데이터 가져오기
try {
const newData = await fetchPastDustData(
getSevenDaysBeforeDate(new Date()),
getYesterdaysStringDate(new Date()),
msrstnName
);
// console.log(newData);
return newData;
} catch (error) {
console.error(`Error fetching data for ${msrstnName}:`, error);
// 에러를 다시 throw하여 React Query가 캐치할 수 있도록 함
throw error;
}
}
},
onSuccess: data => {
// 데이터 fetch 성공 시, Recoil Atom 업데이트
if (data && data.length > 0) {
let pastDustHistory = data.map(item => {
const pm10Value = parseInt(item.pm10Value, 10);
return {
...item,
pm10Value: isNaN(pm10Value)
? findLastValue(data)
: item.pm10Value,
};
});
pastDustHistory =filterLocationInfo(pastDustHistory)
//로컬에 저장
saveToLocalStorage(msrstnName, pastDustHistory);
console.log(pastDustHistory);
// 각각의 recoil atom 업데이트
switch (msrstnName) {
case '고성(DMZ)':
setGoseongPastState(pastDustHistory);
break;
case '양양읍':
setYangyangPastState(pastDustHistory);
break;
case '평창읍':
setPyeongchangPastState(pastDustHistory);
break;
case '주문진읍':
setGangneungPastState(pastDustHistory);
break;
case '금호동':
setSokchoPastState(pastDustHistory);
break;
default:
break;
}
}
},
};
});
useQueries(fetchDataQueries);