next/image를 썼는데 레이아웃이 계속 흔들린 이유(CLS)
문제 발생
페이지에 이미지를 추가한 뒤, 이미지가 로드되는 순간 아래쪽 콘텐츠가 갑자기 밀리는 현상(레이아웃 흔들림)이 발생했고, Core Web Vitals의 CLS(Cumulative Layout Shift) 점수가 나빠졌습니다.
원인 분석
일반 <img> 태그는 이미지가 실제로 로드되기 전까지 브라우저가 얼마나 공간을 차지할지 알 방법이 없습니다. next/image는 이 문제를 해결하기 위해 만들어졌지만, 사용 방식에 따라 여전히 같은 문제가 재현될 수 있습니다.
next/image를 쓸 때 width/height(또는 fill)를 생략하거나 잘못 지정하면, Next.js가 이미지의 실제 종횡비를 미리 계산해 공간을 예약해둘 수 없습니다. 특히 다음 두 경우가 흔한 원인입니다.
- 외부 URL 이미지의 실제 크기를 모른 채 임의의
width/height를 지정해, 실제 이미지 종횡비와 달라 로드 후 크기가 재조정되는 경우 - 부모 컨테이너가 CSS로 크기를 결정하는 상황에서
fillprop을 쓰지 않고 고정width/height를 써서, 반응형 레이아웃에서 실제 표시 크기와 예약된 공간이 어긋나는 경우
해결 방안
- 이미지의 실제 크기를 안다면 정확한
width/height를 지정합니다 — Next.js가 이 비율로 공간을 미리 예약합니다.
<Image src={photo} alt="..." width={800} height={600} />- 부모 컨테이너가 크기를 결정하는 반응형 레이아웃이라면
fill을 쓰고, 부모에position: relative와 명시적 크기(또는 종횡비)를 지정합니다.
<div style={{ position: "relative", aspectRatio: "16/9" }}>
<Image src={photo} alt="..." fill style={{ objectFit: "cover" }} />
</div>- 로컬 정적 이미지(
import photo from "./photo.jpg")를 쓰면 Next.js가 빌드 시점에 실제 크기를 자동으로 읽어와width/height를 직접 안 넘겨도 됩니다. - 우선순위가 높은 이미지(예: 첫 화면에 바로 보이는 hero 이미지)에는
priorityprop을 줘서 지연 로딩 대신 즉시 로드되게 합니다 — 반대로 화면 아래에 있는 이미지에priority를 남발하면 오히려 초기 로딩 성능이 나빠집니다. - 실제 CLS 점수는 Chrome DevTools의 Performance 탭이나 Lighthouse로 측정해 수정 전후를 비교합니다 — 체감상 괜찮아 보여도 실제 점수로 확인하는 것이 중요합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.