Next.js 프로젝트

Next.js 프로젝트 트러블 슈팅 3

notion0896 2024. 12. 14. 01:33
  • 문제 1 : fetchChampionsDetail 함수 타입오류가 계속 남
  • 해결 방안 :  
export const fetchChampionsDetail = async (
  id: string
): Promise<Champion> => {
  try {
    const latestVersion = await fetchVersion();

    // 챔피언 상세정보 api
    const championDetailRes = await fetch(
      `${BASE_URL}/cdn/${latestVersion}/data/ko_KR/champion/${id}.json`
    );
    if (!championDetailRes)
      throw new Error("챔피언 목록을 불러오는데 실패했습니다");

    const championDetailData = await championDetailRes.json();
    return championDetailData;
  } catch (error) {
    console.error("championDetailData api호출 실패", error);
    throw new Error("챔피언 상세 정보를 가져오지 못했습니다");
  }
};

 

export const fetchChampionsDetail = async ( id: string ): Promise<Champion> => {

 

챔피언디테일 페이지인데 챔피언목록 페이지 타입을 정의해주고 있어서 타입 오류가 남.

 

export interface ChampionDetail {
  data: {
    [key: string]: {
      name: string;
      title: string;
      info: ChampionInfo;
      blurb: string;
      image: ChampionImage;
    };
  };
}

 

이런식으로 챔피언디테일 타입을 지정해주면 타입 오류가 안난다. 

 


 

  • 문제 2 : 챔피언 목록 중 하나를 클릭하면 그 챔피언의 상세 페이지가 나와야한다. 아이디를 어쩧게 받아올지 모르겠다...
  • 해결 방안 : 
export const fetchChampionsDetail = async ( id: string ): Promise<ChampionDetail> => {
  try {
    const latestVersion = await fetchVersion();

    // 챔피언 상세정보 api
    const championDetailRes = await fetch(
      `${BASE_URL}/cdn/${latestVersion}/data/ko_KR/champion/${id}.json`);
      
    if (!championDetailRes)
      throw new Error("챔피언 목록을 불러오는데 실패했습니다");

    const championDetailData = await championDetailRes.json();
    return championDetailData;
  } catch (error) {
    console.error("championDetailData api호출 실패", error);
    throw new Error("챔피언 상세 정보를 가져오지 못했습니다");
  }
};

 

 

먼저 챔피언디테일 api 호출하는 함수를 각 리스트별 id 값에 맞게 재사용 되도록 함수의 파라미터 안에 id 값을 넣고 타입을 정의 해준다. 그래야 api 호출 url이 그 id 값을 기준으로 받아와지기 때문.

 

이제 불러온 데이터를 바탕으로 화면에 뿌려줄 클라이언트 사이드에서 로직을 완성해보자

 

interface ChampionPageProps {
  params: { id: string };
}

 

 

id값을 params로 받아와야하기 때문에 타입 지정을 먼저 해줌.

 

export default async function ChampionDetailPage({ params }: ChampionPageProps) {
  const { id } = params;
  const championDetail = await fetchChampionsDetail(id);

  console.log("championDetail", championDetail);
  const latestVersion = await fetchVersion();

  return (
    <main>
      
    </main>
  );
}

 

 

ChampionDetailPage의 파라미터로 params를 받아서 id를 정의해주고, fetchChampionsDetail 함수의 인자를 id로 받아서 데이터를 뿌려준다. 

 

비상!!!비상!!!! 여기서 또 하나의 트러블 발생...

 

콘솔로 ChampionsDetail을 찍었을 때 데이터가 {{{}}} 이런식으로 객체 안에 객체 그 안에 객체 형태로 싸여있었다... 끔찍 ㅜㅜ

 

 

{
  type: 'champion',
  format: 'standAloneComplex',
  version: '14.24.1',
  data: {
    Aatrox: {
      id: 'Aatrox',
      key: '266',
      name: '아트록스',
      title: '다르킨의 검',
      image: [Object],
      skins: [Array],
      lore: '한때는 ... 복수를...',       
      allytips: [Array],
      enemytips: [Array],
      tags: [Array],
      partype: '피의 샘',
      info: [Object],
      stats: [Object],
      spells: [Array],
      passive: [Object],
      recommended: []
    }
  }
}

 

 

콘솔로 찍은 championsDetail은 이 따위 형태의 데이터였다... 내가 필요한건 저 객체 안에 data의 id 이하 데이터들인데 말이지...

 

return (
    <main>
      <div>
        <h1>{championDetail.data.id.name}</h1>
        <h2>{championDetail.data.id.title}</h2>
        <img
          src={`${BASE_URL}/cdn/${latestVersion}/img/champion/${championDetail.data.id.image.full}`}
          alt=""
        />
        <p>{championDetail.data.id.blurb}</p>
        <div>
          <ul>
            <li>공격: {championDetail.data.id.info.attack}</li>
            <li>방어: {championDetail.data.id.info.defense}</li>
            <li>마법: {championDetail.data.id.info.magic}</li>
            <li>난이도: {championDetail.data.id.info.difficulty}</li>
          </ul>
        </div>
      </div>
    </main>
  );

 

그래서 처음에는 이런식으로 접근했는데 절대 안나왔음. 당연함.. data에서 저 id 값으로 가기 위해선 Aatrox 라는 키값의 밸류로 또 접근을 해야했기 때문이다.

 

저런식으로 데이터에 접근을 하려면 championDetail.data.Aatrox.id.name 이렇게 해야하는건데,

Aatrox라고 적힌 id값은 매번 바뀌기 때문에 저렇게 쓰면 안된다. 

 

튜터님께 이거 어째야되냐고 물어본 결과... 기본적인 자바스크립트 코드인데 모르냐고 흠씬 두들겨 맞고 깨달음 ㅠㅠ 

 

객체안에 객체 형태인 상태에서 그 밸류값을 꺼내오기 위해선 대괄호 표기법으로 접근해야한다. 

const obj = { name: "Aatrox", age: 30 };

console.log(obj["name"]); // "Aatrox"

 

이런식으로 championDetail.data 안에 객체로 둘러싸인 id 값을 객체에서 빼내오기 위해선 data[id]로 접근을 해야하는것이다. 

return (
    <main>
      <div>
        <h1>{championDetail.data[id].name}</h1>
        <h2>{championDetail.data[id].title}</h2>
        <img
          src={`${BASE_URL}/cdn/${latestVersion}/img/champion/${championDetail.data[id].image.full}`}
          alt=""
        />
        <p>{championDetail.data[id].blurb}</p>
        <div>
          <ul>
            <li>공격: {championDetail.data[id].info.attack}</li>
            <li>방어: {championDetail.data[id].info.defense}</li>
            <li>마법: {championDetail.data[id].info.magic}</li>
            <li>난이도: {championDetail.data[id].info.difficulty}</li>
          </ul>
        </div>
      </div>
    </main>
  );

 

그 결과 이렇게 바꿔줬더니 너무너무 잘 나옴!!!! ><

 

  • 느낀점 : 세상에 공부할건 너무 많고 새로운 기능도 너무 많은데 예전에 배웠던 기능도 다 까먹는다... 복습 복습 자바스크립트가 모든것의 기초이니라...