[Team Project] 아웃소싱 프로젝트 (2)

liinyeye·2024년 6월 18일
0

Project

목록 보기
20/44
post-thumbnail

날씨 API 가져오기

처음에는 기상청 API를 사용하려다가 OpenWeather API가 사용하는 방법이 더 잘 정리되어 있어 중간에 변경하기로 결정했다. 위도, 경도를 넣어서 데이터를 받아오는 방법도 있었지만, 도시 이름으로 받아오는 더 간단한 방법이 있어서 해당 방식을 사용하기로 했다.

https://api.openweathermap.org/data/2.5/weather?q={city name}&appid={API key}

url에 들어가는 cityname은 여기에 나와있는 이름을 사용하거나 없다면 검색해서 해당 도시이름을 확인하고 넣어주면 된다.

import axios from 'axios';

const APIkey = import.meta.env.VITE_WEATHER_KEY;

export const fetchWeatherData = async (cityName) => {
  //   console.log(cityName);
  const weatherUrl = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${APIkey}&units=metric`;
  try {
    const response = await axios.get(weatherUrl);
    return response.data;
  } catch (error) {
    console.log(error?.response?.data?.message);
    alert(error?.response?.data?.message);
  }
};

받아온 날씨 데이터


게임 스케줄 API 가져오기

이번 프로젝트에서도 supabase를 사용해야 했기 때문에 다시 한 번 다룰 수 있는 기회가 생겼다. 이전에는 authentication만 다뤄봤기 때문에 데이터를 가져오는 로직은 이번에 처음 작성해봤고 생각보다 간단했다.

다만 처음에 로직을 제대로 작성한 것 같은데, 데이터가 불러와지지 않아 확인해보니 테이블 사용 권한이 닫혀있어 생긴 문제였고 권한을 풀어주니 데이터를 제대로 받아올 수 있었다.

import supabase from '../supabase/supabaseClient';

export const fetchGameSchedule = async () => {
  try {
    const { data: gameSchedule, error } = await supabase
      .from('gameSchedule')
      .select('*');
    if (error) {
      throw error;
    }
    console.log('data => ', gameSchedule);
    return gameSchedule;
  } catch (error) {
    console.error('Failed to fetch game schedule:', error.message);
    throw new Error(`Failed to fetch game schedule : ${error.message}`);
  }
};

받아온 게임 스케줄 데이터

날씨와 게임 스케줄에 따라 화면에 그려주기

tanstack query를 사용해서 API 데이터를 불러오면서 상태관리를 하고, 받아온 게임 데이터의 정보를 바탕으로 날씨 데이터도 같이 넣어주어 화면에 그려주도록 했다.

다만, 지금은 데이터가 잘 들어오는지 먼저 확인해보기 위해 도시 이름을 따로 선언해서 관리를 해줬는데 게임 스케줄 데이터에서 받아온 배열 요소의 키를 사용해 넣어주는 방식으로 변경이 필요하다.

그리고 리렌더링이 너무 잦아 useEffect안에 들어가는 함수를 따로 분리해 useCallback으로 감싸주어 리렌더링을 최적화할 수 있도록 로직을 일부 수정했다.

const WeatherByGame = () => {
  // const [weatherInfo, setWeatherInfo] = useState([]);
  const [gameInfo, setGameInfo] = useState([]);

  // 날씨 데이터 불러오기 위해 임시로 적어둔 도시 이름 데이터
  const cityNames = {
    Seoul: 'Seoul',
    Incheon: 'Incheon',
    Busan: 'Busan',
    Gwangju: 'Gwangju',
    Daegu: 'Daegu',
    Cheongju: 'Cheongju',
    Changwon: 'Changwon',
    Suwon: 'Suwon',
    Daejeon: 'Daejeon',
  };

  // 게임 스케줄 데이터 불러오기
  const {
    data: gameScheduleData,
    isPending: isGameSchedulePending,
    isSuccess: isGameScheduleSuccess,
  } = useQuery({
    queryKey: ['gameSchedule'],
    queryFn: fetchGameSchedule,
  });

  // 게임 스케줄 데이터에 있는 도시 이름에 따라 날씨 데이터 가져오기
  const { data: weatherData } = useQuery({
    queryKey: ['weather'],
    queryFn: async (context) => {
      const { queryKey, meta, signal, pageParam } = context;
      return await fetchWeatherData(cityNames.Seoul);
    },
    enabled: isGameScheduleSuccess, // 게임 스케줄 데이터가 성공적으로 로드된 후에만 날씨 데이터 가져오기
  });

  console.log('gameScheduleData => ', gameScheduleData);
  console.log('weatherData => ', weatherData);

  // 날씨 데이터와 게임 스케줄 데이터를 병합하는 함수
  const mergeData = useCallback((gameSchedule, weather) => {
    const weatherInfo = weather ? weather.weather[0].main : '';
    return gameSchedule.map((data) => ({ ...data, weather: weatherInfo }));
  }, []);

  useEffect(() => {
    // 게임 스케줄 데이터에서 받은 날씨 정보 gameInfo에 새로운 키로 넣어주기
    if (isGameScheduleSuccess && weatherData) {
      const mergedData = mergeData(gameScheduleData, weatherData);
      setGameInfo(mergedData);
    }
  }, [weatherData, gameScheduleData, isGameScheduleSuccess, mergeData]);

  console.log('gameInfo => ', gameInfo);

  if (isGameSchedulePending) {
    return <div>데이터를 가져오는 중입니다...</div>;
  }

  return (
    <div className="w-6/12 h-3/6 bg-bgGray rounded-xl text-white">
      <ul className="w-full flex flex-col p-3 gap-0.5">
        {isGameScheduleSuccess &&
          gameInfo.map((game, index) => {
            return (
              <GameList
                key={index}
                weatherInfo={game.weather}
                gameInfo={game}
              />
            );
          })}
      </ul>
    </div>
  );
};

export default WeatherByGame;
profile
웹 프론트엔드 UXUI

0개의 댓글

관련 채용 정보