날씨 스토리지에저장
This commit is contained in:
parent
25c691338d
commit
ffc8b44b46
@ -1,9 +1,8 @@
|
||||
/*
|
||||
작성자 : 서지희
|
||||
작성일 : 2025-04-04
|
||||
수정자 :
|
||||
수정일 :
|
||||
설명 : 위치 기반으로 날씨를 조회하고, 오늘의 최저/최고 기온과 현재 날씨 아이콘/설명을 저장합니다.
|
||||
수정일 : 2025-04-07
|
||||
설명 : 위치 기반으로 날씨를 조회하고, 10분 단위 캐시로 저장합니다.
|
||||
*/
|
||||
import { ref } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
@ -20,67 +19,96 @@ export const useWeatherStore = defineStore('weather', () => {
|
||||
const dailyWeatherList = ref([]);
|
||||
|
||||
const getWeatherInfo = async () => {
|
||||
navigator.geolocation.getCurrentPosition(async position => {
|
||||
const lat = position.coords.latitude;
|
||||
const lon = position.coords.longitude;
|
||||
return new Promise((resolve, reject) => {
|
||||
navigator.geolocation.getCurrentPosition(async position => {
|
||||
const lat = position.coords.latitude;
|
||||
const lon = position.coords.longitude;
|
||||
|
||||
try {
|
||||
const res = await $api.get(`/weather`, {
|
||||
params: { lat, lon },
|
||||
withCredentials: true,
|
||||
});
|
||||
try {
|
||||
const res = await $api.get(`/weather`, {
|
||||
params: { lat, lon },
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
if (!res?.data?.data) return;
|
||||
if (!res?.data?.data) return;
|
||||
|
||||
const resData = res.data.data;
|
||||
const raw = resData.weatherInfo;
|
||||
const data = JSON.parse(raw);
|
||||
console.log(data.list)
|
||||
if (!data || !Array.isArray(data.list) || data.list.length === 0) {
|
||||
console.error('날씨 데이터 형식 오류 또는 없음:', data);
|
||||
return;
|
||||
const resData = res.data.data;
|
||||
const raw = resData.weatherInfo;
|
||||
const data = JSON.parse(raw);
|
||||
if (!data || !Array.isArray(data.list)) {
|
||||
console.error('날씨 데이터 형식 오류');
|
||||
return;
|
||||
}
|
||||
|
||||
dailyWeatherList.value = resData.dailyWeatherList;
|
||||
|
||||
const now = new Date();
|
||||
const todayStr = now.toISOString().split('T')[0];
|
||||
const nowTime = now.getTime();
|
||||
|
||||
const todayList = data.list.filter(item => item.dt_txt.startsWith(todayStr));
|
||||
if (todayList.length > 0) {
|
||||
const minTemp = Math.min(...todayList.map(i => i.main.temp_min));
|
||||
const maxTemp = Math.max(...todayList.map(i => i.main.temp_max));
|
||||
weather.value.tempMin = Math.round(minTemp);
|
||||
weather.value.tempMax = Math.round(maxTemp);
|
||||
}
|
||||
|
||||
const closest = data.list.reduce((prev, curr) => {
|
||||
const prevDiff = Math.abs(new Date(prev.dt_txt).getTime() - nowTime);
|
||||
const currDiff = Math.abs(new Date(curr.dt_txt).getTime() - nowTime);
|
||||
return currDiff < prevDiff ? curr : prev;
|
||||
});
|
||||
|
||||
weather.value.icon = closest.weather[0].icon.replace(/n$/, 'd');
|
||||
weather.value.description = closest.weather[0].description;
|
||||
|
||||
resolve({ weather: weather.value, dailyWeatherList: dailyWeatherList.value });
|
||||
} catch (e) {
|
||||
console.error('날씨 정보 가져오기 실패:', e);
|
||||
reject(e);
|
||||
}
|
||||
|
||||
// 주간 예보 리스트 저장
|
||||
dailyWeatherList.value = resData.dailyWeatherList;
|
||||
|
||||
const now = new Date();
|
||||
const nowTime = now.getTime();
|
||||
const todayStr = now.toISOString().split('T')[0];
|
||||
|
||||
// 오늘의 데이터만 필터링
|
||||
const todayList = data.list.filter(item => item.dt_txt.startsWith(todayStr));
|
||||
|
||||
if (todayList.length > 0) {
|
||||
// 오늘의 최저 / 최고 기온 계산
|
||||
const minTemp = Math.min(...todayList.map(i => i.main.temp_min));
|
||||
const maxTemp = Math.max(...todayList.map(i => i.main.temp_max));
|
||||
weather.value.tempMin = Math.round(minTemp);
|
||||
weather.value.tempMax = Math.round(maxTemp);
|
||||
} else {
|
||||
weather.value.tempMin = null;
|
||||
weather.value.tempMax = null;
|
||||
}
|
||||
|
||||
// 현재 시간과 가장 가까운 시간대 데이터 추출 (아이콘 및 설명용)
|
||||
const closest = data.list.reduce((prev, curr) => {
|
||||
const prevDiff = Math.abs(new Date(prev.dt_txt).getTime() - nowTime);
|
||||
const currDiff = Math.abs(new Date(curr.dt_txt).getTime() - nowTime);
|
||||
return currDiff < prevDiff ? curr : prev;
|
||||
});
|
||||
|
||||
weather.value.icon = closest.weather[0].icon.replace(/n$/, 'd');
|
||||
weather.value.description = closest.weather[0].description;
|
||||
|
||||
} catch (e) {
|
||||
console.error('날씨 정보 가져오기 실패:', e);
|
||||
}
|
||||
}, reject);
|
||||
});
|
||||
};
|
||||
|
||||
// 로컬스토리지 캐시 포함한 로직
|
||||
const getWeatherInfoWithCache = async () => {
|
||||
const now = new Date();
|
||||
const pad = n => String(n).padStart(2, '0');
|
||||
const key = `weather_${pad(now.getMonth() + 1)}${pad(now.getDate())}${pad(now.getHours())}${Math.floor(now.getMinutes() / 10) * 10}`;
|
||||
|
||||
const cached = localStorage.getItem(key);
|
||||
if (cached) {
|
||||
const parsed = JSON.parse(cached);
|
||||
weather.value = parsed.weather;
|
||||
dailyWeatherList.value = parsed.dailyWeatherList;
|
||||
return;
|
||||
}
|
||||
|
||||
// 캐시 삭제
|
||||
Object.keys(localStorage).forEach(k => {
|
||||
if (k.startsWith('weather_')) localStorage.removeItem(k);
|
||||
});
|
||||
|
||||
try {
|
||||
const { weather: w, dailyWeatherList: d } = await getWeatherInfo();
|
||||
localStorage.setItem(key, JSON.stringify({ weather: w, dailyWeatherList: d }));
|
||||
} catch (e) {
|
||||
// 오류 시 기존 로컬스토리지 값 중 가장 최신 값 사용
|
||||
const oldKey = Object.keys(localStorage).filter(k => k.startsWith('weather_')).sort().pop();
|
||||
if (oldKey) {
|
||||
const fallback = JSON.parse(localStorage.getItem(oldKey));
|
||||
weather.value = fallback.weather;
|
||||
dailyWeatherList.value = fallback.dailyWeatherList;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
weather,
|
||||
dailyWeatherList,
|
||||
getWeatherInfo,
|
||||
getWeatherInfoWithCache,
|
||||
};
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user