[배우는 중] "성능 개선해주세요"가 사실은 숫자 세 개였다 — Core Web Vitals
막연히 "느리다"를 어떻게 손대야 할지 몰랐다. 구글이 매기는 LCP·INP·CLS 세 지표를 배우고 나니, 성능 작업이 "감"이 아니라 "숫자를 낮추는 일"로 바뀐 과정을 남긴다.
배우는 중(Learning log) — 완성된 정리가 아니라, 혼자 공부하다 막힌 지점과 그걸 넘은 과정을 그대로 남기는 시리즈입니다. 지금 제 이해라서 틀릴 수 있고, 나중에 알게 되면 정정 노트를 답니다.
퍼블리셔로 오래 일하며 “페이지 무겁다”, “빠르게 해달라”는 말을 참 많이 들었어요.
그런데 막상 개발로 넘어와 “그래서 뭘 손대지?”
앞에서 늘 막연했어요.
만든 페이지가 체감상 좀 굼떠서 최적화를 하고 싶었어요.
근데 뭘 먼저 봐야 할지 몰라서, 이미지 압축하고 코드 좀 줄이고 — 감으로 이것저것 만졌어요.
문제는 좋아졌는지 확인할 방법이 없다는 거였어요.
뭘 고쳐도 “빨라진 것 같기도 하고”로 끝났죠.
기준이 없으니 어디까지 해야 할지도 몰랐고요.
성능이 잴 수 있는 대상이라는 감각 자체가 없었어요.
그러다 Core Web Vitals를 알았어요.
구글이 “실제 사용자가 느끼는 품질”을 수치화한 세 지표.
”느리다”는 사실 이 셋 중 하나였어요.
| 지표 | 재는 것 | “좋음” 기준 |
|---|---|---|
| LCP (Largest Contentful Paint) | 가장 큰 콘텐츠(히어로 이미지·제목)가 뜨기까지 | 2.5초 이하 |
| CLS (Cumulative Layout Shift) | 로딩 중 레이아웃이 덜컹 밀리는 정도 | 0.1 이하 |
| INP (Interaction to Next Paint) | 클릭·입력 후 화면이 반응하기까지 | 200ms 이하 |
퍼블리셔의 언어로 옮기니 완전히 익숙했어요.
LCP는 “메인 비주얼이 몇 초 만에 보이나”. CLS는 “이미지에 width/height 안 넣어서 본문이 아래로 밀려 내려가나” — 이거 제가 늘 잡던 거잖아요.
INP는 “버튼 눌렀는데 굳어 있나”.
측정도 코드 몇 줄이면 돼요.
import { onLCP, onCLS, onINP } from 'web-vitals';
onLCP(console.log);
onCLS(console.log);
onINP(console.log);
CLS 예방은 사실 퍼블리셔의 오랜 습관 그대로였고요.
img { width: 100%; aspect-ratio: 16 / 9; } /* 자리를 미리 확보 */
가장 크게 바뀐 건 작업 순서였어요.
그동안 배운 코드 스플리팅·메모이제이션·useDeferredValue 같은 게 전부 이 세 숫자를 낮추는 수단이었던 거예요.
검색 인풋에 타이핑할 때마다 1만 개 리스트를 필터링해 버벅이면 INP가 나빠지고, 그럼 useDeferredValue. 이제 “감으로 memo 붙이기”가 아니라 어느 지표가 나쁜지 재고 그에 맞는 무기를 꺼내는 순서가 생겼어요.
“성능 개선해주세요”는 대부분 이 세 숫자를 낮춰달라는 뜻이었어요.
아직 모르는 것도 있어요.
Lighthouse의 실험실 점수와 실제 사용자 데이터(CrUX)가 다르게 나올 때 어느 걸 믿어야 하는지.
INP를 실제로 낮추는 구체적 기법 — 입력 응답을 쪼개는 방법 같은 건 다음에.
혹시 “느린데 뭘 손대야 할지 모르겠는” 중이면 — LCP·CLS·INP 중 뭐가 나쁜지부터 재보세요.
막연함은 대개 측정을 안 해서 생기더라고요.
댓글