Next.js Image는 src랑 alt만 필수 속성 아니었어?

Dev
2025-12-11

사건의 발단: SVG를 컴포넌트처럼 사용하고 싶었다

처음에는 SVG 아이콘을 아래처럼 React 컴포넌트 형태로 사용하고 싶었다.

<IcTicket width={24} height={24}/>

하지만 SVG 파일을 컴포넌트처럼 불러오려고 하자 다음과 같은 에러가 발생했다. 컴포넌트처럼 불러오니 뜬 에러창 캡쳐본

에러 메시지를 보면, SVG 파일이 아직 React 컴포넌트가 아닌데 함수형 컴포넌트처럼 렌더링하려 해서 발생한 오류임을 알 수 있다. 이를 해결하기 위해 @svgr/webpack을 설치하고, next.config.mjs에 SVGR 설정을 추가하자 SVG를 정상적으로 컴포넌트처럼 사용할 수 있게 되었다.

npm install @svgr/webpack
# 또는
yarn add @svgr/webpack
webpack: (config) => {
    config.module.rules.push({
        test: /\.svg$/,
        use: ["@svgr/webpack"],
    });
 
    return config;
},

또 다른 문제: Image 컴포넌트에서 발생한 width 에러

이후 Header 컴포넌트를 구현하는 과정에서 다음과 같은 코드가 있었다.

<section className={styles.headerSection}>
  <Header
    left={<Image src={"/assets/imgs/img_cgv.jpg"} alt="cgv 로고" />}
    right={
      <div className={styles.rightHeaderSection}>
        <IcTicket width={24} height={24} />
        <IcAlarm width={24} height={24} />
        <IcSearch width={24} height={24} />
      </div>
    }
  />
</section>

여기서 Image 컴포넌트의 src에 문자열 경로를 직접 전달하자 다음과 같은 에러가 발생했다.

Error: Image with src "..." is missing required "width" property.

즉, Image 컴포넌트에 width를 지정하지 않았다는 오류였다. width 에러 캡쳐본

내가 알고 있는 Image 컴포넌트에서는 src와 alt만 필수값인데...!?


그런데 이상한 점이 있었다. 같은 Image 컴포넌트인데, 아래처럼 이미지를 import해서 전달하면 에러가 발생하지 않았다.

import ImgLogoCGV from "@/assets/imgs/img_cgv.jpg";
 
<Image src={ImgLogoCGV} alt="cgv 로고" />

왜 문자열 경로를 사용할 때는 에러가 나고, import로 불러온 이미지를 사용할 때는 에러가 나지 않지?

이유: import된 이미지는 "메타데이터"를 알고 있다

차이는 src에 전달되는 값의 형태였다.

  • 문자열 경로("/assets/imgs/img_cgv.jpg")
    → 단순한 이미지 URL
  • import로 불러온 이미지
    → 빌드 시점에 width와 height 정보를 포함한 Static Image Import 객체

즉, import로 가져온 이미지(png/jpg/webp 등)는 빌드 타임에 이미지의 크기 메타데이터를 이미 알고 있기 때문에 widthheight를 명시하지 않아도 동작할 수 있다.

반면 문자열 경로로 전달한 경우에는 Next.js가 이미지 크기를 미리 알 수 없기 때문에, fill을 사용하지 않는다면 width와 height를 반드시 지정해야 한다.
Next.js 공식 문서에서도 Image 컴포넌트는 fill 속성을 사용하지 않는 경우 widthheight를 필수로 지정해야 한다고 명시되어 있다.


해결방법

  1. SVG를 Image 컴포넌트로 사용하고 싶다면
    정적 경로 또는 import한 이미지 객체를 src로 전달해야 한다.
import ImgLogoCGV from "@/assets/icons/ic_cgv.jpg";
 
// static import → 메타데이터 있음
<Image src={ImgLogoCGV} alt="cgv 로고" />  // ✅
<Image src={ImgLogoCGV} alt="cgv 로고" fill />  // ✅
<Image src={ImgLogoCGV} alt="cgv 로고" width={24} height={24}/>  // ✅

반대로, 문자열 경로를 사용할 경우에는 width/height 또는 fill이 필요하다.

import ImgLogoCGV from "@/assets/icons/ic_cgv.jpg";
 
// 확장자가 무엇이든 직접 경로 지정했으면 width/height 또는 fill 속성 필수
<Image src='/assets/icons/ic_cgv.jpg' alt="cgv 로고" /> // ❌
<Image src='/assets/icons/ic_ticket.svg' alt="티켓" />  // ❌
 
  1. SVG를 컴포넌트로 쓰고 싶다면
    Image 컴포넌트를 사용하지 말고 직접 렌더링한다.
import IcTicket from "@/assets/icons/ic_ticket.svg";
 
// SVG는 React 컴포넌트로 직접 렌더링
<IcTicket /> // ✅

왜 Next.js Image 컴포넌트는 img 태그와는 달리 width와 height를 필수로 요구할까?

Next.js의 <Image>는 단순한 태그가 아니라, 이미지 최적화를 위해 만들어진 React 컴포넌트다. 그래서 이미지의 크기를 명확히 알아야 다음과 같은 작업을 수행할 수 있다.

  1. 레이아웃 시프트(CLS) 방지
    렌더링 전에 이미지 영역을 확보해 화면이 밀리는 현상을 방지한다.

  2. 반응형 이미지 최적화 제공
    Next.js는 기기 크기에 맞는 최적의 이미지 크기를 자동으로 계산해 제공한다.

  3. SVG는 원본 크기 정보가 없기 때문
    SVG는 벡터 이미지라 원본 크기 정보가 없다. SVGR을 적용하면 React 컴포넌트가 되기 때문에 Next.js가 자동으로 크기를 계산할 수 없다.


정리하면, Image 컴포넌트는 fill 속성을 사용할 때를 제외하고 widthheight를 반드시 지정해야 한다.

  • SVG를 컴포넌트처럼 사용하려면 → SVGR 설정이 필요
  • Image 컴포넌트의 src에는 → 이미지 정보만 전달 가능
  • import한 이미지는 → 메타데이터를 포함해 크기 자동 추론 가능
  • 문자열 경로를 사용할 경우 → fill이 아니면 width/height 필수

Image 컴포넌트의 src 규칙 요약

  • static import 이미지 → width/height 생략 가능
  • 문자열 경로 → fill이 아니면 width/height 필수
  • React 컴포넌트(SVGR SVG) → src로 사용 불가

참고 링크