본문 바로가기
개발

[CSS] 이미지가 로딩되면서 버튼 위치가 쿵 내려앉는다? CLS(누적 레이아웃 이동) 해결기

by 돌미나리는야생미나리 2026. 8. 28.

웹 서핑을 하다가 기사나 상품 페이지를 읽는 도중, 상단 이미지가 뒤늦게 다운로드되면서 화면 전체가 덜컹 내려앉아 엉뚱한 버튼을 잘못 클릭해 본 경험이 다들 한 번쯤 있으실 겁니다.

저 역시 초기 웹 프로젝트를 배포한 뒤 모바일 환경에서 테스트를 하다가 동일한 문제를 겪었습니다. 텍스트가 먼저 렌더링 된 후 용량이 큰 배너 이미지가 0.5초 뒤에 늦게 로딩되면서, 사용자가 클릭하려던 '장바구니 담기' 버튼이 아래로 쑥 밀려 내려가 '구매 취소' 버튼을 누르게 만드는 치명적인 UI 버그가 발생한 것입니다.

구글 라이트하우스(Lighthouse) 성능 점수를 측정해 보니 CLS(Cumulative Layout Shift, 누적 레이아웃 이동) 점수가 빨간색 경고(0.35 이상)를 기록하고 있었습니다.

오늘은 화면 깜빡임과 덜컹거림을 완벽히 잡고 부드러운 사용자 경험을 만들어 준 CLS 개선 노하우와 최신 CSS aspect-ratio 및 스켈레톤 UI 적용법을 공유해 보려고 합니다.

1. 내가 마주친 문제: "왜 화면이 덜컹거리며 밀려날까?"

브라우저가 HTML을 파싱할 때, 이미지 태그에 가로/세로 크기 정보가 미리 지정되어 있지 않으면 브라우저는 해당 이미지의 크기를 0 x 0 픽셀로 간주하고 아래 요소들을 먼저 위로 바짝 끌어올려 배치합니다.

HTML
 
<!-- ❌ 브라우저가 이미지 크기를 미리 알 수 없어 CLS를 유발하는 위험한 태그 -->
<img src="https://example.com/banner.jpg" alt="이벤트 배너" />

그 후 네트워크를 통해 실제 이미지 파일이 다운로드되면, 브라우저는 그제야 이미지의 진짜 높이(예: 400px)를 인식하고 아래에 있던 콘텐츠들을 강제로 밀어내는 재배치(Reflow / Relayout) 작업을 수행합니다. 이것이 바로 레이아웃 덜컹거림(Layout Shift)의 원인입니다.

2. 해결 방법 1: width와 height 속성으로 종횡비(Aspect Ratio) 미리 알려주기

가장 기본적이면서 강력한 해결법은 HTML <img> 태그에 반드시 원본 이미지의 width와 height 속성을 명시해 주는 것입니다.

HTML
 
<!-- ⭕ 브라우저가 이미지 비율을 미리 계산하여 공간을 확보함 -->
<img 
  src="https://example.com/banner.jpg" 
  alt="이벤트 배너" 
  width="800" 
  height="450" 
  style="width: 100%; height: auto;" 
/>

최신 브라우저는 태그에 적힌 width와 height 값을 기반으로 이미지가 로딩되기 전부터 종횡비(Aspect Ratio: 16/9)를 미리 계산해 정확한 높이의 빈 공간을 미리 예약해 둡니다. 따라서 이미지가 늦게 다운로드되어도 주변 레이아웃이 1픽셀도 흔들리지 않습니다.

3. 해결 방법 2: 최신 CSS aspect-ratio 속성 활용하기

동적으로 불러오는 외부 이미지나 반응형 카드 컴포넌트에는 최신 CSS 속성인 aspect-ratio를 사용하면 훨씬 유연하게 공간을 확보할 수 있습니다.

CSS
 
/* ⭕ 이미지가 다운로드되기 전에도 16:9 비율 공간을 강제로 유지 */
.banner-image-container {
  width: 100%;
  aspect-ratio: 16 / 9;
  background-color: #1e293b; /* 로딩 전 빈 공간에 어두운 배경색 지정 */
  border-radius: 12px;
  overflow: hidden;
}

.banner-image-container img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

과거에 padding-top: 56.25% 같은 복잡하고 난해한 핵(Hack)을 쓰던 방식에서 벗어나, 단 한 줄의 CSS로 완벽한 반응형 종횡비 공간을 예약할 수 있게 되었습니다.

📸 [사진 첨부 가이드 1]

여기에 VS Code에서 aspect-ratio: 16 / 9; 및 이미지 컨테이너 CSS 코드가 작성된 에디터 스크린샷을 넣으세요!

(캡처 팁: CSS 속성 중 aspect-ratio와 object-fit: cover 부분이 한눈에 들어오도록 에디터 화면을 스크린샷 찍어 첨부해 주세요.)

이미지 컨테이너 css

4. 해결 방법 3: 스켈레톤 UI(Skeleton)로 로딩 체감 속도 극대화

API 통신으로 데이터를 받아오는 동안에는 빈 화면 대신 스켈레톤(Skeleton UI)을 띄워 공간을 유지하면서 사용자에게 "데이터를 불러오는 중"이라는 시각적 피드백을 주는 것이 좋습니다.

CSS
 
/* 은은하게 반짝이는 스켈레톤 애니메이션 */
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

.skeleton-box {
  width: 100%;
  aspect-ratio: 16 / 9;
  background-color: #334155;
  animation: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  border-radius: 8px;
}

스켈레톤 UI를 적용하면 레이아웃 밀림 방지는 물론, 사용자가 대기 시간을 훨씬 짧게 체감하게 만드는 효과가 있습니다.

이미지 로드 전 스켈레톤
이미지 로드 후 상태

5. 결론 및 느낀 점

구글 검색 엔진은 이제 단순히 텍스트 내용뿐만 아니라 사용자가 화면을 조작할 때 시각적 안정성을 유지하는지(Core Web Vitals)를 중요한 랭킹 요소로 평가합니다.

  1. 모든 <img> 태그에 종횡비 정보(width/height 또는 CSS aspect-ratio)를 명시할 것
  2. 동적 콘텐츠 로딩 구간에는 미리 높이를 확보한 스켈레톤 UI를 배치할 것

이 두 가지 원칙만 지켜도 화면이 덜컹거리는 불쾌한 사용자 경험을 없애고 웹 사이트의 전문성과 완성도를 한 단계 끌어올릴 수 있습니다!