Next.js에서는 sharp 라이브러리와 결합해 이미지 최적화 기능을 제공합니다.
<aside>
Next.js 환경에서 Image 컴포넌트와 sharp 라이브러리의 활용은 강력하게 권장됩니다. 이미지가 웹페이지에서 가장 큰 자원을 점유하는 콘텐츠 중 하나인만큼 최적화를 사용하냐 아니냐에 따라 웹에서의 성능이 크게 달라집니다.
Trablock 프로젝트는 이미지를 많이 사용하는 서비스이므로 필연적으로 Image 컴포넌트를 많이 사용합니다. 이 과정에서 공통으로 적용하는 속성이 있었고, 이를 공통화하여 정리하는 과정이 필요했습니다. 필요한 기능을 정리하고 구현한 첫 코드는 다음과 같았습니다.
<aside>
image-cover 속성 적용priority 에 따라 loading 자동 지정
</aside>interface NextImageProps extends Omit<ImageProps, 'width' | 'height'> {
width: number;
height: number;
}
function NextImage({
className,
src,
alt,
width,
height,
loading = 'lazy',
priority,
...restImageProps
}: NextImageProps) {
return (
<div className={`overflow-hidden ${className}`}>
<Image
{...restImageProps}
className="image-cover"
src={src}
alt={alt}
width={width}
height={height}
loading={priority ? 'eager' : loading}
priority={priority}
/>
</div>
);
}
위 코드를 사용하다보니 불편한 점이 있었습니다. 만약 src가 빈 문자열일 경우 Image 컴포넌트에서 컴파일 에러가 발생하는데, 이 때 에러를 처리하기 위해서는 src가 없을 때 표시할 대체 이미지를 사용하거나 Image 컴포넌트 자체를 렌더링하지 않아야 합니다. 이 문제를 위해 추가하고자 한 기능은 다음과 같습니다.
<aside>
src가 없을 경우 배경색으로 공간을 채운다.src가 있을 경우 Image 컴포넌트를 렌더링한다.
</aside>export interface NextImageProps extends Omit<ImageProps, 'width' | 'height' | 'src'> {
placeholderClassName?: string;
width: number;
height: number;
src?: ImageProps['src'];
}
export default function NextImage({
className,
placeholderClassName,
src,
alt,
width,
height,
loading = 'lazy',
priority,
...restImageProps
}: NextmageProps) {
// src가 없을 때 배경색 렌더링
if (!src) {
return (
<div className={`overflow-hidden ${className}`}>
<div className={`size-full bg-gray-02 ${placeholderClassName}`} />
</div>
);
}
// src가 있을 때 Image 컴포넌트 렌더링
return (
<div className={`overflow-hidden ${className}`}>
<Image
{...restImageProps}
className="image-cover"
src={src}
alt={alt}
width={width}
height={height}
loading={priority ? 'eager' : loading}
priority={priority}
/>
</div>
);
}
src가 있을 때 Image 컴포넌트를 렌더링하고, 없을 때 플레이스홀더를 렌더링하게 처리하는 로직에는 처리해야하는 문제가 추가적으로 발생했습니다.
<aside>
src가 유효하지 않거나 서버에서 이미지를 가져오는데 실패할 경우 못생긴 아이콘과 텍스트가 표시되는 문제
이미지가 로드되기 전에 빈 공간이 유지되는 문제
원본 이미지의 비율이 다양해 이미지의 크기가 정해진 width, height 중 하나보다 작은 경우가 발생하는 문제
따라서 기존 컴포넌트는 NextServerImage로 분리해 서버 측 전용으로 사용하고, NextImage를 클라이언트 측 전용으로 전환해 문제를 해결할 기능을 추가했습니다.