[실전 성능 08] 폰트라는 함정

지난 편에서 이미지를 가볍게 만드는 법을 다뤘다. 이번 편의 주인공은 폰트다. 폰트는 눈에 잘 안 띄는 성능 요소지만, 잘못 쓰면 텍스트를 늦게 띄우고 화면을 흔들며 데이터까지 잡아먹었다. 나는 데스크탑과 모바일을 다르게 접근해서 이 함정을 피했는데, 그 판단의 과정을 이번 편에서 풀어본다.


1. 웹폰트가 부리는 두 가지 심술

디자인을 위해 예쁜 웹폰트를 쓰고 싶은 마음은 누구나 있다. 그런데 웹폰트는 사용자 기기에 없어서 매번 다운로드해야 하는 자원이고, 그 다운로드가 끝나기 전까지 텍스트를 어떻게 보여줄지가 문제였다. 브라우저는 두 가지 선택지 사이에서 갈등했는데, 하나는 폰트가 올 때까지 글자를 숨기는 것이고 다른 하나는 기본 폰트로 먼저 보여주는 것이었다. 둘 다 나름의 심술이 있었다.


첫 번째 심술은 글자가 안 보이는 현상이었다. 폰트가 도착할 때까지 텍스트를 숨기면, 사용자는 폰트가 늦게 올 경우 한동안 빈 공간을 보게 됐다. 배경과 이미지는 다 떴는데 정작 읽을 글자가 없는 이상한 화면이었다. 느린 회선에서는 이 빈 텍스트 상태가 몇 초씩 이어지기도 해서, 사용자는 페이지가 덜 로딩됐다고 느꼈다.


두 번째 심술은 글자가 갑자기 바뀌는 현상이었다. 기본 폰트로 먼저 보여주면 텍스트는 빨리 뜨지만, 나중에 웹폰트가 도착하면 그 폰트로 확 교체됐다. 두 폰트의 글자 폭과 높이가 다르면 이 교체 순간에 텍스트 길이가 달라지고 줄바꿈이 바뀌면서 레이아웃이 출렁였다. 앞서 시각 안정성 편에서 다룬 그 흔들림의 숨은 범인이 바로 이 폰트 교체였다.


결국 웹폰트는 텍스트를 늦게 띄우거나 화면을 흔들거나 둘 중 하나의 대가를 치르게 했다. 나는 이 딜레마를 마주하고, 두 심술 사이에서 절충점을 찾기보다 더 근본적인 질문을 던졌다. 과연 이 웹폰트가 그만한 대가를 치를 가치가 있는가 하는 것이었다. 이 질문이 내 폰트 전략의 출발점이 됐다. 디자인 욕심에 이끌려 웹폰트를 당연하게 여기던 태도를 내려놓고, 폰트도 이미지나 스크립트처럼 성능 예산을 소비하는 자원으로 바라보기 시작하니 판단이 훨씬 냉정해졌다.


2. 시스템 폰트라는 우회로

가장 확실한 해법은 웹폰트를 안 쓰는 것이었다. 사용자 기기에 이미 깔려 있는 시스템 폰트를 쓰면 다운로드가 아예 없으니, 텍스트가 즉시 뜨고 교체로 인한 흔들림도 없었다. 두 가지 심술을 원천 봉쇄하는 방법이었다. 문제를 정교하게 관리하는 대신 문제 자체를 없애는 이 접근이 나에게는 매력적이었다.


시스템 폰트의 장점은 성능만이 아니었다. 각 운영체제가 자기 화면에 가장 잘 보이도록 다듬어둔 폰트라, 그 환경에서 가장 자연스럽고 읽기 편했다. 사용자는 평소 쓰던 익숙한 글꼴로 콘텐츠를 봤고, 낯선 웹폰트보다 오히려 편안하게 느끼기도 했다. 성능을 위해 디자인을 희생하는 게 아니라, 각 환경에 맞는 최적을 얻는 셈이었다.


다만 시스템 폰트는 기기마다 실제 글꼴이 달라진다는 단점이 있었다. 어떤 기기에서는 이 글꼴, 다른 기기에서는 저 글꼴로 보이니 화면이 완전히 통일되지 않았다. 브랜드의 일관된 글꼴을 중요시하는 곳에서는 이게 걸림돌이 될 수 있었다. 나는 커뮤니티 사이트에서는 글꼴의 완벽한 통일보다 빠르고 편한 읽기가 더 중요하다고 판단했다.


그래서 나는 시스템 폰트를 우선순위 목록으로 지정했다. 각 운영체제의 대표적인 읽기 좋은 폰트를 순서대로 나열해두고, 기기가 자기에게 있는 첫 번째 것을 쓰도록 했다. 이렇게 하니 어느 환경에서든 그 환경에 맞는 좋은 폰트가 다운로드 없이 즉시 적용됐다. 목록 하나로 모든 기기를 커버한 것이다. 특정 폰트 하나를 모든 기기에 강요하는 대신 각 기기가 자기에게 최적화된 폰트를 고르게 두는 이 방식이, 결과적으로 성능과 가독성을 모두 챙기는 실용적인 타협이었다.


3. 데스크탑과 모바일을 나누다

그런데 모든 곳에서 시스템 폰트만 고집할 수는 없었다. 특히 모바일에서는 기본 시스템 폰트의 한글 표현이 아쉬운 경우가 있어서, 가벼운 웹폰트로 읽기 경험을 높이고 싶었다. 그래서 나는 데스크탑과 모바일을 나눠서 접근하는 하이브리드 전략을 택했다. 환경마다 최선이 다르니 전략도 달리한 것이다.


