본문 바로가기
TIL

12. 12. 35일차 TIL next과제 시작

by 눈 새 2024. 12. 12.

오늘은 Riot에서 api key를 발급 받은 후 가져오는 로직과 함께 데이터의 타입을 작성하였다.


1. LOL 로테이션 정보 가져오기

route.ts는 Next.js의 API 라우트에서 사용할 수 있도록 설계되었으며 fetchChampionRotation 함수는 Riot Games API를 통해 챔피언 로테이션 데이터를 가져오는 서버 사이드 함수이다.  get 메서드를 통해 데이터를 가져왔다.

import { NextResponse } from "next/server";

export async function GET() {
  const RIOT_API_KEY = process.env.RIOT_API_KEY;
  const RIOT_API_URL =
    "https://kr.api.riotgames.com/lol/platform/v3/champion-rotations";

  if (!RIOT_API_KEY) {
    return NextResponse.json(
      { error: "Riot API key is missing in environment variables." },
      { status: 500 }
    );
  }

  try {
    const response = await fetch(RIOT_API_URL, {
      headers: {
        "X-Riot-Token": RIOT_API_KEY,
      },
    });

    if (!response) {
      throw new Error("패치 데이터가 없습니다");
    }

    const data = await response.json();
    return NextResponse.json(data);
  } catch (error) {
    return NextResponse.json(
      { error: "An unexpected error occurred." },
      { status: 500 }
    );
  }
}

2. LOL의 최신 정보 가져오기

1) 최신 버전 정보 가져오기 (getLatestVersion)

  • Riot Games API의 /versions.json 엔드포인트를 호출하여 최신 버전 목록을 가져왔다.
  • 반환되는 배열의 첫 번째 요소가 최신 버전을 나타내므로 이를 반환해주었다.
  • 예외 상황(네트워크 문제 등)을 처리하여 호출 실패 시 에러를 던졌고 오류의 타입을 any로 명시해주었다.
// utils/serverApi.ts

export const getLatestVersion = async (): Promise<string> => {
  try {
    const response = await fetch(
      "https://ddragon.leagueoflegends.com/api/versions.json"
    );
    if (!response.ok) {
      throw new Error("Failed to fetch versions");
    }
    const versions: string[] = await response.json();
    return versions[0];
  } catch (error: any) {
    throw new Error("Error fetching latest version: " + error.message);
  }
};

 

2) 챔피언 상세 정보 가져오기 (fetchChampionDetails)

  • 특정 챔피언 ID를 기반으로 Riot Games의 /champion/{id}.json 엔드포인트를 호출하여 해당 챔피언의 상세 정보를 가져올 수 있도록 하였다.
  • HTTP 응답 상태가 실패하면 에러 메시지와 상태 코드를 반환하도록 하였다.
  • 응답에 성공 시 챔피언 상세 정보를 반환하도록 하였다.
// utils/serverApi.ts

export async function fetchChampionDetails({ params }: { params: { id: string } }) {
  const championId = params.id;

  // 최신 버전 가져오기
  const latestVersion = await getLatestVersion();

  // 챔피언 정보 요청
  const championResponse = await fetch(
    `https://ddragon.leagueoflegends.com/cdn/${latestVersion}/data/ko_KR/champion/${championId}.json`
  );

  if (!championResponse.ok) {
    return NextResponse.json(
      { error: `Failed to fetch champion details: ${championResponse.statusText}` },
      { status: championResponse.status }
    );
  }

  const championData = await championResponse.json();

  // 챔피언 정보 반환
  return NextResponse.json(championData.data[championId]);
}

 

3) 아이템 정보 가져오기 (fetchItemDetails)

  • Riot Games의 /item.json 엔드포인트를 호출하여 최신 버전의 모든 아이템 정보를 가져왔다.
  • HTTP 응답 상태가 실패하면 에러 메시지와 상태 코드를 반환하도록 하였다.
  • 응답에 성공 시 아이템에 대한 정보를 반환하도록 하였다.
// utils/serverApi.ts

export async function fetchItemDetails() {
  // 최신 버전 가져오기
  const latestVersion = await getLatestVersion();

  // 아이템 정보 요청
  const itemResponse = await fetch(
    `https://ddragon.leagueoflegends.com/cdn/${latestVersion}/data/ko_KR/item.json`
  );

  if (!itemResponse.ok) {
    return NextResponse.json(
      { error: `Failed to fetch item details: ${itemResponse.statusText}` },
      { status: itemResponse.status }
    );
  }

  const itemData = await itemResponse.json();

  // 아이템 정보 반환
  return NextResponse.json(itemData.data);
}

3. 데이터 타입 지정

severApi.ts 파일에서 최신 서버의 정보를 가져올 때 스펠, 스킨, 등 모든 데이터를 가져왔으므로 이 또한 구분하여 타입을 지정해주었다. 챔피언의 상세정보와 아이템만을 구분했지만 나중에 필요하다면 스킨과 스펠, 등에 대한 정보만을 가져오는 로직을 작성해야 할 수도 있을 것 같다.

 

1) 챔피언 정보에 대한 데이터 타입 지정

// types/champions.ts

// 챔피언 디테일 데이터를 나타내는 타입
export interface ChampionDetails {
  id: string;
  name: string;
  title: string;
  lore: string;
  blurb: string;
  tags: string[];
  partype: string;
  info: {
    attack: number;
    defense: number;
    magic: number;
    difficulty: number;
  };
  spells: Spell[];
  passive: Passive;
  skins: Skin[];
}

// 스펠 데이터 타입
export interface Spell {
  id: string;
  name: string;
  description: string;
  tooltip: string;
  cooldown: number[];
  cost: number[];
  range: number[];
  image: Image;
}

// 패시브 데이터 타입
export interface Passive {
  name: string;
  description: string;
  image: Image;
}

// 스킨 데이터 타입
export interface Skin {
  id: string;
  name: string;
  num: number;
}

// 이미지 데이터 타입
export interface Image {
  full: string;
  sprite: string;
  group: string;
  x: number;
  y: number;
  w: number;
  h: number;
}

 

2) 아이템 정보에 대한 데이터 타입 지정

// types/items.ts

// 아이템 데이터를 나타내는 타입
export interface ItemDetails {
  [id: string]: {
    name: string;
    description: string;
    colloq: string;
    plaintext: string;
    gold: {
      base: number;
      total: number;
      sell: number;
      purchasable: boolean;
    };
    tags: string[];
    maps: {
      [mapId: string]: boolean;
    };
    stats: {
      [statName: string]: number;
    };
    image: Image;
  };
}

// 이미지 데이터 타입
export interface Image {
  full: string;
  sprite: string;
  group: string;
  x: number;
  y: number;
  w: number;
  h: number;
}


3) 로테이션 챔피언에 대한 데이터 타입 지정

// types/rotation.ts

export interface ChampionRotation {
  freeChampionIds: number[];
  freeChampionIdsForNewPlayers: number[];
  maxNewPlayerLevel: number;
}