웹 폰트란

웹 서버에 원하는 폰트를 요청해서 사용자에게 보여주는 방식입니다.

이러한 기술을 사용하게 된 이유는 사용자가 느끼는 UI/UX의 기준은 날이 갈수록 높아지고 그에 따라 더 높은 수준의 사용자 경험(UX)를 제공하기 위해선 다양한 폰트를 제공하는 것은 선택이 아닌 필수가 되었습니다. 하지만 사실상 모든 사용자의 로컬 환경에 개발자가 사용할 폰트가 설치되어 있는 것은 불가능합니다.

그래서 사용자의 로컬 환경에 구애받지 않고 최적의 사용자 경험(UX)를 제공하기 위해서 사용하게 된 기술입니다.

사용 방법

@font-face

@font-face {
  font-family: NanumSquare;
  src: url(NanumSquareR.eot) format('embedded-opentype'),
       url(NanumSquareR.woff) format('woff'),
       url(NanumSquareR.ttf) format('truetype'); 
  font-weight : 400;
}

body { font-family : NanumSquare , sans-serif}

이름은 NanumSquare이고 src경로는 NanumSquareR.eot font-weight는 400인 폰트 객체를 만드는 것처럼 사용할 수 있습니다.

format

format을 알기 전에 font-face가 어떻게 동작하는지 알아야 할 것 같습니다. font-facesrc에 존재하는 폰트들을 순서대로 로드하면서 현재 브라우저에서 사용 가능하거나, 정상적으로 로드 된 폰트를 적용합니다. 순서대로 라는 말이 중요한데, 그렇다면 가장 마지막에 존재하는 폰트 하나만 브라우저에서 지원할 경우 아래와 같이 중간에 있는 불필요한 폰트들을 로드해야합니다.

image

이런 점을 해결하기 위해 마치 CSS의 vender prefix처럼 미리 브라우저에게 알려주는 역할을 하는 것이 format입니다.

예들 들어, 크롬에서는 .eot 파일 형식을 지원해주지 않습니다. 그렇기 때문에 아래처럼 로드할 필요조차 없으므로 로드 자체를 하지 않습니다.

@font-face {
  font-family: NanumSquare;
  src: url(NanumSquareR.eot) format('embedded-opentype'), /* chrome browser 로드안함 */
       url(NanumSquareR.woff) format('woff'),
       url(NanumSquareR.ttf) format('truetype'); 
  font-weight : 400;
}

image

format에 사용할 파일 형식은 아래와 같습니다.

파일 형식 Format 값
.woff “woff”
.ttf “truetype”
.ttf, otf “opentype”
.eot “embedded-opentype”

CDN

goole fonts 구글 폰트 사이트에서 원하는 폰트 및 스타일을 커스터마이징 해서 사용하는 방법도 있습니다. 이 방법을 사용할 때는 CSS보다 위에 작성하는 것이 좋습니다.


 <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
   	<title>Document</title>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;300;400;500&display=swap" rel="stylesheet"> <!-- 웹 폰트 먼저 작성 -->
    <link rel="stylesheet" href="main.css"> 
  </head>

@font-face와 비교했을 때 속도가 약간 느리다는 단점이 있지만 사용하는 방법은 굉장히 편합니다.

웹 폰트의 한계

지금까지 정리한 내용을 토대로 하면 @font-facecdn을 사용하는 방식보다 빠르고 원하는 폰트를 사용자의 로컬 환경에 구애받지 않고 사용할 수 있는 장점 뿐인 기능이라고 생각할 수 있습니다.

하지만, 서버에 요청해서 받아서 사용할 경우 네트워크 및 다양한 변수로 인해 제대로 로드하지 못할 수 있습니다. 그로인해 발생할 수 있는 문제점에 대해서 정리해보겠습니다.

아래는 취소텍스트를 강조를 위해 취소 텍스트에만 웹 폰트를 적용한 예시 입니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
      @font-face {
        font-family: "NotoSansCJKkr";
        src: url(./NotoSansCJKkr-Bold.otf);
      }
      .highlight {
        font-family: NotoSansCJKkr, sans-serif;
        font-size: 28px;
      }
    </style>
  </head>
  <body>
    <span>[긴급] N-Tech Service 재택근무 연장</span>
    <span class="highlight">취소</span>
  </body>
