"Ensure text remains visible during webfont load" 수정
웹폰트는 사용하기 전에 다운로드해야 하므로, 로드하는 동안 텍스트가 일시적으로 숨겨집니다.

"Ensure text remains visible during webfont load" 요약
웹폰트는 웹 브라우저에서 기본적으로 사용할 수 없는 폰트입니다. 따라서 웹폰트는 사용하기 전에 먼저 다운로드해야 합니다. 웹폰트를 다운로드하는 동안 웹페이지의 텍스트는 웹폰트가 로드될 때까지 일시적으로 숨겨집니다.
결과적으로 방문자가 사용할 수 있을 만큼 페이지 로딩이 "완료"되지 않았기 때문에 페이지가 훨씬 느리게 로드되는 것처럼 보일 것입니다. 이는 user experience 저하로 이어질 수 있습니다. 페이지에서 Lighthouse 분석을 실행하면 페이지 로드 성능에 대한 경고인 "Ensure text remains visible during webfont load"가 나타납니다.
font-display 값을 변경하거나 폰트 로더를 사용하여 이 문제를 해결하세요. 이 기사에서는 이것이 어떻게 작동하는지 설명합니다.
마지막 검토: Arjen Karel, 2026년 2월

웹폰트를 로드하는 동안 텍스트가 계속 표시되도록 하세요
웹폰트가 존재하기 전에는 웹 디자이너들이 사전 설치된 소수의 폰트만 사용해야 했습니다. 웹폰트는 웹사이트에서 어떤 폰트든 사용할 수 있는 자유를 제공합니다.
물론 듣기에는 좋지만 웹폰트에도 단점이 있습니다. 웹폰트는 여러 가지 측면에서 페이지 로딩 속도를 늦춥니다.
웹폰트는 일반적으로 컴퓨터에 기본적으로 설치되어 있지 않은 대용량 파일입니다. 따라서 웹폰트는 사용하기 전에 다운로드해야 합니다. 웹폰트를 다운로드하는 동안 웹페이지의 텍스트는 웹폰트가 완전히 로드될 때까지 일시적으로 숨겨집니다. 이것은 불쾌한 user experience를 만듭니다. 아무도 빈 화면을 너무 오래 쳐다보고 싶어하지 않습니다.
웹폰트가 로드되고 렌더링되자마자 브라우저는 새로운 웹폰트가 적용된 최종 텍스트로 "보이지 않는 텍스트"를 대체합니다. 이 순간을 FOIT(Flash of Invisible Text)라고 합니다. 이 FOIT가 "Ensure text remains visible during webfont load" 오류 메시지를 나타나게 하는 원인입니다.

