본문 바로가기
웹개발 이모저모

[실무에서 복붙해 쓰는 에러 해결 및 트러블슈팅 가이드 #08] 텍스트가 번쩍? 폰트 깜빡임(FOUT/FOIT) 현상 없이 웹 폰트 완벽 로드하기

by 코드메이트 2026. 3. 25.

안녕하세요! 지난번 터미널을 새빨갛게 물들였던 의존성 충돌 지옥에서는 무사히 빠져나오셨나요? node_modules를 시원하게 날려버린 용기에 박수를 보냅니다! 자, 오늘은 프론트엔드 개발자라면 누구나 한 번쯤 겪어봤을, 그리고 디자이너분들의 뒷목을 잡게 만드는 '화면 깜빡임' 현상에 대해 이야기해 볼까 합니다.

 

열심히 코딩을 마치고 프로젝트를 배포했습니다. 두근거리는 마음으로 사이트에 접속했는데... 어라? 0.5초 정도 화면에 글자가 아예 안 보이다가 갑자기 '짠!' 하고 나타나거나, 못생긴 기본 굴림체로 보이던 글자가 갑자기 예쁜 웹 폰트로 '번쩍!' 하면서 바뀌는 현상. 다들 겪어보셨죠? 네, 맞습니다. 바로 프론트엔드 성능 최적화의 단골손님, 'FOIT(Flash of Invisible Text)' 'FOUT(Flash of Unstyled Text)' 현상입니다. 

 

오늘은 애써 적용한 예쁜 웹 폰트가 오히려 유저 경험을 깎아먹지 않도록, 이 지긋지긋한 폰트 깜빡임 현상을 완벽하게 제어하는 실전 팁을 모두 방출하겠습니다.

 

웹 페이지 로딩 시 글자가 안 보이다가 나타나는 FOIT 현상과 기본 폰트에서 웹 폰트로 바뀌며 레이아웃이 흔들리는 FOUT 현상을 비교한 예시 화면

 

1. FOIT와 FOUT, 이 깜빡임의 정체는 대체 뭘까?

우리가 CSS에 웹 폰트 URL을 적어두면, 브라우저는 HTML과 CSS를 읽다가 "어? 폰트 파일이 필요하네?" 하고 그제야 서버에 폰트를 다운로드하러 갑니다. 문제는 폰트 파일이 꽤 무겁다는 거죠. 다운로드가 완료될 때까지 브라우저는 화면에 글자를 어떻게 그려야 할지 고민에 빠집니다.

여기서 브라우저마다 성격이 나뉩니다. 사파리(Safari)나 크롬(Chrome) 같은 최신 브라우저들은 FOIT(Flash of Invisible Text) 방식을 택합니다. "완벽한 폰트가 다운로드될 때까지 일단 글자를 숨겨두자!" 라며 하얀 여백만 보여주다가 폰트가 오면 짠하고 보여주죠. 유저 입장에서는 사이트가 먹통이 된 줄 알고 답답해합니다.

반면, FOUT(Flash of Unstyled Text) 방식은 "일단 못생긴 기본 폰트로라도 내용을 보여주고, 다운로드 끝나면 그때 예쁜 폰트로 덮어씌우자!"라는 전략입니다. 글자는 바로 읽을 수 있지만, 폰트가 바뀌는 순간 글자 크기나 자간이 달라지면서 레이아웃이 '덜컹'하고 흔들리는 끔찍한 경험을 주게 됩니다.

 

2. 첫 번째 무기: CSS font-display: swap으로 통제하기

이 문제를 해결하는 가장 쉽고 강력한 무기는 바로 CSS의 font-display 속성입니다.

 

@font-face {
  font-family: 'MyAwesomeFont';
  src: url('my-awesome-font.woff2') format('woff2');
  font-display: swap; /* 이 한 줄이 핵심입니다! */
}

 

font-display: swap을 설정하면 브라우저에게 이렇게 명령하는 것과 같습니다. "폰트 다운로드 기다리지 말고 일단 당장 시스템 기본 폰트로 글자를 보여줘! (FOUT 방식 강제) 그리고 다운로드가 끝나면 그때 부드럽게 바꿔치기해!"

최소한 유저가 하얀 화면만 보며 기다리는 답답함(FOIT)을 없앨 수 있기 때문에, 실무에서 구글 웹 폰트를 포함한 대부분의 폰트 최적화에 가장 먼저 쓰이는 든든한 방어막입니다.

 

브라우저가 폰트를 다운로드하는 과정에서 font-display: swap 속성이 적용될 때 fallback 폰트를 먼저 보여주고 웹 폰트로 교체하는 렌더링 생명주기 다이어그램

 

하지만 swap만으로는 폰트가 바뀌면서 화면이 덜컹거리는 현상까지 막을 순 없습니다. 근본적인 해결책은 '폰트 다운로드 속도 자체를 미친 듯이 끌어올리는 것'입니다. 브라우저가 CSS를 다 읽기도 전에, HTML 최상단에서 "이 폰트는 무조건 쓰이니까 일단 다운로드부터 시작해!"라고 우선순위를 팍팍 밀어주는 것이죠.

 

<!-- HTML의 <head> 태그 안에 넣어주세요 -->
<link rel="preload" href="/fonts/my-awesome-font.woff2" as="font" type="font/woff2" crossorigin>

 

이렇게 preload를 걸어두면, 브라우저는 페이지를 열자마자 폰트 파일을 병렬로 다운로드하기 시작합니다. 폰트가 도착하는 타이밍이 렌더링보다 빨라지기 때문에 깜빡임 현상 자체가 마법처럼 사라지게 됩니다. 단, 너무 많은 폰트를 preload 하면 오히려 다른 중요한 자원(이미지, JS) 로딩을 방해하니 가장 핵심적인 제목 폰트 정도에만 사용하는 것이 좋습니다.

 

4. 세 번째 무기: WOFF2 포맷과 서브셋(Subset) 폰트로 다이어트 시키기

폰트 파일 크기 자체를 줄이는 것도 필수입니다. 과거에 쓰던 .ttf나 .otf 포맷은 너무 무겁습니다. 압축률이 가장 뛰어난 최신 포맷인 .woff2를 반드시 사용하세요.

또한, 한글 폰트는 자음과 모음의 조합 때문에 파일 크기가 엄청나게 큽니다. '뀱', '쀍' 같이 평생 한 번 쓸까 말까 한 글자들을 다 빼고, 실생활에서 자주 쓰는 2,350자만 추려낸 '서브셋(Subset) 폰트'를 사용하면 폰트 용량을 1/4 수준으로 확 줄일 수 있습니다. 가벼운 폰트 파일이야말로 최고의 렌더링 최적화입니다!

 

마무리하며

오늘은 디자이너와 프론트엔드 개발자 모두의 골칫거리인 웹 폰트 깜빡임(FOUT/FOIT) 현상의 원인과 실전 해결법에 대해 알아보았습니다. 예쁜 디자인도 중요하지만, 사용자가 사이트에 들어오자마자 텍스트를 편안하게 읽을 수 있게 해주는 것이 최고의 UX입니다. 오늘 알아본 font-display: swap과 preload, 그리고 WOFF2 서브셋 폰트 최적화 기법을 여러분의 프로젝트에 꼭 적용해 보셔서, 깜빡임 없이 매끄럽게 렌더링되는 완벽한 웹 사이트를 완성해 보시길 바랍니다!

 

[다음 포스팅 예고] 화면을 번쩍이게 만들던 폰트 깜빡임을 무사히 잡으셨나요? 다음 글에서는 프론트엔드 개발자들을 당황하게 만드는 또 다른 형태의 무시무시한 깜빡임, 바로 "다크 모드(Dark Mode) 구현 시 발생하는 깜빡임(FOUC) 문제 완벽 해결" 편으로 돌아오겠습니다. 하얀 화면이 1초 보였다가 갑자기 검은색으로 휙 바뀌면서 유저의 눈뽕(?)을 유발하는 다크 모드 버그를 겪어보셨다면, 다음 글도 절대 놓치지 마세요! 오늘도 버그 없는 평온한 하루 보내시길 응원합니다!

 

[실무에서 복붙해 쓰는 에러 해결 및 트러블슈팅 가이드 #09] 앗 내 눈! 다크 모드 화면 깜빡임(FOUC

안녕하세요! 지난번 글자를 춤추게 만들던 폰트 깜빡임(FOUT/FOIT) 문제는 잘 해결하셨나요? 쾌적해진 텍스트 렌더링에 유저들도 분명 만족하고 있을 겁니다. 자, 오늘은 프론트엔드 개발자들을 당

code-bricks.tistory.com