본문 바로가기
StyleSheet/CSS

[CSS] 타이포그래피(Typography)

반응형

인터넷에 존재하는 정보의 90% 이상은 '텍스트'로 이루어져 있습니다. 화려한 비디오와 이미지들이 시선을 끌 수는 있지만, 결국 사용자가 그 웹사이트에 머무르며 정보를 습득하고 구매 버튼을 누르게 만드는 최종적인 설득의 매개체는 잘 정돈된 글씨(Typography)입니다. 종이 출판물 시대부터 이어져 온 타이포그래피의 엄격한 규칙들은 웹으로 넘어오면서 모니터 픽셀과 브라우저 렌더링이라는 새로운 변수를 만나 더욱 고도화되었습니다. 주니어 프론트엔드 개발자들이 흔히 font-size나 대충 키우고 font-weight를 굵게 만드는 것으로 글꼴 디자인을 끝냈다고 착각하지만, 진짜 전문가들은 줄 간격(Line Height)의 미세한 황금비율을 계산하고, 외부 웹 폰트가 로딩될 때 발생하는 끔찍한 '깜빡임 현상'을 최적화하기 위해 고군분투합니다. 이번 05단계 포스팅에서는 단순히 글꼴을 바꾸는 기초를 넘어, 브라우저가 외부 폰트를 다운로드할 때 발생하는 렌더링 블로킹(FOIT, FOUT) 현상을 제어하는 고급 실무 기법과, 완벽한 가독성을 보장하는 줄 간격 및 자간 제어 공식에 대해 다뤄보겠습니다.

1. 폰트의 선택: 웹 폰트(Web Font) vs 시스템 폰트(System Font)

CSS에서 글꼴을 지정하는 가장 기본적인 속성은 font-family입니다. 우리는 쉼표(,)를 통해 여러 개의 폰트 이름을 나열할 수 있는데, 이는 "첫 번째 폰트가 사용자 컴퓨터에 없으면 두 번째 폰트를 쓰고, 그것도 없으면 세 번째 폰트를 써라!"라는 브라우저를 향한 Fallback(대체) 명령입니다.

디자이너의 로망, 웹 폰트 (Web Font)

구글 폰트(Google Fonts)나 눈누(Noonnu) 같은 서비스에서 제공하는 외부 폰트 파일(.woff, .woff2)을 서버에서 직접 다운로드하여 렌더링하는 방식입니다. 어떤 기기나 OS에서 접속하든 디자이너가 의도한 것과 정확히 100% 동일한 글꼴을 보여줄 수 있다는 엄청난 장점이 있습니다. 하지만 수 메가바이트(MB)에 달하는 폰트 파일을 네트워크를 통해 다운로드해야 하므로, 페이지 초기 로딩 속도 저하라는 치명적인 대가를 지불해야만 합니다.

극강의 퍼포먼스, 시스템 폰트 스택 (System Font Stack)

사용자의 컴퓨터(Windows, Mac)나 스마트폰(iOS, Android)에 이미 기본적으로 깔려 있는 폰트를 그대로 가져다 쓰는 방식입니다. 다운로드가 0초이므로 성능 최적화에 목숨을 거는 글로벌 빅테크 기업들(GitHub, WordPress, Bootstrap 등)이 기본으로 채택하는 방식입니다. 운영체제마다 글꼴 모양이 조금씩 달라진다는 단점이 있지만, "각 운영체제 사용자들이 가장 눈에 익숙하고 편안하게 느끼는 네이티브 글꼴을 제공한다"는 UX 철학 관점에서는 오히려 장점으로 작용합니다.

/* 💡 실무 최강의 시스템 폰트 스택 공식 */
/* 애플(Mac/iOS)은 San Francisco, 윈도우는 맑은 고딕, 안드로이드는 Roboto를 즉각적으로 렌더링합니다! */
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
}

2. 고급 실무: 끔찍한 폰트 깜빡임(FOIT / FOUT) 제어하기

무거운 외부 웹 폰트를 사용할 경우, 브라우저는 폰트 파일이 완전히 다운로드될 때까지 화면의 글씨를 어떻게 처리해야 할지 딜레마에 빠집니다. 브라우저 엔진마다 이 상황을 대처하는 방식이 달라 사용자는 끔찍한 시각적 버그를 경험하게 됩니다.

  • FOIT (Flash of Invisible Text): 애플 사파리(Safari) 브라우저의 악명 높은 방식입니다. 폰트가 다 다운로드될 때까지 최대 3초 동안 글씨를 아예 투명하게 숨겨버립니다(안 보여줌). 사용자는 3초 동안 텅 빈 하얀 화면만 보다가 갑자기 글씨가 팟! 하고 나타나는 공포를 겪습니다.
  • FOUT (Flash of Unstyled Text): 구글 크롬(Chrome) 등의 방식입니다. 폰트 다운로드를 기다리지 않고 일단 못생긴 기본 폰트(바탕체 등)로 글씨를 먼저 보여줍니다. 그리고 0.5초 뒤 예쁜 웹 폰트 로딩이 완료되면 폰트를 바꿔치기합니다. 이때 글꼴의 덩치가 달라지면서 레이아웃이 덜컥거리며 밀리는(CLS) 시각적 불쾌함이 발생합니다.
