답변
먼저 원인부터 정확히 짚어야 합니다. font-display:swap은 웹폰트가 로딩되는 동안 폴백 폰트로 텍스트를 먼저 보여주다가 웹폰트가 준비되면 바로 교체하는데, 이때 폴백 폰트와 실제 웹폰트의 글자 너비·행간이 다르면 교체되는 순간 줄바꿈 위치와 그 아래 요소들이 밀리면서 CLS 점수가 나빠집니다. 크롬 개발자도구 Performance 패널에서 'Layout Shift' 이벤트를 필터링하면 정확히 폰트 교체 타이밍에 시프트가 찍히는지 바로 확인할 수 있습니다. 원인이 확인되면 CSS의 size-adjust, ascent-override, descent-override, line-gap-override 네 가지 속성을 폴백 폰트의 @font-face 선언에 적용하세요. 이 속성들은 폴백 폰트의 글자 크기·기준선을 실제 웹폰트 지표에 맞춰 강제로 맞춰주기 때문에, 교체되는 순간에도 텍스트 박스 크기가 거의 그대로 유지돼 시프트가 크게 줄어듭니다. 추가로 두 가지를 병행하면 좋습니다. 핵심 폰트 파일은 `<link rel="preload" as="font">`로 로딩 우선순위를 앞당겨 교체 타이밍 자체를 앞으로 당기고, 브랜드 서체 일치가 필수가 아닌 본문 영역은 font-display:optional로 바꿔서 폰트가 제때 준비되지 않으면 아예 교체하지 않고 폴백 폰트를 계속 쓰게 하면, 시프트 자체가 발생할 여지를 원천적으로 없앨 수 있습니다.