본문으로 건너뛰기
개발 머꼬
개발 노트Next.js
hohyeon.dev20

next/image를 썼는데 레이아웃이 계속 흔들린 이유(CLS)

  • #Engineering Note
  • #Next.js
  • #Performance
  • #Web Vitals

문제 발생

페이지에 이미지를 추가한 뒤, 이미지가 로드되는 순간 아래쪽 콘텐츠가 갑자기 밀리는 현상(레이아웃 흔들림)이 발생했고, Core Web Vitals의 CLS(Cumulative Layout Shift) 점수가 나빠졌습니다.

원인 분석

일반 <img> 태그는 이미지가 실제로 로드되기 전까지 브라우저가 얼마나 공간을 차지할지 알 방법이 없습니다. next/image는 이 문제를 해결하기 위해 만들어졌지만, 사용 방식에 따라 여전히 같은 문제가 재현될 수 있습니다.

next/image를 쓸 때 width/height(또는 fill)를 생략하거나 잘못 지정하면, Next.js가 이미지의 실제 종횡비를 미리 계산해 공간을 예약해둘 수 없습니다. 특히 다음 두 경우가 흔한 원인입니다.

  1. 외부 URL 이미지의 실제 크기를 모른 채 임의의 width/height를 지정해, 실제 이미지 종횡비와 달라 로드 후 크기가 재조정되는 경우
  2. 부모 컨테이너가 CSS로 크기를 결정하는 상황에서 fill prop을 쓰지 않고 고정 width/height를 써서, 반응형 레이아웃에서 실제 표시 크기와 예약된 공간이 어긋나는 경우

해결 방안

  1. 이미지의 실제 크기를 안다면 정확한 width/height를 지정합니다 — Next.js가 이 비율로 공간을 미리 예약합니다.
<Image src={photo} alt="..." width={800} height={600} />
  1. 부모 컨테이너가 크기를 결정하는 반응형 레이아웃이라면 fill을 쓰고, 부모에 position: relative와 명시적 크기(또는 종횡비)를 지정합니다.
<div style={{ position: "relative", aspectRatio: "16/9" }}>
  <Image src={photo} alt="..." fill style={{ objectFit: "cover" }} />
</div>
  1. 로컬 정적 이미지(import photo from "./photo.jpg")를 쓰면 Next.js가 빌드 시점에 실제 크기를 자동으로 읽어와 width/height를 직접 안 넘겨도 됩니다.
  2. 우선순위가 높은 이미지(예: 첫 화면에 바로 보이는 hero 이미지)에는 priority prop을 줘서 지연 로딩 대신 즉시 로드되게 합니다 — 반대로 화면 아래에 있는 이미지에 priority를 남발하면 오히려 초기 로딩 성능이 나빠집니다.
  3. 실제 CLS 점수는 Chrome DevTools의 Performance 탭이나 Lighthouse로 측정해 수정 전후를 비교합니다 — 체감상 괜찮아 보여도 실제 점수로 확인하는 것이 중요합니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.