
1. 배포된 URL
이번에는 githubio를 사용해서 배포를 진행했습니다.
https://harang-dev.github.io/Poke-Dict.io/
Poke-Dict
harang-dev.github.io
클라우드 타입과 다르게 따로 건들지 않아도 24시간 동작합니다 ㅎㅎ
2. 어려웠던 점 & 아쉬웠던 점
이전에는 useInfiniteQuery를 사용해서 무한스크롤만 구현했었습니다.
이번에는 포켓몬의 상세한 정보까지도 알기 쉽게 하고 싶었는데, 처음에 제가 요청한 엔드포인트에서는 한글로 반환을 해주지 않았습니다.
그래서 구글링 및 여러 가지 엔드포인트를 건드리다 보니 어떤 조건의 맞는 값을 반환하는 코드를 작성할 수 있었습니다.
const koreanNameObj = (await axios.get(`${API}/pokemon-species/${id}`)).data.names.find(
(name) => name.language.name === "ko"
);
const koreanName = koreanNameObj ? koreanNameObj.name : "No Korean name";
또한, 상세페이지에는 포켓몬의 이름, 도감번호, 타입, 특성, 기본 스탯 등 여러 가지 정보가 포함되었기 때문에 한 가지 엔드포인트에서 가져올 수 있는 것이 아니었습니다.
그래서 여러가지 엔드포인트에서 원하는 값만을 추출해서 새로운 배열로 반환시킨 응답을 주고, 그 응답값을 사용해서 렌더링 하는 코드를 작성했습니다.
export const fetchPokemons = async (limit, offset) => {
const response = await axios.get(`${API}/pokemon?limit=${limit}&offset=${offset}`);
const pokemons = await Promise.all(
response.data.results.map(async (pokemon) => {
try {
const id = pokemon.url.split("/").slice(-2)[0];
const pokemonData = (await axios.get(`${API}/pokemon/${id}`)).data;
const sizeData = { height: pokemonData.height, weight: pokemonData.weight };
const statData = pokemonData.stats.map(stat => ({
name: stat.stat.name,
base_stat: stat.base_stat
}));
const backImage = pokemonData.sprites.back_default;
const image = pokemonData.sprites.front_default;
const koreanNameObj = (await axios.get(`${API}/pokemon-species/${id}`)).data.names.find(
(name) => name.language.name === "ko"
);
const koreanName = koreanNameObj ? koreanNameObj.name : "No Korean name";
let typeNames = [];
if (pokemonData.types && pokemonData.types.length > 0) {
typeNames = await Promise.all(
pokemonData.types.map(async (typeData) => {
try {
const typeResponse = await axios.get(typeData.type.url);
const koType = typeResponse.data.names.find(name => name.language.name === 'ko');
return { koreanName: koType.name };
} catch (error) {
console.error(`타입 데이터 가져오기 실패: ${error}`);
return { englishName: typeData.type.name, koreanName: "알 수 없음" };
}
})
);
}
let ability = [];
if (pokemonData.abilities && pokemonData.abilities.length > 0) {
ability = await Promise.all(
pokemonData.abilities.map(async (abilityData) => {
try {
const abilityResponse = await axios.get(abilityData.ability.url);
const koAbility = abilityResponse.data.names.find(name => name.language.name === 'ko');
const koAbilityEffect = abilityResponse.data.flavor_text_entries.find(entry => entry.language.name === 'ko');
const abilityName = koAbility ? koAbility.name : "알 수 없음";
const abilityEffect = koAbilityEffect ? koAbilityEffect.flavor_text : "설명 없음";
return { name: abilityName, effect: abilityEffect };
} catch (error) {
console.error(`능력 데이터 가져오기 실패: ${error}`);
return { name: "알 수 없음", effect: "설명 없음" };
}
})
);
}
return {
id,
name: koreanName,
image,
backImage,
types: typeNames,
size: sizeData,
stats: statData,
abilities: ability
};
} catch (error) {
console.error(`포켓몬 데이터 가져오기 실패: ${error}`);
return { id: null, name: "데이터 없음", image: null, types: [], size: null, stats: [], abilities: [] };
}
})
);
return pokemons;
};
기존에는 원하는 값을 바로바로 주는 그런 아주 친절한(?) 엔드포인트만 이용했어서, 여러개의 엔드포인트를 동시에 사용하는 부분이 어려웠습니다.
하지만 워낙 유명한 Open API라 너무나도 많은 분들이 진행하고 올려놓은 글들을 많이 참고했고, 저에게 좋은 공부가 되었습니다.
또한 반응형으로 웹을 처음 구현해봤는데 나름(?) 성공적으로 구현했다고 생각합니다 ㅎㅎ....
3. 페이지 소개
- 메인 화면
- 메인화면에는 flip 애니메이션을 사용하여 카드가 뒤집어지는 효과를 만들었습니다.
- 상세페이지
- 상세페이지에서는 포켓몬의 앞모습과 뒷모습 사진, 도감 번호, 타입, 특성, 기본스탯을 확인할 수 있습니다.
4. 마치면서
무한스크롤만 사용해서 진행했던 프로젝트에서 추가로 리팩토링을 거치며 프로젝트를 진행해 보았습니다.
반응형 웹도 처음 구현해 봤고, 여러 가지 엔드포인트를 하나로 묶어서 사용하는 것도 처음 해봤습니다.
아직도 저에게는 마냥 쉽게 다가와지지는 않지만 그래도 하나씩 배울 때마다 더욱더 흥미가 생기는 것 같습니다.
게을러지지 않고 앞으로 더 열심히 하도록 하겠습니다.
'Front-End > 프로젝트 리뷰' 카테고리의 다른 글
프로젝트 리뷰) 간단한 무한스크롤 만들기-실습편 (0) | 2024.11.26 |
---|---|
미니 프로젝트) 간단한 무한 스크롤 구현하기 (4) | 2024.11.26 |
미니 프로젝트) 간단한 to-do list 구현하기 (0) | 2024.11.26 |
프론트엔드 공부 기록 및 나의 성장기
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!