저번 아티클을 번역하면서 간단한 get 요청이지만 어떻게 UI적으로 신경쓸 수 있는 구성을 만들 수 있는지 확인해 보았었다.
해당 코드로 만들어낼 수 있는 화면은 다음과 같다.
'use client';
import Image from 'next/image';
import Skeleton from 'react-loading-skeleton';
import '../styles/index.css';
import 'react-loading-skeleton/dist/skeleton.css';
import { PokeDataType } from '../types';
const PokemonCard = ({
isLoading,
error,
data,
}: {
isLoading: boolean;
error: any;
data: PokeDataType;
}) => {
if (isLoading) {
return (
<article className="card">
<figure>
<Skeleton
baseColor="gray"
circle
enableAnimation
width={200}
height={200}
/>
<figcaption>
<Skeleton
baseColor="gray"
enableAnimation
height={21}
width={109}
/>
<Skeleton
baseColor="gray"
enableAnimation
height={21}
width={109}
/>
</figcaption>
</figure>
</article>
);
}
if (error) {
return (
<article className="card">
<figure>
<Image
width={200}
height={200}
src="https://ui.dev/images/courses/pokemon-unknown.png"
alt="pokemon error"
/>
<figcaption>
<h4>Oops.</h4>
<h6>{error}</h6>
</figcaption>
</figure>
</article>
);
}
return (
<article className="card">
<figure className="">
{data?.sprites?.front_default && (
<Image
width={200}
height={200}
src={data?.sprites?.front_default}
alt={data.name}
/>
)}
<figcaption>
<h4>{data.name}</h4>
<h6>No. {data.id}</h6>
</figcaption>
</figure>
</article>
);
};
export default PokemonCard;

여전히 무언가 아쉬운 점이 보인다.
일부러 개발자 콘솔로 인터넷 속도에 제약을 걸고 본다면 이미지 하나 당 2초 정도가 걸리는 것을 확인할 수 있다.
그리고 스크린샷으로 찍지는 못했지만, 사용량이 오버될때 페칭이 실패해 alt가 뜨는 모습도 확인할 수 있었다.

이번에 react-loading-skeleton으로 간편하게 컴포넌트의 로딩을 만들어내긴 했지만, 이미지 역시 비동기 콜이기 때문에 이 부분을 잡아주면 조금 더 괜찮은 UI가 될 거라고 생각한다.
// components/PokemonImage.tsx
'use client';
import React from 'react';
import Image from 'next/image';
type Props = {
front_default: string;
name: string;
};
const PokemonImage: FC<Props> = ({ front_default, name }) => {
const [src, setSrc] = React.useState(front_default);
return (
<Image
src={src}
width={200}
height={200}
onError={() =>
setSrc('https://ui.dev/images/courses/pokemon-unknown.png')
}
alt={name}
/>
);
};
export default PokemonImage;
페칭에 실패하는 경우는 쉽게 에러 이미지를 가져오도록 처리할 수 있었지만, 로딩의 경우는 조금 까다로운 것 같다.
사실 이번에 적용한 스켈레톤뷰의 경우 리액트 컴포넌트이기 때문에, 대체해주려면 svg를 사용해야 한다! 물론 넥스트의 Image 에 대한 이해가 부족해서 그런걸 수도 있겠지만...
이 부분에 대해서는 조금 더 나은 레퍼런스를 찾아보는 것이 좋겠다.