🚨 문제
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 |