성능 지표를 이야기할 때 LCP는 '느린 로딩', INP는 '무거운 자바스크립트'로 원인이 명확하게 지목된다. 그런데 CLS(Cumulative Layout Shift)는 다르다. 이미지에 width와 height를 달아도 점수가 거의 안 움직인다. 팀이 Lighthouse를 돌리고 '살짝 나아졌네' 하고 넘어가는 사이, 실제 사용자 데이터(CrUX)는 여전히 빨간불이다. dev.to에 기고된 137Foundry의 분석은 그 이유를 정확히 짚는다—CLS는 단일 원인이 아니라 누적이기 때문이다.
CLS가 까다로운 진짜 이유
CLS 점수는 페이지 세션 전반의 예상치 못한 레이아웃 시프트를 모두 합산한다. 브라우저는 이를 '세션 윈도우'로 묶는데, 5초 안에서 1초 이하 간격으로 발생한 시프트들이 하나의 윈도우로 집계되고, 가장 나쁜 윈도우 점수가 최종 CLS가 된다. 시각적으로는 사소해 보이는 작은 이동도, 뷰포트의 넓은 영역에 걸쳐 연속으로 발생하면 치명적인 점수가 된다.
원인의 순서도 중요하다. 이미지 다음으로 팀이 놓치는 소스는 웹폰트, 서드파티 광고·위젯, 레이아웃 속성을 건드리는 CSS 애니메이션, 그리고 초기 페인트 이후 위쪽에 삽입되는 동적 콘텐츠다. font-display: swap은 폴백 폰트와 웹폰트의 x-height·자간 차이로 텍스트 블록을 통째로 밀어낸다. 쿠키 동의 배너가 헤더 위에 뚝 떨어지는 것도, 높이 선언 없이 광고가 채워지는 것도 같은 맥락이다. 137Foundry의 Dennis Traina는 이를 단적으로 표현한다. "이미지를 고치고 Lighthouse를 다시 돌려서 수치가 조금 나아지면 끝났다고 생각하는데, 필드 데이터는 여전히 나쁘다. 남은 점수는 거의 언제나 폰트 스왑, 서드파티 인젝션, 아무도 레이아웃에 영향을 준다고 생각하지 못한 애니메이션에서 온다."
도구가 잡지 못하는 것을 잡으려면
Lighthouse는 클린 브라우저 환경에서 단일 로드를 시뮬레이션한다. 브라우저 익스텐션이 주입하는 콘텐츠, 방문자 위치나 프로파일에 따라 달라지는 광고 콘텐츠, 운영체제별로 다른 시스템 폰트 렌더링—이 모든 변수는 랩 데이터에서 재현되지 않는다. Google Search Console의 필드 데이터(75th percentile)와 랩 점수 사이에 괴리가 있다면, 그 차이는 거의 확실히 방문자마다 다르게 동작하는 소스에서 온다.
디버깅 출발점은 Chrome DevTools 퍼포먼스 패널의 'Experience' 행이다. 시프트 이벤트를 클릭하면 어떤 요소가 얼마나 움직였는지, CLS 기여도가 얼마인지 바로 확인된다. 초기 로드 후 발생하는 시프트는 더 긴 세션을 녹화해야 잡힌다. 느린 네트워크 프로파일과 실제 기기를 함께 써야 로드 조건에서만 나타나는 시프트가 수면 위로 올라온다.
접근성이라는 또 다른 '느끼는 품질'
CLS가 시각적 안정성의 문제라면, 접근성은 정보가 모든 감각 경로로 도달하는지의 문제다. dev.to의 Shayna Productions 기고는 WCAG를 '감각 모달리티와 주변 기기'의 관점으로 재해석한다. 우리가 디지털 콘텐츠를 소비하는 감각은 시각·청각·촉각 세 가지이고, 각각은 스크린·스피커·게임 컨트롤러(또는 점자 프린터)라는 주변 기기와 연결된다. 접근성을 '장애인을 위한 특수 기능'이 아니라 '어떤 주변 기기로도 콘텐츠에 접근할 수 있게 코드를 짜는 것'으로 프레이밍하면, 추상적인 WCAG 지침이 훨씬 구체적인 개발 체크리스트가 된다.
WCAG의 POUR 원칙 중 Perceivable(인식 가능)은 스크린과 스크린리더, 두 개의 주변 기기를 동시에 타깃해야 한다는 뜻이다. 시맨틱 HTML과 ARIA 속성이 이 역할을 담당한다. Operable(조작 가능)은 포인터(마우스·트랙패드), 키보드, 그리고 음성 세 가지 입력 경로를 커버해야 한다는 의미다. 화면에 보이는 레이블과 프로그래밍 방식으로 연결된 이름이 일치해야 음성 제어가 제대로 작동한다(WCAG 2.5.3). 프론트엔드 개발자가 실질적으로 책임지는 접근성의 범위는 여기—코드의 구조와 시맨틱—에 집중된다.
두 문제가 가리키는 하나의 교훈
CLS와 접근성은 표면적으로는 다른 도메인처럼 보인다. 하지만 둘은 같은 지점을 찌른다. 사용자가 직접 느끼는 품질은 기능 완성도와 별개로 존재한다는 것. 버튼이 눌리고 데이터가 불러와지는데도 레이아웃이 계속 밀리는 페이지는 '고장난 느낌'을 준다. 시각적으로는 완성도 높은 UI인데 키보드로 한 번도 테스트되지 않은 컴포넌트는 특정 사용자에게 사실상 존재하지 않는 기능이다.
애자일 스프린트의 속도압 속에서 둘 다 backlog 깊숙이 밀려나는 경향이 있다. 접근성 기고의 저자가 직접 목격한 사례—동료 개발자가 검토에서 스크린리더 이슈를 지적했을 때 "나는 시각장애인에 관심 없다"고 일축한 디자이너—는 극단적이지만, 이 태도의 희석된 버전은 훨씬 흔하다. '나중에 접근성 계획을 세우겠다'는 말이 그것이다.
지금 팀에서 시작할 수 있는 것
CLS 관점에서는 랩 점수와 필드 데이터를 함께 모니터링하는 것이 첫 걸음이다. 둘 사이에 괴리가 크다면 웹폰트 스왑, 광고 슬롯 최소 높이 선언, transform 기반 애니메이션 전환의 순서로 점검한다. 모든 페이지 템플릿을 개별적으로 감사해야 하며, 한 템플릿의 수정이 다른 템플릿에 자동으로 적용되지 않는다.
접근성 관점에서는 WCAG를 감각 모달리티 체크리스트로 재번역하는 것이 진입 장벽을 낮춘다. '이 컴포넌트는 스크린리더로 읽히는가? 키보드만으로 조작되는가? 음성 입력의 레이블이 화면 텍스트와 일치하는가?' 세 질문이 스프린트 Definition of Done에 들어가는 순간, 접근성은 백로그 항목이 아니라 완료 조건이 된다.
전망: '느끼는 품질'이 경쟁 우위가 되는 시대
AI 코드 생성 도구가 컴포넌트 조립 속도를 극적으로 높이는 지금, 아이러니하게도 CLS와 접근성의 중요성은 더 커진다. 빠르게 생성된 코드일수록 시맨틱 구조와 레이아웃 안정성이 검증되지 않은 채 배포될 위험이 높다. Figma-to-code 자동화가 확산될수록 '화면에 보이는 것'은 쉽게 완성되지만, '모든 사용자에게 닿는 것'의 책임은 여전히 사람이 설계해야 한다.
CLS 점수 하나, ARIA 속성 하나가 사용자 이탈률과 법적 리스크를 동시에 건드린다. 사용자가 느끼는 품질을 구성하는 요소 중 많은 부분이 눈에 띄지 않는 곳에 있다. 바로 그래서, 그것을 챙기는 팀이 결국 더 오래 신뢰받는다.