[React Project] League of Legend(LOL) 전적 검색 사이트 만들기

Blackeichi·2022년 12월 5일
0
post-thumbnail

배포된 Project

애플리케이션 : https://lolwr.me/
깃 허브 Repository : https://github.com/blackeichi/lol-warriors

🎮 롤 전적사이트(lolwr.me)

RIOT DEVELOPER PORTAL (Riot - API)
라이엇의 API를 이용하여 사용자의 전적을 검색할 수 있는 어플리케이션 개발하기.

-한국어, 일본어, 영어 세 가지의 언어를 선택할 수 있음.
-검색 전적을 저장하여 입력창에서 추천으로 띄어줌
-아이콘, 랭크정보, 전적, 숙련도 등 유저 정보 제공하기
-끝난 게임의 상세 정보 제공하기
-현재 게임 중이라면 인게임 정보 제공

📌 제작 동기

LOL이라는 게임을 좋아하는 유저라면 OP.GG, FOW.KR와 같은 게임전적검색 사이트를 자주 이용할 것 이다. 나 또한 게임을 즐기면서 항시 켜놓는 사이트이다.

웹 서핑을 하다가 라이엇이 API로 유저, 전적 정보를 무료로 제공하고 있다는 것을 알게 되었고, 나도 내가 직접 만든 웹 앱에서 기존 사이트들과 같은 서비스를 제공하고 싶어 제작하게 되었다.

📌 사용 기술

  • TypeScript (language)
  • create-react-app (react)
  • react-router-dom (router)
  • styled-components (CSS in JS)
  • React-Query (Get Api Data)
  • Recoil (State Management Library for React)
  • Netlify (deploy)

📌 API 사용 방법

우선 Riot에서 제공하는 API KEY는 다음과 같이 세 종류이다.

1. 일회용 KEY
앱의 등록 및 승인기간이 필요없이 바로 사용할 수 있는 KEY입니다. 다만 RATE LIMITS가 걸려있으며, 24시간마다 KEY를 Regenerate해야 한다.

2. PRODUCTION API KEY
대규모 커뮤니티 또는 인터넷 전체를 대상으로 하는 제품에 사용되는 KEY입니다. 표준 API 및 토너먼트 API에 대한 액세스를 요청할 수 있습니다. 일반적으로 API 키를 받기 전에 작동하는 프로토타입이 필요하다.

3. PERSONAL API KEY
개발자나 소규모 개인 커뮤니티만을 위한 제품에 사용되는 KEY입니다. 이 제품들은 인증 절차 없이 등록이 가능하지만, 요금 제한 인상은 승인되지 않습니다. 표준 API에 대한 액세스를 요청할 수 있지만 토너먼트 API에는 액세스할 수 없습니다.

나는 Personal API KEY를 사용했으며, API는 다음과 같이 API주소 뒤에 api_key를 넣으면 된다.

ex) Lol Match API
https://asia.api.riotgames.com/lol/match/v5/matches/${matchId}?api_key=${API_KEY}

📙 폴더 구조

📂src
┣ 📂components
┃ ┣ 📂Map
┃ ┃ ┣ 📄EachUser.tsx
┃ ┃ ┣ 📄Mastery.tsx
┃ ┃ ┣ 📄Match.tsx
┃ ┃ ┣ 📄OpenMatch.tsx
┃ ┃ ┗ 📄RecentKDA.tsx
┃ ┣ 📄InputForm.tsx
┃ ┣ 📄LangSelect.tsx
┃ ┣ 📄Piechart.tsx
┃ ┣ 📄SummonerBot.tsx
┃ ┣ 📄SummonerTop.tsx
┃ ┗ 📄TitleCompo.tsx
┣ 📂Router
┃ ┣ 📄Search.tsx
┃ ┗ 📄Summoner.tsx
┣ 📂lang
┃ ┣ 📄i18n.ts
┃ ┣ 📜lang.en.json
┃ ┣ 📜lang.ko.json
┃ ┗ 📜lang.jp.json
┣ 📂util
┃ ┣ 📄atom.ts
┃ ┣ 📄color.ts
┃ ┣ 📄index.css
┃ ┗ 📄api.ts
┣ 📄App.tsx
┗ 📄index.tsx

📝 주요 로직

최근 전적의 챔프별 KDA와 승률 나타내기

#각 매치 Component

  const [KDAdata, setKDAdata] = useRecoilState(KDAstate);
  //상태 관리 라이브러리를 이용하여 각 매치의 kda와 승패여부를 저장
  useEffect(() => {
    const exist = KDAdata.filter(
      (data: any) => data.gameId === gameData?.info.gameId
    );
    if (exist[0]) {
    //이미 state에 저장되어있는 매치이면 return
    } else {
      if (gameData && Me?.challenges?.kda) {
        const newData = {
          gameId: gameData?.info.gameId,
          kda: Me?.challenges.kda,
          championName: Me?.championName,
          win: Me?.win,
        };
        setKDAdata([...KDAdata, newData]);
        //해당 매치의 정보를 객체로 생성하여 배열에 Add.
      }
    }
  });

