Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,42 @@ public AiPredictionRequestDto makePredictRequest(Member member) {

private List<WeatherPredictDto> getWeatherForecast(Member member) {
List<Integer> targetHours = List.of(9, 12, 15, 18, 21);

String regionName = member.getRegionName() != null ? member.getRegionName() : "서울특별시 용산구";

LocalDate today = LocalDate.now();

List<WeatherForecast> forecasts = weatherForecastRepository
.findByRegionNameAndForecastDateAndHourIn(regionName, LocalDate.now(), targetHours);
.findByRegionNameAndForecastDateAndHourInOrderByCreatedAtDesc(regionName, today, targetHours);

if (forecasts.isEmpty()) {
LocalDate yesterday = today.minusDays(1);
log.warn("[날씨 조회 재시도] 지역 {}에 대해 오늘({}) 데이터가 없어 어제({}) 날짜로 재시도합니다.",
regionName, today, yesterday);

forecasts = weatherForecastRepository
.findByRegionNameAndForecastDateAndHourInOrderByCreatedAtDesc(regionName, yesterday, targetHours);

if (forecasts.isEmpty()) {
log.error("[날씨 조회 최종 실패] 지역 {}에 대해 어제, 오늘 모두 예보 데이터가 없습니다.", regionName);
}
}

log.info("[날씨 조회 결과] memberId={}, 지역: {}, 조회된 예보 개수: {}",
member.getId(), regionName, forecasts.size());

Map<Integer, WeatherForecast> hourToForecastMap = forecasts.stream()
.collect(Collectors.toMap(
WeatherForecast::getHour,
forecast -> forecast,
(oldVal, newVal) -> oldVal
));

return forecasts.stream()
return hourToForecastMap.values().stream()
.map(this::convertToDto)
.collect(Collectors.toList());
}


private WeatherPredictDto convertToDto(WeatherForecast forecast) {
return WeatherPredictDto.builder()
.hour(forecast.getHour())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,7 @@ private List<WeatherFeelingDto> makeWeatherFeeling(Map<String, Integer> predicti
ClothingRecommendation recommendation) {
List<WeatherFeelingDto> feelingList = new ArrayList<>();

LocalDate today = LocalDate.now();
LocalTime now = LocalTime.now();
LocalDate forecastDate = now.isBefore(LocalTime.of(6, 0)) ? today.minusDays(1) : today;
LocalDate forecastDate = recommendation.getDate();

String regionName = recommendation.getRegionName();

Expand All @@ -127,13 +125,13 @@ private List<WeatherFeelingDto> makeWeatherFeeling(Map<String, Integer> predicti
.collect(Collectors.toList());

List<WeatherForecast> forecasts = weatherForecastRepository
.findByRegionNameAndForecastDateAndHourIn(regionName, forecastDate, hours);
.findByRegionNameAndForecastDateAndHourInOrderByCreatedAtDesc(regionName, forecastDate, hours);

Map<Integer, WeatherForecast> hourToForecastMap = forecasts.stream()
.collect(Collectors.toMap(
WeatherForecast::getHour,
forecast -> forecast,
(oldVal, newVal) -> newVal
(oldVal, newVal) -> oldVal
));

for (Map.Entry<String, Integer> entry : predictionMap.entrySet()) {
Expand All @@ -150,10 +148,9 @@ private List<WeatherFeelingDto> makeWeatherFeeling(Map<String, Integer> predicti
.build();
feelingList.add(dto);
} else {
log.warn("날씨 데이터 없음: region={}, hour={}", regionName, hour);
log.warn("날씨 데이터 없음: region={}, date={}, hour={}", regionName, forecastDate, hour);
}
}

return feelingList;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ public interface WeatherForecastRepository extends JpaRepository<WeatherForecast

List<WeatherForecast> findByRegionNameAndForecastDate(String regionName, LocalDate now);

List<WeatherForecast> findByRegionNameAndForecastDateAndHourIn(
List<WeatherForecast> findByRegionNameAndForecastDateAndHourInOrderByCreatedAtDesc(
String regionName,
LocalDate forecastDate,
List<Integer> hours);
List<Integer> hours
);

void deleteByForecastDateGreaterThanEqual(LocalDate baseDate);

List<WeatherForecast> findByRegionNameAndForecastDateAndHourIn(String regionName, LocalDate now, List<Integer> targetHours);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.howWeather.howWeather_backend.global.exception.CustomException;
import com.howWeather.howWeather_backend.global.exception.ErrorCode;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -20,6 +21,7 @@

@Service
@AllArgsConstructor
@Slf4j
public class WeatherService {
private final WeatherRepository weatherRepository;
private final WeatherApiClient weatherApiClient;
Expand Down Expand Up @@ -64,17 +66,30 @@ public double getTemperature(WeatherSimpleDto dto) {
@Transactional
public void fetchHourlyForecast() {
List<Region> regions = regionRepository.findAll();

LocalDate baseDate = LocalDate.now();

weatherForecastRepository.deleteByForecastDateGreaterThanEqual(baseDate);

List<WeatherForecast> allForecasts = new ArrayList<>();

for (Region region : regions) {
double lat = region.getLat();
double lon = region.getLon();
String regionName = region.getName();

List<WeatherPredictDto> forecasts = weatherApiClient.fetchForecast(lat, lon);
List<WeatherPredictDto> forecasts = null;
try {
forecasts = weatherApiClient.fetchForecast(lat, lon);

if (forecasts == null || forecasts.isEmpty()) {
log.warn("[날씨 API 경고] 지역 {}에 대해 유효한 예보 데이터가 없어 저장 생략.", regionName);
continue;
}

} catch (Exception e) {
log.error("[날씨 API 오류] 지역 {}의 예보 데이터 가져오기 실패: {}", regionName, e.getMessage());
continue;
}

int cnt = 0;
for (WeatherPredictDto dto : forecasts) {
Expand All @@ -96,6 +111,12 @@ public void fetchHourlyForecast() {
cnt++;
}
}
weatherForecastRepository.saveAll(allForecasts);

if (!allForecasts.isEmpty()) {
weatherForecastRepository.saveAll(allForecasts);
log.info("[날씨 예보 저장 완료] 총 {}개의 예보 데이터가 DB에 저장되었습니다.", allForecasts.size());
} else {
log.warn("[날씨 예보 저장 실패] 모든 지역에서 API 호출에 실패하여 저장된 데이터가 없습니다.");
}
}
}
Loading