프론트엔드

2024.12.24

zayn 2024. 12. 24. 23:52

 

1. 프로젝트 소개

이 글에서는 Next.js, React Query, Riot Games API를 활용해 리그 오브 레전드의 챔피언 로테이션 페이지를 구현하고 배포 환경에서 발생한 문제를 해결하는 과정을 공유합니다.


2. 주요 기술 및 구현 목표

사용된 기술

  • Next.js 13: 최신 React 기능과 SSR/ISR 지원.
  • React Query: 클라이언트 상태 및 API 데이터 관리.
  • Riot Games API: 로테이션 데이터 및 챔피언 정보를 가져오기 위한 API.
  • TypeScript: 데이터 구조를 명확히 정의하여 안정성 확보.
  • Tailwind CSS: 빠르고 유연한 스타일링.

구현 목표

  1. Riot API를 통해 챔피언 로테이션 데이터를 가져와 UI에 표시.
  2. 에러 처리, 로딩 상태 관리, 다크 모드 지원.
  3. 배포 환경에서 발생한 에러를 해결하고 안정적인 데이터 로드 제공.

3. 구현 코드

3.1. Riot API 호출을 위한 서버 API 라우트

Next.js의 API 라우트를 활용해 Riot API와의 통신을 프록시 처리합니다.

// /pages/api/rotation.ts
import { NextApiRequest, NextApiResponse } from "next";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  try {
    const response = await fetch(
      "https://kr.api.riotgames.com/lol/platform/v3/champion-rotations",
      {
        headers: {
          "Content-Type": "application/json",
          "X-Riot-Token": process.env.NEXT_PUBLIC_RIOT_API_KEY!,
        },
      }
    );

    if (!response.ok) {
      throw new Error(`API 요청 실패: 상태 코드 ${response.status}`);
    }

    const data = await response.json();
    res.status(200).json(data);
  } catch (error) {
    console.error("API 요청 중 오류 발생:", error);
    res.status(500).json({ error: "API 요청 실패" });
  }
}

3.2. 클라이언트에서 데이터 호출

React Query를 활용해 API 데이터를 관리하고, 에러 및 로딩 상태를 처리합니다.

"use client";

import { useQuery } from "@tanstack/react-query";
import { getChampionRotation } from "@/utils/riotApi";
import { ChampionCard } from "@/components/ChampionCard";

export default function RotationPage() {
  const { data, error, isLoading, refetch } = useQuery(
    ["championRotation"],
    getChampionRotation,
    {
      retry: false,
      staleTime: 1000 * 60 * 5,
    }
  );

  if (isLoading) {
    return <div>로딩 중입니다...</div>;
  }

  if (error) {
    return (
      <div>
        <p>로테이션 데이터를 가져오는 중 오류가 발생했습니다.</p>
        <button onClick={() => refetch()}>다시 시도</button>
      </div>
    );
  }

  const { allPlayers, newPlayers } = data;

  return (
    <div>
      <h1>금주의 로테이션 챔피언</h1>
      <div>
        {allPlayers.map((champion) => (
          <ChampionCard key={champion.id} champion={champion} />
        ))}
      </div>
    </div>
  );
}

3.3. 데이터 처리 함수

Riot API에서 가져온 로테이션 데이터를 필터링하고 클라이언트에 전달합니다.

export async function getChampionRotation() {
  try {
    const res = await fetch("/api/rotation", {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      },
    });

    if (!res.ok) {
      throw new Error(`API 요청 실패: 상태 코드 ${res.status}`);
    }

    const data = await res.json();
    const champions = await fetchChampionsList();

    const allPlayers = champions.filter((champion) =>
      data.freeChampionIds.includes(Number(champion.key))
    );

    const newPlayers = champions.filter((champion) =>
      data.freeChampionIdsForNewPlayers.includes(Number(champion.key))
    );

    return { allPlayers, newPlayers };
  } catch (error) {
    console.error("로테이션 데이터를 가져오는 중 에러 발생:", error);
    throw new Error("로테이션 데이터 처리 실패");
  }
}

4. 문제 상황 및 해결 방법

문제: 배포 환경에서 "에러 다시 시도" 화면 표시

  • 원인:
    1. Riot API 호출 실패.
    2. 환경 변수(NEXT_PUBLIC_RIOT_API_KEY) 누락.
    3. 데이터 처리 중 필터링 로직에서 오류 발생.
  • 해결 방법:
    1. Riot API 요청 시 헤더에 X-Riot-Token이 올바르게 전달되도록 확인.
    2. getChampionRotation 함수에서 예외 처리를 개선.
    3. Vercel 환경에서 환경 변수를 올바르게 설정.

문제 해결 후 코드:

위에서 제시한 수정 코드를 통해 API 호출과 데이터 처리를 안정적으로 수행할 수 있습니다.


5. 결과

  • Riot API에서 가져온 데이터를 기반으로 로테이션 챔피언 정보를 성공적으로 표시.
  • React Query로 로딩/에러 상태를 관리하여 사용자 경험 개선.
  • 배포 환경에서도 안정적으로 작동하도록 문제를 해결.

6. 결론 및 팁

결론

Next.js와 Riot API를 활용한 챔피언 로테이션 페이지 구현은 복잡한 API 데이터 처리와 상태 관리를 효율적으로 처리하는 방법을 보여줍니다. React Query와 Next.js API 라우트를 결합하면 배포 환경에서도 안정적인 서비스를 제공할 수 있습니다.

개발 팁

  • API 요청 디버깅: console.log를 사용해 호출된 데이터와 상태를 항상 확인.
  • 환경 변수 관리: NEXT_PUBLIC로 시작하는 환경 변수는 클라이언트에서도 사용할 수 있도록 설정.
  • React Query 활용: 비동기 데이터 관리를 간소화하고, 캐싱을 활용해 성능 최적화.

 

'프론트엔드' 카테고리의 다른 글

2024.12.27  (2) 2024.12.27
2024.12.26  (0) 2024.12.26
가보자고 나혼자프젝  (0) 2024.12.23
팀프로젝트 뉴스피드 _ 3  (1) 2024.11.20
뉴스피드 팀프 _ 2  (0) 2024.11.19