본문 바로가기

TIL

fetch json() 메서드 적용이 안되는 문제

🚨 문제

route handler 를 컴포넌트에서 불러오는 과정에서 .json() 부분에 오류가 있다는 에러 메세지를 계속 마주했다.  

// app/api/rotation/route.ts
export async function GET(request: Request) {
  const res = await fetch(
    "https://kr.api.riotgames.com/lol/platform/v3/champion-rotations",
    {
      headers: {
        "Content-Type": "application/json",
        "X-Riot-Token": process.env.RIOT_API_KEY!,
      },
    }
  );
  const data: ChampionRotation = await res.json();
  const response = await getChampionList();
  const arr: List[] = Object.values(response);
  const championId: number[] = data.data.freeChampionIds;
  const rotationChampion = arr.filter((champion) =>
    championId.includes(+champion.key)
  );
  return NextResponse.json({ rotationChampion });
  }

 

// app/rotation/page.tsx
"use client"
const getChampionRotation = async () => {
  const res = await fetch("api/rotation");
  console.log(res);
  const data = await res.json();
  return data;
};

const Rotation = () => {
  const [championData, setChampionData] = useState<List[]>([]);
  useEffect(() => {
    getChampionRotation().then(setChampionData);
  }, []);
  if (!championData) {
    return <div>loading...</div>;
  }
  return (
   ⋮
   )
};
export default Rotation;

 

 

❓ 원인

컴포넌트에서 route handler를 fetch한 response 를 콘솔에 찍어 보니 아예 응답을 못받고 있는 것 같았다.

 

그래서 route handler 파일에서 값들을 하나하나 콘솔에 찍어보았다.

처음에 fetch한 응답값에 await res.json() 한 로직이 아예 파싱처리가 안되어서 그 아래 로직들이 전부 막혔던 것이었다.

그렇게 처리가 안된 상태인 response 에 NextResponse.json 을 해주어서 response 를 이중으로 return 해준 상태였다.

그래서 컴포넌트에서 아무리 response.json() 을 해도 한겹만 벗겨냈기 때문에 response 가 아직 남아있던 것.

(컴포넌트에서 호출하면 무조건 response 에서 한번 묶여서 옴(async await 으로 호출하니깐))

 

 

✅ 해결 방법

json() 이 적용이 안되어서 응닶값을 await res.json() 이 아니라 await res.text() 해주어 응답값을 text(string)로 바꿔주고,

text로 바꾼 해당 값을 JSON.parse(data) 해서 json으로 파싱 해주었더니 파싱처리가 정상적으로 되어 벗겨낸 데이터 값을 받을 수 있었다.

// app/api/rotation/route.ts
export async function GET(request: Request) {
  const res = await fetch(
    "https://kr.api.riotgames.com/lol/platform/v3/champion-rotations",
    {
      headers: {
        "Content-Type": "application/json",
        "X-Riot-Token": process.env.RIOT_API_KEY!,
      },
    }
  );
  // 에러 처리
  if (!res.ok) {
    throw new Error("network error");
  }
  // res.text() 텍스트 변환 후 JSON.parse 
  const data: string = await res.text();
  const parsedData = JSON.parse(data);

  const response = await getChampionList();
  const arr: List[] = Object.values(response);

  const championId: number[] = parsedData.freeChampionIds;
  const rotationChampion = arr.filter((champion) =>
    championId.includes(+champion.key)
  );

  return NextResponse.json({ rotationChampion });
}
// app/rotation/page.tsx
"use client"
const Rotation = () => {
  const [championData, setChampionData] = useState<List[]>([]);

  const getChampionRotation = async () => {
    const res = await fetch("/api/rotation");
    const data = await res.json();
    setChampionData(data.rotationChampion);
  };

  useEffect(() => {
    getChampionRotation();
  }, []);

  if (!championData) {
    return <div>loading...</div>;
  }

  return(
   ⋮
   )
};

export default Rotation;

 

+ 추가로 이해한 개념

Next 에서 "use client" 일때 전체 컴포넌트에는 async await 를 사용 못하지만 전체 컴포넌트의 안/밖 으로는 사용이 가능하다.!

 

 

☀︎ JSON.parse()와 response.json()의 차이

JSON.parse()에는 응답(response) 바디만을 넣어야한다. 바디와 헤더가 들어가면 데이터를 읽어오지 못한다
response.json()에는 응답 헤더가 들어가도 바디만 읽어서 불러온다.

 

 

🥲 느낀점

json() 이 적용이 되었으면 간단하게 쓸 수 있는걸  .text JSON.parse 로 두줄로 풀어서 처리해주었다..

json() 이 안먹히는 이유는 못찾았다.ㅠ

그래도 헷갈렸던 개념들을 좀 더 살펴보게 된 시간이 된 것 같다.

'TIL' 카테고리의 다른 글

ERD (Entity Relationship Diagram)  (3) 2024.10.10
type 과 interface 의 차이점  (0) 2024.10.09
typescript-eslint/no-unused-vars  (0) 2024.10.07
Route Handler & Server Action 제대로 이해하기  (1) 2024.10.05
절대경로 import alias @/*  (0) 2024.10.04