</html>

font-delay

새로고침을 할 때마다 webfont를 사용하는 “취소”텍스트는 깜빡이는 현상을 보실 수 있습니다. 여기서는 심각하지 않아서 문제가 되지 않을 수도 있지만 webfont로딩 시간이 길어질 경우 어떤 사용자는 ‘재택근무가 연장되었다’ , 어떤 사용자는 ‘재택근무 연장이 취소되었다’ 라는 서로 다른 정보를 가져가게 됩니다.

위 같은 이슈를 해결하는 방법을 알아보기 전에 위 같은 이슈가 왜 발생하는지 알기 위해서 브라우저 렌더링 과정에 간단히 이해하고 넘어가겠습니다.

image

사용자가 특정 url에 접속해서 서버에 HTML을 요청 해서 받아오면 렌더링 엔진이 html 코드를 읽어가면서 DOM Tree를 만들고 css 코드를 읽어가며 CSSOM Tree를 든 후에 layout을 잡고 paint하게 됩니다.

웹 폰트는 CSSOM Tree를 만드는 과정에서 font를 GET 하는데 이 과정에서 로드할 때까지 텍스트를 painting하지않습니다. 그래서 위에서 봤던 것처럼 기본 폰트를 사용하는 글씨들은 정상적으로 paint되는 반면, 웹폰트를 사용하는 텍스트는 painting이 뒤늦게 되는 것입니다. 그러니 webfont를 GET하는 시간이 길어지면 길어질수록 전혀 다른 정보를 제공하는 사이트가 되게 됩니다.

하지만 painting을 하지 않는 방법도 브라우저별로 차이가 있습니다.

IE

IE는 FOUT(flash of unstyled text) 방식으로 웹폰트를 처리합니다. 화면이 깜빡이지만, 스타일 없는 텍스트를 깜빡입니다.

fout

그 외 브라우저

그 외 브라우저들은 FOIT(flash of invisible text) 방식으로 웹폰트를 처리합니다. 화면이 깜빡이지만, 텍스트를 보여주지 않고 깜빡입니다.

foit

해결 방법

웹 폰트를 서버에서 로드할 때 걸리는 시간은 어떻게 할 수 없기 때문에, 로드하는 과정에서 사용자에게 같은 정보를 제공하는 것이 일관된 사용자 경험(UX)를 제공할 수 있는 방법이라고 생각합니다. 많은 브라우저에서 사용하는 FOIT방식이 아닌 IE의 FOUT 방식으로 깜빡임을 처리해보겠습니다. 이외에도 다양한 해결 방법이 있지만 해당 글에서는 다루지 않겠습니다.

font-display

font-display라는 속성을 통해 웹폰트가 로드되는 동안 font가 display되는 방법을 정할 수 있습니다.

font-display: auto;
font-display: block; 
font-display: swap;
font-display: fallback;
font-display: optional;

image

위 내용은 MDN에서 가져왔습니다.

  • font-display : block -> font-face가 로드되지 않았을 때 invisible로 렌더링 한다고 합니다. FOIT
  • font-display : swap -> font-face가 로드되지 않았을 때 fallback font로 렌더링 한다고 합니다. FOUT

여기서 fallback font란 로드에 실패했을 때 보여질 기본 폰트입니다. 아래 상황에서는 sans-serif가 fallback font가 됩니다.

 font-family: "NotoSansCJKkr" , sans-serif;

우리가 원하는 건 웹폰트를 로드하는 과정에서 기본 폰트라도 보여주고 싶은 것이니 fontface객체에 아래처럼 속성을 추가해주겠습니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
       @font-face {
        font-family: "NotoSansCJKkr";
        src: url(./NotoSansCJKkr-Bold.otf);
        font-display : swap;
      }
      .highlight {
        font-family: NotoSansCJKkr, sans-serif;
        font-size: 28px;
      }
    </style>
  </head>
  <body>
    <span>[긴급] N-Tech Service 재택근무 연장</span>
    <span class="highlight">취소</span>
  </body>
</html>

fout

위에서 보시는 것처럼 크롬 브라우저에서도 웹폰트를 로딩할 때도 FOIT방식이 아닌 FOUT방식으로 처리를 해주었습니다.