Flash of Invisible Text를 방지하기 위한 조치를 취하지 않고 페이지에 웹폰트를 로드하고 있나요? Lighthouse에서 PageSpeed Insights를 분석하면 "Ensure text remains visible during webfont load"라는 메시지가 나타납니다. 이는 웹폰트가 로드되기 전에 텍스트를 표시하여 절약할 수 있는 시간을 알려줍니다. 단일 폰트 1개의 경우 쉽게 100ms를 절약할 수 있습니다.
보이지 않는 텍스트가 페이지 속도에 나쁜 이유는 무엇입니까?
보이지 않는 텍스트는 최종적으로 측정되는 페이지 로딩 시간을 실제로 늦추지 않습니다. 그렇다면 Lighthouse는 왜 이것이 그렇게 문제라고 생각할까요?
Google은 웹 페이지가 최상의 user experience를 제공하는 것이 중요하다고 생각합니다. user experience는 페이지의 콘텐츠를 가능한 한 빨리 보여줌으로써 향상될 수 있습니다. 브라우저는 숨기고 있는 텍스트를 그릴 수 없기 때문에 보이지 않는 텍스트는 First Contentful Paint (FCP)에 직접적인 영향을 미칩니다. 텍스트가 Largest Contentful Paint (LCP) 요소인 경우, FOIT는 해당 지표 또한 지연시킵니다. 아래에서 저희 홈페이지의 두 가지 필름 스트립 버전을 비교해 보세요:
Flash of Invisible Text
display:swap을 사용하여 보이지 않는 텍스트 플래시 없음
보시다시피, 두 페이지의 로딩이 정확히 동시에 완료되었습니다. 그럼에도 불구하고 최신 버전의 웹사이트가 방문자에게 훨씬 좋아 보입니다. 방문자는 즉시 읽기 시작할 수 있습니다.
그렇기 때문에 최종 폰트가 아닌 "fallback" 폰트로라도 어쨌든 텍스트를 표시하는 것이 현명합니다. 이렇게 하면 방문자는 페이지가 정말 매우 빠르게 로드된다고 생각합니다.
간단한 상기: FOIT와 FOUT
더 진행하기 전에 다음 개념인 FOIT와 FOUT를 구분하는 것이 도움이 됩니다. FOIT는 Flash of Invisible Text를 의미하며 로딩 중 웹폰트가 보이지 않을 때 발생합니다. fallback 폰트를 포함하여 이를 완화할 수 있습니다. fallback 폰트가 웹폰트로 교체될 때 이를 FOUT(Flash of Unstyled Text)라고 합니다.
로딩 중 웹폰트가 표시되도록 만들기
로딩 중 웹폰트가 보이게 하는 방법에는 두 가지가 있습니다. 첫 번째는 CSS font-display 값을 통한 방법이고, 두 번째는 클래스를 통한 fallback 폰트를 사용하는 것입니다. 두 방법 모두 장단점이 있으며, 이에 대해서는 아래에서 논의하겠습니다.
방법 1: Font-display:swap
Font-display는 모든 최신 브라우저에서 사용할 수 있는 CSS 설명자(descriptor)입니다. font-display 설명자는 폰트가 다운로드되었는지 여부와 시기에 따라 폰트가 표시되는 방식을 결정합니다. Font-display는 @font-face 규칙에서 사용됩니다.
알아야 할 네 가지 font-display 값이 있습니다:
- swap: fallback 폰트를 즉시 표시한 다음, 로드되면 웹폰트로 교체합니다. 교체(swap) 기간은 무한하므로, 웹폰트는 결국 항상 fallback을 대체합니다. 브랜드 폰트 및 제목에 가장 적합합니다.
- optional: fallback 폰트를 즉시 표시합니다. 브라우저는 연결 속도에 따라 교체 여부를 결정합니다. 교체하지 않는다는 것은 layout shift가 없음을 의미합니다. 성능이 우선인 본문 텍스트에 가장 적합합니다.
- fallback: fallback 폰트를 즉시 표시한 다음 웹폰트가 로드될 수 있도록 짧은 기간(약 3초)을 줍니다. 기간을 놓치면 fallback이 유지됩니다. swap과 optional 사이의 절충안입니다.
- block: 폰트가 로드되는 동안 최대 3초 동안 텍스트를 숨깁니다. 이것이 FOIT의 원인입니다. 특정 이유(아이콘 폰트 등)가 없는 한 사용하지 마세요.
2025 Web Almanac에 따르면 사이트의 50%만이 font-display: swap을 사용하며 25%는 여전히 block을 사용합니다. 이는 웹의 1/4이 폰트 로딩 중에 여전히 보이지 않는 텍스트를 표시하고 있음을 의미합니다.
FOIT를 피하고 텍스트가 가능한 한 빨리 화면에 나타나도록 하려면 swap 값을 사용하세요. @font-face 규칙에서 font-display: swap 값을 설정하면, 웹폰트가 로드될 때까지 페이지가 로드되는 동안 시스템의 기본 폰트가 사용됩니다. 이는 방문자가 페이지의 텍스트를 즉시 읽을 수 있도록 도와줍니다.
Google Fonts
Google Fonts를 사용할 때는 스타일시트나 삽입 코드에 간단히 "&display=swap"을 추가하여 font-display: swap 메서드를 사용할 수 있습니다.
<!-- 외부 스타일시트를 통한 방법 --> <link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
<!-- import 방식을 통한 방법 (느림, 권장하지 않음) -->
<style>
@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');
</style>
@import 방식은 렌더링 차단(render-blocking)이며 브라우저가 스타일시트를 순차적으로 다운로드하도록 강제합니다. <link> 방식은 브라우저가 파싱 프로세스 초기에 폰트 스타일시트를 발견할 수 있으므로 더 빠릅니다.
하지만 우리는 이 두 가지 접근 방식을 모두 선호하지 않습니다. 웹폰트를 직접 호스팅하는 것이 거의 항상 훨씬 더 빠릅니다. 이를 통해 폰트의 "사전 로드(preloading)" 과정을 더 잘 제어할 수 있습니다. 이미 존재하는 HTTP/2 연결을 사용할 수 있으며 추가 스타일시트를 다운로드할 필요가 없습니다.
로컬 폰트
@font-face {
font-family: "Open Sans";
font-weight: 400;
font-style: normal;
src: url("OpenSans400.woff2") format("woff2");
font-display: swap
}
WOFF2만 있으면 됩니다. 모든 최신 브라우저에서 지원되며 최고의 압축을 제공합니다. 2025 Web Almanac에 따르면 이제 사이트의 72%가 폰트를 자체 호스팅하며 WOFF2가 모든 웹 폰트 요청의 65%를 차지합니다. 더 이상 WOFF나 TTF를 fallback 형식으로 포함할 이유가 없습니다.
폰트 교체 시 레이아웃 전환(layout shift) 방지
font-display: swap에는 함정이 있습니다. 브라우저가 fallback 폰트에서 웹폰트로 교체할 때 텍스트 크기가 변경되는 경우가 많습니다. 폰트마다 문자 너비, 어센트(ascent) 높이 및 줄 간격이 다릅니다. 이러한 크기 변경은 Core Web Vitals 중 하나인 Cumulative Layout Shift (CLS)를 유발합니다.
해결책은 size-adjust CSS 설명자입니다. fallback 폰트의 크기를 웹폰트의 치수와 일치하도록 조정하므로 교체 시 눈에 띄는 전환이 거의 발생하지 않습니다. 브라우저 지원은 Safari 17+를 포함하여 93% 이상입니다.
/* 일치하는 fallback 폰트 정의 */
@font-face {
font-family: "Open Sans Fallback";
src: local("Arial");
size-adjust: 105%;
ascent-override: 110%;
descent-override: 25%;
line-gap-override: 0%;
}
/* 폰트 스택에 둘 다 사용 */
body {
font-family: "Open Sans", "Open Sans Fallback", sans-serif;
}
ascent-override, descent-override 및 line-gap-override 설명자는 수직 메트릭에 대해 훨씬 더 정밀한 제어를 제공합니다. 이들은 Chrome, Firefox 및 Edge에서 작동하지만 아직 Safari에서는 작동하지 않으므로 점진적 향상(progressive enhancement)으로 취급하세요. size-adjust 속성만으로도 눈에 띄는 차이를 만들 수 있습니다.
CoreDash가 모니터링하는 사이트 전체에서 font-display: swap을 폰트 메트릭 재정의(override)와 결합하는 페이지는 swap만 사용하는 페이지보다 폰트 관련 CLS가 75% 낮습니다.
방법 2: 클래스가 있는 폰트
로딩 중에 폰트를 표시되도록 하는 두 번째 방법은 클래스를 사용하여 작업하는 것입니다. 이러한 클래스는 일반적으로(항상 그런 것은 아님) <body> 또는 <html> 요소에 추가됩니다.
이 방법의 장점은 fallback 폰트와 Flash of Unstyled Text의 타이밍을 더 잘 제어할 수 있다는 것입니다.
이 방법은 다음과 같이 작동합니다. 스타일시트에 페이지가 처음에 한 폰트(fallback 폰트)로 렌더링되어야 함을 나타냅니다. 그런 다음 JavaScript FontFace API를 통하거나 사전 로드(preloading)를 통해 웹폰트를 로드합니다. 이 폰트가 로드된 후 페이지에 클래스를 추가합니다. 이 클래스는 웹폰트가 활성화되도록 합니다.
왜 그렇게 해야 하는지 묻고 싶을 것입니다. fallback 폰트에 대한 더 많은 제어권을 얻기 위해 이렇게 합니다. 더 넓은 줄 간격이나 다른 크기로 fallback 폰트를 표시하여 웹폰트와 더 잘 일치하게 할 수 있습니다. 이것은 layout shifts를 방지합니다.
여러 웹폰트를 사용할 때 FontFace API 방법을 사용하여 모든 폰트를 한 번에 전환할 수 있습니다. 이렇게 하면 브라우저 다시 그리기(repaints)를 많이 절약할 수 있습니다. 개인적으로 이 방법을 좋아하지 않습니다. 이렇게 하면 마지막 폰트가 로드된 후 FOUT가 발생하기 때문입니다. 따라서 필요 이상으로 항상 늦어집니다.
FontFace API를 통한 클래스가 있는 폰트:
<style>
// .9rem 폰트 크기를 가진 fallback 폰트
html{
font-family: sans-serif;
font-size:.9rem;
}
// 1rem 폰트 크기를 가진 웹폰트
html.fl{
font-family: 'webfont';
font-size:1rem;
}
</style>
<script>
var font = new FontFace("webfont", "url(/font.woff2)", {
style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});
// 렌더링 트리를 기다리지 말고 즉시 가져오기를 시작하세요!
font.load().then(function() {
document.fonts.add(font);
document.documentElement.classList.add("fl")
});
</script>
사전 로드(preload) 링크를 통해
두 번째 방법은 사전 로드(preload) 링크를 이용하는 것입니다. 아래 설명된 대로 폰트를 사전 로드합니다. 이 작업이 완료되면 <html> 요소의 클래스를 전환합니다.
<link
rel="preload"
href="/webfont.woff2"
as="font"
type="font/woff2" crossorigin
onload="document.documentElement.classList.add('fl')">
<style>
// .9rem 폰트 크기를 가진 fallback 폰트
html{
font-family: sans-serif;
font-size:.9rem;
}
// 1rem 폰트 크기를 가진 웹폰트
html.fl{
font-family: 'webfont';
font-size:1rem;
}
// @font-face, html 태그에 .fl 클래스가 추가된 후에만 활성화됨
@font-face{
font-family:'Open Sans';
font-style:normal;
font-weight:400;
font-display:swap;
src: url(/webfont.woff2) format("woff2");
unicode-range:U+000-00FF;
}
</style>
추가 팁 및 요령
- 보이는 폰트는 항상 사전 로드(preload)하세요. 폰트는 페이지에서 실제로 사용될 때까지 기본적으로 다운로드되지 않습니다. 웹폰트가 필요하다면 더 빨리 사용할 수 있도록 사전 로드하세요.
- FOIT 및 FOUT를 완전히 방지하고 싶으신가요? 사전 로드(preloading)와 함께 font-display: optional을 사용하세요.
- 웹폰트를 직접 호스팅하는 것이 항상 Google Fonts 또는 다른 외부 CDN을 통한 웹폰트보다 빠릅니다.
폰트 로딩 전략이 실제로 실제 user experience를 향상시키는지 확인하고 싶으신가요? 변경 전후의 FCP와 CLS를 추적하려면 Real User Monitoring을 사용하세요.