#챔프 정보란(KDA, 승률)

-2022.12.06 수정✍ 객체 배열의 중복 제거 및 중복이 많은 순대로 정렬한 배열 만들기

  const KDAdata = useRecoilValue(KDAstate);
  //각 상태관리라이브러리에 저장된 각 매치들의 KDA와 승패여부 정보를 가져옴
  const recentChamp = KDAdata.reduce(
    (prev: any, current: any) =>
      prev.includes(current.championName)
        ? prev
        : [...prev, current.championName],
    []
  );
  //가져온 정보에서 챔피언 목록 생성(중복 제거)
  .........
  	{recentChamp.map((champ: any, index: any) => (
          <RecentKDA key={index} KDAdata={KDAdata} champ={champ} />
     ))}
    //챔피언 목록별로 컴포넌트 생성

#챔프 목록별 컴포넌트(RecentKDA)

  const [kda, setKda] = useState() as any;
  const [wins, setWins] = useState() as any;
  const gameData = KDAdata.filter((data: any) => data.championName === champ);
  //KDAdata중에서 전달받은 champ 데이터만 filter하기
  useEffect(() => {
    if (gameData?.length > 0) {
      setKda(
        (
          gameData?.reduce((prev: any, current: any) => {
            return prev + current?.kda;
          }, 0) / gameData.length
        ).toFixed(2)
      );
      //배열에서 KDA 평균 값
      setWins(
        (
          (gameData?.reduce((prev: any, current: any) => {
            if (current?.win) {
              return prev + 1;
            } else {
              return prev;
            }
          }, 0) /
            gameData.length) *
          100
        ).toFixed(0)
      );
      //배열에서 승률계산
    }
  });
  return (
  	//위에서 설정한 kda와 win으로 데이터 표시하기
  )

🤔 어려웠던 점

라이엇에서 제공하는 API의 정보들이 빈약한 부분이 다소 존재하였다. API에서 받은 데이터로 다시 다른 API정보를 요청하여 받아써야 하고 내가 구현하고 싶은 기능을 위해서 API에서 정보를 받아, 이것을 새로운 데이터로 만들어야 하는 경우가 있어 메모리낭비가 있다. 예를 들면 유저를 검색하였을 때 최근 20게임들의 승패비율을 보여주고자 하는데, 라이엇에서 검색된 유저의 최근 20게임들의 API정보를 받으면 해당 데이터에는 그 게임들의 승패 값을 포함하고 있지 않고 20판 각 게임들의 고유ID만을 가지고 있다. 그렇기 때문에 그 고유ID들을 가지고 다시 각 게임들의 세부사항 API에 접근해야하고, 거기서 승/패 값을 뽑아서 사용하여야 한다. 나는 상태 관리 라이브러리를 사용하여 승/패값을 저장하고 사용하는 방법을 사용하였는데 많이 비효율적으로 느껴진다.

⭐ 업데이트(수정) 예정

  • 승/패 데이터가 맞지않음
    • 가끔 API의 RATE LIMITS를 초과하여 Block당함.
  • 승/패 비율이 에러가 뜰 때가 있음.
    • 코드 수정
<이전 코드>
    setWins(
        (
          (gameData?.reduce((prev: any, current: any) => {
            return prev + current?.win ? 1 : 0;
          }, 0)
          //이 부분에서 prev가 0이나 1만 들어가게됌
          /
            gameData.length) *
          100
        ).toFixed(0)
      );
      
      
  <수정 코드>
  setWins(
        (
          (gameData?.reduce((prev: any, current: any) => {
            if (current?.win) {
              return prev + 1;
            } else {
              return prev;
            }
          }, 0) /
            gameData.length) *
          100
        ).toFixed(0)
      );
  • 챔프별 kda와 승률데이터 게임판수에 따라 정렬
  • 인 게임 정보 추가하기.
    • 추가 완료
  • LOL말고 다른 Riot 게임 전적검색도 추가
  • 챔피언 정보 페이지 만들기
  • Rune,Spell 아이콘을 컴포넌트로 만들고, hover하면 효과띄우기

😎 마무리

주변 사람들에게 사용해보것을 추천해볼만한 실용적인 사이트를 만든 것 같다. 피드백을 받고 점차 개선해나가며 큰 규모의 인원이 사용할 수 있을 정도의 높은 퀄리티의 서비스를 제공하고 싶다.

profile
프론트엔드 주니어 개발자 한정우입니다. 😁

0개의 댓글