back

Posts

next/image - Error handling

2023-07-03

문제 상황

회사에서 리팩토링을 진행하던 중, 이미지 렌더링과 관련된 이슈를 발견했다.

기존 코드의 동작

<Image
  alt={"이미지"}
  src={imgUrl ? imgUrl : DEFAULT_IMG_URL}
  width={width}
  height={height}
/>

기존 코드는 다음과 같이 동작한다:

  1. API 호출로 이미지 경로(imgUrl)를 받아온다
  2. imgUrl이 null이나 undefined인 경우 DEFAULT_IMG_URL을 렌더링한다
  3. 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)}
    />
  );
}

동작 원리

  1. 초기 상태: imgSrc state를 props로 받은 src 값으로 초기화한다
  2. 정상 로드: 이미지가 정상적으로 로드되면 그대로 표시된다
  3. 에러 발생: 이미지 로드에 실패하면 onError 핸들러가 실행되어 imgSrcDEFAULT_PROFILE_IMG_URL로 변경한다
  4. 폴백 이미지 표시: state가 업데이트되면서 기본 이미지가 렌더링된다

개선된 점

이제 다음 두 가지 상황을 모두 처리할 수 있게 되었다:

  1. 이미지 경로가 null/undefined인 경우: 부모 컴포넌트에서 기본 이미지 경로를 전달
  2. 이미지 경로는 존재하지만 로드에 실패하는 경우: onError로 자동으로 폴백 처리

추가 고려사항

프로덕션 환경에서는 다음 사항들도 고려할 수 있다:

  • 무한 루프 방지: 폴백 이미지도 로드 실패할 경우를 대비한 처리
  • 로딩 상태 표시: 이미지 로딩 중 스켈레톤 UI 표시
  • 에러 로깅: 이미지 로드 실패 시 모니터링 시스템에 로그 전송