폰트 로딩 UX 최적화 - 무거운 웹 폰트 파일이 다운로드되는 빈 시간(Gap) 동안 텍스트를 아예 숨겨버리는 최악의 FOIT 현상을 막고, 일단 기본 시스템 폰트로 보여주다가 스무스하게 폰트를 갈아 끼우는 font-display: swap 의 작동 메커니즘

💡 구세주의 등장: font-display: swap

CSS 최신 명세는 @font-face 선언부 안에 font-display: swap;이라는 마법의 코드를 추가할 수 있게 해주었습니다. 이 코드를 넣으면 모든 브라우저가 사파리의 FOIT(투명 숨김) 방식을 강제로 버리고, 일단 사용자에게 텍스트 내용을 먼저 보여준 뒤(FOUT) 스무스하게 폰트를 교체하도록 렌더링 전략을 강제 통일시킵니다. "예쁜 글꼴을 기다리느라 글씨 내용 자체를 못 읽게 만드는 짓은 절대 하지 마라!"라는 사용자 중심의 철학이 담긴 실무 필수 속성입니다.

3. 가독성의 황금 비율: 단위 없는(Unitless) Line Height

글씨의 크기(font-size)만큼이나 가독성에 지대한 영향을 미치는 것이 바로 줄과 줄 사이의 여백, line-height(줄 간격)입니다. 텍스트가 여러 줄로 이어질 때 줄 간격이 너무 좁으면 글씨가 뭉개져 보이고, 너무 넓으면 시선이 흩어져 글이 읽히지 않습니다.

수많은 초보 개발자들이 line-height: 24px; 처럼 고정된 px 단위를 사용합니다. 이는 최악의 방법입니다. 나중에 반응형 환경에서 font-size가 30px로 커져버리면 어떻게 될까요? 줄 간격은 여전히 24px에 머물러 있어서 첫 번째 줄과 두 번째 줄의 글씨가 겹쳐버리는(Overlap) 참사가 발생합니다.

/* 💡 실무 정석: 단위(px, em)를 절대 쓰지 마라! */
p {
    font-size: 16px;
    line-height: 1.6; /* 폰트 크기의 1.6배를 줄 간격으로 자동으로 계산해라! */
}

숫자 뒤에 어떠한 단위도 붙이지 않는 Unitless(단위 없음) 방식을 사용하면, 브라우저는 현재 글꼴 크기(16px)에 1.6을 곱한 25.6px을 줄 간격으로 자동 설정합니다. 나중에 폰트가 30px로 커지면 줄 간격도 알아서 48px로 우아하게 넓어집니다. 보통 웹에서 가장 편안한 한국어(한글) 가독성을 보장하는 황금 비율은 1.5 ~ 1.6 사이로 알려져 있습니다.

정리하며

타이포그래피는 웹 디자인의 영혼입니다. 아무리 화려한 레이아웃을 짰더라도, 폰트 로딩 시 화면이 번쩍거리거나 줄 간격이 답답하게 짓눌려 있다면 사용자는 그 글을 읽지 않고 뒤로 가기를 누를 것입니다. font-display: swapline-height의 단위 없는 수학적 비율 공식을 통해 우리는 텍스트에 숨을 불어넣었습니다. 자, 지금까지 배운 박스 모델과 폰트 속성들은 단일 요소(나 하나)의 껍데기를 꾸미는 작업에 불과했습니다. 이제 본격적으로 여러 개의 네모 박스들을 화면 좌우상하로 퍼즐처럼 꿰어 맞추는 거대한 '레이아웃'의 험난한 여정을 떠날 시간입니다. 브라우저 흐름을 통제하는 레이아웃의 절대 코어! 다음 06단계 포스팅에서는 "CSS Display: Block과 Inline의 본질적 차이점과 숨겨진 비밀"에 대해 뼈 때리게 파헤쳐 보겠습니다!

반응형

'StyleSheet > CSS' 카테고리의 다른 글

[CSS] Positioning  (0) 2026.07.28
[CSS] Display  (0) 2026.07.28
[CSS] Color & Background  (0) 2026.07.28
[CSS] 단위(Units) 완벽 가이드  (0) 2026.07.28
[CSS] Box Model - 브라우저가 세상을 바라보는 네모난 시선  (0) 2026.07.28