데스크탑에서는 시스템 폰트를 그대로 썼다. 큰 화면에서 오래 콘텐츠를 읽는 환경이라 다운로드 지연이나 흔들림 없이 즉시 안정적으로 뜨는 것이 중요했고, 시스템 폰트가 그 요구에 딱 맞았다. 데스크탑 사용자는 대개 회선도 안정적이라 굳이 웹폰트의 위험을 감수할 이유가 없었다. 안전한 선택을 유지했다.


모바일에서는 가벼운 웹폰트를 쓰되 심술을 최소화하는 장치를 걸었다. 폰트가 도착하기 전에도 기본 폰트로 글자를 즉시 보여주게 해서, 텍스트가 안 보이는 첫 번째 심술을 막았다. 사용자는 일단 기본 폰트로 읽기 시작하고, 웹폰트는 준비되면 자연스럽게 적용됐다. 빈 화면을 보여주느니 먼저 읽히게 하는 것이 나은 선택이었다.


이 하이브리드 접근의 핵심은 획일적인 정답을 거부한 데 있었다. 데스크탑에 좋은 것과 모바일에 좋은 것이 다른데 하나로 밀어붙이면 어느 한쪽이 손해였다. 나는 환경별로 측정하고 각각에 맞는 선택을 했다. 성능 최적화가 늘 하나의 정답이 아니라 상황에 맞는 판단이라는 걸 폰트에서 다시 확인했다.


4. 교체 흔들림 다스리기

모바일에서 웹폰트를 쓰기로 한 이상, 두 번째 심술인 교체 흔들림도 다뤄야 했다. 기본 폰트로 보여주다 웹폰트로 바뀌는 순간의 출렁임을 줄이는 것이 과제였다. 완전히 없애기는 어려워도, 두 폰트를 최대한 비슷하게 맞추면 교체 순간의 변화를 눈에 안 띄게 줄일 수 있었다. 나는 이 미세 조정에 신경 썼다.


핵심은 기본 폰트와 웹폰트의 크기와 간격을 맞추는 것이었다. 폴백으로 쓰는 기본 폰트의 글자 크기와 줄 간격을 웹폰트에 가깝게 조정해두면, 교체가 일어나도 텍스트가 차지하는 공간이 거의 변하지 않았다. 공간이 안 변하면 줄바꿈도 안 바뀌고 레이아웃도 안 밀렸다. 사용자는 폰트가 바뀐 것조차 잘 몰랐다.


폰트 파일 자체를 가볍게 만드는 것도 흔들림을 줄이는 길이었다. 파일이 작으면 그만큼 빨리 도착해서 교체가 일찍 일어났고, 사용자가 이미 깊이 읽기 전에 조용히 끝났다. 나는 필요한 글자만 담은 가벼운 폰트를 쓰고, 효율적인 폰트 형식으로 크기를 줄였다. 안 쓰는 스타일과 굵기를 덜어내는 것만으로도 파일이 눈에 띄게 작아졌다.


또한 자주 방문하는 사용자를 위해 폰트를 브라우저에 오래 캐시했다. 한 번 받은 폰트는 다시 다운로드하지 않으니, 재방문 시에는 웹폰트가 처음부터 적용된 상태로 떴다. 첫 방문의 교체 흔들림은 감수하더라도, 이후 방문은 완전히 매끄러웠다. 폰트는 자주 안 바뀌는 자원이라 이 캐시 전략이 특히 잘 들어맞았다.


5. 폰트에서 배운 절제

폰트를 다루며 얻은 교훈은 절제였다. 예쁜 폰트, 여러 굵기, 다양한 스타일을 다 쓰고 싶지만 그만큼 다운로드가 늘고 성능이 나빠졌다. 나는 정말 필요한 최소한의 폰트만 쓰기로 했다. 굵기 하나를 추가할 때마다 그것이 치를 성능 비용을 따졌고, 대부분은 없어도 되는 욕심이었다.


절제는 성능뿐 아니라 디자인에도 오히려 도움이 됐다. 폰트 종류를 줄이니 화면이 더 정돈되고 일관돼 보였다. 이것저것 섞인 화면보다 몇 가지로 통일된 화면이 읽기도 편하고 깔끔했다. 성능을 위한 절제가 디자인의 완성도로 이어지는 반가운 경험이었다. 덜어냄이 손해가 아니라 이득이었다.


폰트는 또한 성능이 눈에 안 보이는 곳에도 숨어 있다는 걸 알려줬다. 이미지처럼 대놓고 무겁지 않아 무심코 지나치기 쉬웠지만, 재보면 분명히 로딩과 안정성에 영향을 줬다. 나는 이 경험으로 재기 전에는 무엇이 병목인지 함부로 단정하지 않게 됐다. 폰트 같은 조용한 요소가 의외의 범인일 때가 많았다. 눈에 띄게 무거운 것만 쫓다 보면 이렇게 조용히 성능을 갉아먹는 요소를 놓치기 쉬웠고, 그래서 나는 짐작 대신 측정으로 사이트 전체를 골고루 훑는 습관을 들였다.


이렇게 이미지와 폰트라는 대표적인 콘텐츠 자원을 다뤘다. 다음 편부터는 조금 다른 층위로 내려간다. 콘텐츠가 아니라 그 콘텐츠를 그리는 과정 자체를 막는 자원, 즉 렌더링을 블로킹하는 스타일과 스크립트 이야기다. 화면 그리기를 멈춰 세우는 이 자원들을 어떻게 걷어냈는지 다음 편에서 풀어보겠다.