누적 레이아웃 이동(CLS), 읽던 줄이 밀려나는 이유
읽던 문장이 밀리는 것은 로딩 속도와 다른 문제예요. CLS가 보는 움직임과 이미지·글꼴·광고의 공간을 미리 잡는 이유를 알아봐요.
이 글의 목차밀어내는 것은 대개 넷이다4
신문을 읽는데 누가 옆에서 광고지를 중간에 끼워 넣는다고 해 볼게요. 읽던 문장이 아래로 밀리고 눈은 방금까지 있던 줄을 다시 찾아야 해요. 광고지가 늦게 온 것이 문제가 아니라, 이미 자리를 잡은 것을 밀어냈다는 점이 문제예요.
이런 예기치 않은 움직임을 재는 지표가 CLS(Cumulative Layout Shift), 누적 레이아웃 이동이에요. 단순히 몇 픽셀 움직였는지만 보지는 않아요. 화면의 얼마나 넓은 부분이 얼마나 멀리 이동했는지를 함께 봐요. 느리게 뜨는 페이지와 읽던 줄을 밀어 버리는 페이지는 서로 다른 불편을 주는 거예요.
밀어내는 것은 대개 넷이다
첫째는 크기를 알려 주지 않은 이미지예요. 브라우저는 파일을 받아 보기 전에는 그 그림이 얼마나 높은지 몰라요. 그래서 자리를 비워 두지 않고, 그림이 도착한 뒤에야 그만큼을 밀어내요.
둘째는 광고예요. 광고는 무엇이 들어올지 요청하기 전에는 알 수 없고, 크기도 그때그때 달라요. 자리를 미리 잡아 두지 않으면 본문이 한 번 밀리고, 광고가 새로 고쳐질 때마다 또 밀려요. 광고를 배달하는 쪽에서도 슬롯에 공간을 미리 확보하라는 안내를 따로 내놓아요.
셋째는 글꼴이에요. 웹 글꼴을 내려받는 동안 기본 글꼴로 먼저 그렸다가 나중에 바꾸면 글자의 폭과 높이가 달라져 문단 전체가 흔들려요. 넷째는 페이지가 뜬 뒤에 위쪽에 무언가를 끼워 넣는 경우예요. 공지 띠나 동의 배너가 본문 위에 나중에 들어오면 아래의 모든 것이 그만큼 내려가요.
자리를 미리 잡아 두는 일
해결은 대체로 같은 모양이에요. 나중에 채울 것이라도 얼마나 차지할지를 먼저 알려 줘요. 이미지에는 실제 가로세로를 적어 두면 브라우저가 비율을 계산해 도착 전에 공간을 비워 둬요. 광고는 크기를 모르니 그 자리에 최소 높이를 정해 두고, 광고가 오지 않아도 그 공간이 그대로 남게 해요. 빈 공간이 낭비처럼 보이지만, 그 낭비가 밀림을 막아요.
같은 크기의 이미지를 두 지면에 늦게 채워 보세요.
자리 예약 안 함
읽던 문장은
이 자리에 있어요.
자리 예약함
읽던 문장은
이 자리에 있어요.
자리 예약 안 함
읽던 문장은
이 자리에 있어요.
자리 예약함
읽던 문장은
이 자리에 있어요.
이미지 높이를 미리 비워 두면 늦게 채워도 읽던 문장이 밀리지 않아요. 자리가 없으면 도착한 이미지가 문장을 밀어내요.
오른쪽은 아직 오지 않은 이미지의 자리를 미리 비워 뒀어요.
작은 지면 안의 위치 비교예요. 실제 CLS 수치를 측정하지 않으며 이 글의 본문과 버튼은 움직이지 않아요.
글꼴은 조금 달라요. 바뀌는 순간을 없앨 수 없다면 바뀔 때의 차이를 줄이는 쪽으로 가요. 대체 글꼴의 크기와 자간을 실제 글꼴에 가깝게 맞춰 두면 교체가 일어저도 줄바꿈이 유지돼요. 위에 끼워 넣는 요소는 아예 본문을 밀지 않는 위치에 두거나, 자리를 처음부터 확보해 두는 편이 나아요.
이 값이 순위에 들어온 시점
이 현상이 널리 이야기되기 시작한 데에는 계기가 있어요. Google은 2020년 5월 페이지 경험 신호를 검색 순위에 포함하겠다고 예고했고, 실제 적용은 2021년으로 이어졌어요. 그 신호 묶음 안에 CLS가 들어 있었어요.
측정 기준도 함께 공개됐어요. 좋은 상태로 보는 값은 0.1 이하예요. 이 숫자 자체보다 중요한 것은 밀림이 취향의 문제에서 측정되는 항목으로 옮겨 갔다는 사실이에요. 예전에는 거슬린다고 말할 수밖에 없던 것이 이제 수치로 비교돼요.
| 밀어내는 것 | 왜 미나 | 무엇을 예약하나 |
|---|---|---|
| 이미지 | 받아 보기 전에는 높이를 모른다 | 실제 가로세로를 미리 적어 둔다 |
| 광고 | 무엇이 올지 요청 전에는 모른다 | 최소 높이를 정해 빈 채로 둔다 |
| 웹 글꼴 | 교체되며 글자 크기가 달라진다 | 대체 글꼴의 크기를 맞춰 둔다 |
세 줄 모두 예약이라는 같은 해법으로 수렴해요. 정확한 내용을 몰라도 차지할 크기는 대개 미리 정할 수 있기 때문이에요.
저는 무엇을 예약했나
이 블로그의 도해는 벡터로 실려서 그림 자체가 비율을 들고 있고, 화면은 그 비율로 자리를 먼저 잡아요. 비율을 미리 알 수 없는 사진 쪽에는 실제 가로세로를 적게 하고 빌드에서 검사해요. 사람이 매번 기억하기에는 잊기 쉬운 항목이기 때문이에요. 이미지 하나를 크기 없이 넣는 순간 그 문단 아래가 전부 밀리는데, 쓰는 사람은 자기 화면에 이미 캐시된 이미지를 보고 있어 그 밀림을 겪지 않아요.
이 블로그의 광고는 현재 꺼져 있어요. 나중에 활성화한다면 실제 광고 크기와 빈 응답 상태를 포함해 공간을 정하고, 읽던 문단이 움직이지 않는지 다시 확인해야 해요. 아직 표시하지 않는 광고 때문에 지금 본문에 빈칸을 남길 필요는 없어요.
사용자가 느끼는 불쾌함의 상당 부분은 느려서가 아니라 예상과 달라서 생겨요. 빨리 보여 주는 일과 움직이지 않게 하는 일은 서로 다른 작업이었어요.