next/image - Error handling
2023-07-03문제 상황
회사에서 리팩토링을 진행하던 중, 이미지 렌더링과 관련된 이슈를 발견했다.
기존 코드의 동작
<Image
alt={"이미지"}
src={imgUrl ? imgUrl : DEFAULT_IMG_URL}
width={width}
height={height}
/>
기존 코드는 다음과 같이 동작한다:
- API 호출로 이미지 경로(
imgUrl)를 받아온다 imgUrl이 null이나 undefined인 경우DEFAULT_IMG_URL을 렌더링한다imgUrl이 존재하는 경우 해당 경로의 이미지를 렌더링한다
발견된 문제점
하지만 이 코드는 이미지 경로는 존재하지만 해당 이미지 파일 자체에 문제가 있는 경우를 처리하지 못했다.
예를 들어:
- 서버에서
"admin/img1"경로를 전달받았지만 - 해당 경로에 이미지 파일이 실제로 존재하지 않아 404 에러가 발생하거나
- 이미지 파일이 손상된 경우
이런 상황에서는 imgUrl이 null이 아니므로 조건문을 통과하지만, 실제로는 이미지 로드에 실패하여 깨진 이미지가 표시되는 문제가 있었다.
해결 방법
이 문제를 해결하기 위해 next/image의 onError 이벤트 핸들러를 활용한 커스텀 컴포넌트를 생성했다.
import { useState } from "react";
import Image from "next/image";
const DEFAULT_PROFILE_IMG_URL = "/images/default-profile.png";
interface ImageProps {
alt: string;
src: string;
width: number;
height: number;
}
export default function ImageWithFallback({
alt,
src,
height,
width,
}: ImageProps) {
const [imgSrc, setImgSrc] = useState<string>(src);
return (
<Image
alt={alt}
src={imgSrc}
width={width}
height={height}
onError={() => setImgSrc(DEFAULT_PROFILE_IMG_URL)}
/>
);
}
동작 원리
- 초기 상태:
imgSrcstate를 props로 받은src값으로 초기화한다 - 정상 로드: 이미지가 정상적으로 로드되면 그대로 표시된다
- 에러 발생: 이미지 로드에 실패하면
onError핸들러가 실행되어imgSrc를DEFAULT_PROFILE_IMG_URL로 변경한다 - 폴백 이미지 표시: state가 업데이트되면서 기본 이미지가 렌더링된다
개선된 점
이제 다음 두 가지 상황을 모두 처리할 수 있게 되었다:
- 이미지 경로가 null/undefined인 경우: 부모 컴포넌트에서 기본 이미지 경로를 전달
- 이미지 경로는 존재하지만 로드에 실패하는 경우:
onError로 자동으로 폴백 처리
추가 고려사항
프로덕션 환경에서는 다음 사항들도 고려할 수 있다:
- 무한 루프 방지: 폴백 이미지도 로드 실패할 경우를 대비한 처리
- 로딩 상태 표시: 이미지 로딩 중 스켈레톤 UI 표시
- 에러 로깅: 이미지 로드 실패 시 모니터링 시스템에 로그 전송