Next.js 이미지 컴포넌트(next/image) width/height 강제 에러 우회법

Next.js Image 컴포넌트 width height 에러 우회 및 반응형 최적화 가이드
3초 요약: 이렇게 고치세요
  • 원인: next/image는 레이아웃 흔들림(CLS)을 막으려고 width·height를 미리 요구하는데, 반응형으로 늘어나는 이미지는 고정 픽셀을 줄 수 없어서 발생
  • 해결: 부모를 position: relative로 잡고 fill 속성 사용 / 데이터 절약이 필요하면 sizes 속성 추가 / 원본 비율만 아는 외부 이미지는 가상 비율값 + height: auto
  • 주의: fill만 쓰면 뷰포트와 무관하게 가장 큰 원본을 그대로 받아오므로, 모바일 트래픽이 걱정되면 sizes를 꼭 같이 지정할 것
<div style={{ position: 'relative', width: '100%', height: '300px' }}>
  <Image src="/hero.webp" alt="배너" fill style={{ objectFit: 'cover' }} />
</div>
↓ 왜 이런 에러가 나는지 원리 보기

Next.js에서 반응형 웹을 구현할 때 이미지 컴포넌트(next/image)를 쓰면 가로(width)와 세로(height)를 필수로 지정하라는 에러를 마주하게 됩니다. 고정 크기가 아니라 화면 너비에 맞춰 늘어나는 이미지를 쓰고 싶을 땐 이 제약을 우회할 방법이 필요한데, 상황별로 정리해 봤습니다.


Next.js는 왜 가로/세로 크기 지정을 강제하는가

Next.js의 next/image 컴포넌트가 일반 <img> 태그보다 강력한 이유는 웹 성능을 자동으로 최적화해 주기 때문입니다. 그중 핵심이 바로 CLS(Cumulative Layout Shift: 누적 레이아웃 이동) 방지입니다. 이미지가 로드되기 전에 브라우저가 이미지의 크기를 알지 못하면, 로딩이 끝난 순간 화면의 글자들이 아래로 툭 떨어지는 불쾌한 레이아웃 흔들림이 발생합니다. Next.js는 이를 막기 위해 사전에 이미지의 가로/세로 비율을 강제로 파악하려 하며, 지정하지 않으면 빌드 단계에서 에러를 뿜어냅니다. 실무에서는 CMS나 마크다운에서 가져온 이미지처럼 원본 크기를 미리 알 수 없는 경우에 이 에러를 가장 많이 만나게 됩니다.

일반 <img> 태그는 로딩 전에 공간을 확보해 두지 않아 이미지가 로드되는 순간 본문 텍스트가 아래로 밀리는 CLS 현상이 자주 발생합니다. Next.js Image 컴포넌트는 픽셀 값을 사전에 지정해 이미지 영역을 미리 확보해 두므로 이런 흔들림 없이 렌더링되고, 그만큼 SEO 점수에도 긍정적인 영향을 줍니다.


고정 크기를 우회하는 실전 반응형 구현법 3가지

방법 A: fill 속성과 부모 컴포넌트의 relative 조합 (가장 추천)

가장 보편적이고 Next.js가 공식적으로 지원하는 우회 통로입니다. widthheight를 명시하는 대신 fill 속성을 넣고, 이미지의 부모 컨테이너 크기에 이미지를 맞춰 채우도록 설계합니다.

import Image from 'next/image';

export default function ResponsiveImage() {
  return (
    // 1. 부모 컨테이너에 relative와 높이/너비를 반응형으로 설정
    <div style={{ position: 'relative', width: '100%', height: '300px' }}>
      <Image
        src="/images/hero.webp"
        alt="대형 배너 이미지"
        fill // 2. fill 속성으로 부모 영역을 가득 채우도록 선언
        style={{ objectFit: 'cover' }} // 3. 이미지 비율 깨짐 방지
      />
    </div>
  );
}

방법 B: sizes 속성을 통한 반응형 해상도 분기 최적화

fill을 사용하면 뷰포트 크기에 상관없이 가장 큰 해상도의 원본 이미지를 다운로드받을 수 있습니다. 모바일 환경에서의 데이터 낭비를 막으려면 브라우저 창 너비에 따른 이미지 크기 가이드를 주는 것이 좋습니다.

<div style={{ position: 'relative', width: '100%', height: '400px' }}>
  <Image
    src="/images/gallery.webp"
    alt="갤러리 사진"
    fill
    sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
    style={{ objectFit: 'contain' }}
  />
</div>

방법 C: 외부 이미지 도메인의 원본 비율 유지 기법 (aspect-ratio)

Blogger나 외부 CDN에서 원본 비율을 정확히 알 수 없는 동적 이미지 주소를 받아와 렌더링해야 할 때는 CSS의 aspect-ratio를 조합하여 해결합니다.

import Image from 'next/image';

export default function AspectRatioImage() {
  return (
    <div style={{ width: '100%', maxWidth: '600px' }}>
      <Image
        src="https://external.com/photo.webp"
        alt="가로세로 16대 9 유지 이미지"
        width={1600} // 가상의 비율 기준값 설정 (실제 화면 크기와 무관)
        height={900}  // 1600x900은 16:9 비율을 의미
        style={{ width: '100%', height: 'auto' }} // CSS 스타일로 크기 재정의
      />
    </div>
  );
}

CMS에서 이미지를 받아오는 프로젝트를 맡았을 때, 에디터가 세로로 긴 사진과 가로로 넓은 배너를 섞어 올리는 바람에 width·height를 고정값으로 박아뒀던 카드 레이아웃이 죄다 찌그러진 적이 있습니다. 처음엔 CMS 쪽에서 이미지 크기를 통일해달라고 요청하려다가, 방법 A의 fill+relative 조합으로 부모 컨테이너 비율만 고정하는 쪽이 훨씬 빨리 끝났습니다.


요약: 이미지 요구사항 대응 체크리스트

상황에 맞는 최적의 렌더링을 돕는 의사결정 요약 테이블입니다.

구현하려는 이미지 레이아웃 에러 원인 및 리스크 추천 해결 기술
반응형 배너 (예: 가로 100%) 가로세로 픽셀 고정 시 화면이 늘어날 때 깨짐 리스크 발생 fill + 부모 relative
모바일 데이터 절약 최적화 fill 속성 사용 시 너무 큰 해상도의 원본 이미지 일괄 로드됨 sizes 속성으로 반응형 사전 고지
외부 CDN 동적 원본 비율 유지 고정 수치 입력 불가 및 이미지 왜곡 비율 일그러짐 가상 비율 대입 + height: auto CSS
공식 참고 레퍼런스

이미지 압축 기술과 Next.js Image 최적화 옵션에 대한 자세한 내용은 공식 문서에서 확인할 수 있습니다.

호마다의 웹개발 팁

width/height 강제 규칙도 결국 브라우저가 이미지를 배치하고 리플로우하는 방식을 알아야 이해가 됩니다. 기초가 헷갈리신다면 [호마다의 IT 개발 입문 블로그] 의 HTML 이미지 태그 기초 글도 참고해보세요.

댓글

이 블로그의 인기 게시물

TypeScript: Unknown vs Any 타입 차이점과 안전한 타입 가드(Type Guard)

Next.js 하이드레이션 오류 원인과 해결법 완벽 정리

Next.js App Router에서 getServerSideProps 대체 및 데이터 페칭법