🚀 프로젝트/리그 오브 레전드 정보 앱

리그 오브 레전드 정보 앱 | 트러블 슈팅 (2): TypeScript: 챔피언 데이터 인덱싱 오류 해결하기

seheej 2024. 10. 8. 09:57

1. 문제 상황

챔피언 목록을 Object.keys()로 순회하면서 key를 사용해 데이터를 참조하려고 할 때, 다음과 같은 오류를 마주했습니다.

import Image from "next/image";
import { getChampions, getLatestVersion } from "@/utils/serverApi";
import { Champion } from "@/types/Champion";

const ChampionsPage = async () => {
  const champions: Champion[] = await getChampions();
  const latestVersion = await getLatestVersion();

  return (
    <div>
      <h2>챔피언 목록</h2>
      <ul>
        <div className='champion-grid'>
          {Object.keys(champions).map((key) => {
            const champion = champions[key]; // 오류 발생 부분
            return (
              <div key={champion.id} className='champion-card'>
                <Image
                  src={https://ddragon.leagueoflegends.com/cdn/${latestVersion}/img/champion/${champion.image.full}}
                  alt={${champion.name}}
                  width={150}
                  height={150}
                />
                <h2>{champion.name}</h2>
                <p>{champion.title}</p>
              </div>
            );
          })}
        </div>
      </ul>
    </div>
  );
};

export default ChampionsPage;
Element implicitly has an 'any' type because index expression is not of type 'number'.ts(7015)
(parameter) key: string

 

이 오류는 Object.keys()로 가져온 key가 string 타입인 반면, champions가 배열로 정의되어 있어 타입 불일치가 발생한 것입니다.

 

2. 문제 분석

문제를 분석해보니, champions는 객체로서, 각 챔피언의 id를 키로 갖고 있는 구조였습니다. 하지만 TypeScript는 이를 명확하게 인식하지 못해 any 타입으로 처리했고, 이에 따른 인덱싱 오류가 발생한 것이었습니다.

 

3. 해결 과정

해결책은 챔피언 데이터를 객체 형태로 정의하고, 타입을 명확하게 지정하는 것이었습니다.

 

  1. 타입 정의 수정:
    • Record<string, Champion> 형태로 champions를 정의해, 키가 string 타입이고 값이 Champion 타입임을 명확히 지정했습니다.
    • const champions: Record<string, Champion> = await getChampions();
      
  2. 정확한 타입 지정 후 오류 해결:
    • champions[key]로 각 챔피언 데이터를 안전하게 참조할 수 있게 되었습니다.
    • {Object.keys(champions).map((key) => {
        const champion = champions[key];
        return (
          <div key={champion.id}>
            <h2>{champion.name}</h2>
            <p>{champion.title}</p>
          </div>
        );
      })}
       

4. 교훈

이 문제를 통해 TypeScript에서 타입 정의가 얼마나 중요한지 다시 한번 느꼈습니다. 특히 API에서 받아오는 데이터를 다룰 때는, 정확한 타입을 지정하여 안전한 코드를 작성하는 것이 중요합니다.

5. 향후 개선

  • 더 복잡한 상태 관리나 데이터 처리 로직을 추가할 때에도 TypeScript의 강점을 최대한 활용할 예정입니다.