스타일/font

웹에서의 폰트

richready2011 2022. 8. 25. 14:09

@refer:

웹디자이너가 디자인 한 것을 웹에 옮기려면 웹디자이너가 원하는 것을 구현할 수 있는 기술을 알고 있어야 한다.

디자이너 마다 성향이 달라서 어떤 디자이너는 폰트를 중요하게 보고, 어떤 디자이너는 비쥬얼을 중요하게 보고... 하는거 같은데, 디자인에 대해선 전혀 모르기 때문에, 어떤게 중요한지는 모르겠고, 일반인의 눈으로 보는 웹디자인은 전체를 보게 된다.

전체적으로 봤을때 이쁘면 이쁘다. 어색하면 어색하다 정도의 주관적 의견이 있을뿐이다.
이렇게 주관적 일수 밖에 없는 이유는 학문적 뒷받침이 없기 때문에, 왜 어색하고, 왜 이쁜지를 설명할 수가 없다.

컴퓨터 글꼴

컴퓨터에게 글꼴은 3가지가 있다.

  • 비트맵 방식의 글꼴
  • 외곽선 방식의 글꼴(벡터)
  • 스트로트 글꼴

비트맵은 수많은 점을 찍어서 하는 방식이다. 컴퓨터가 연산해야할 부분이 적기 때문에 속도가 빠르지만, 확대하면 계단현상같은 부분이 보인다.

외곽선 방식은 실제로 선을 그리는 방식으로, 표현하기 위한 정보와 컴퓨터 연산이 더 많다. 계단현상이 없지만 정보와 연산이 더 들어가기 때문에 느리다.

스트로크 글꼴은 지정된 선+부가정보 를 사용해서 크기+모양 을 결정한다.

글꼴 형식

  • 타입1, 타입3 글꼴 : 어도브사가 개발한 방식으로 베지에곡선 의 외곽선 글꼴.
  • 오픈타입 글꼴 : 마이크로소프트가 설계한 스마트폰트다(?). 트루타입+타입1
  • 트루타입 글꼴 : 애플이 개발한 글꼴로 타입1을 대체할 목적으로 만들어졌고, 베지에 곡선 으로 그린다. 대부분의 운영체제에 적용되고 있다.
  • 메타폰트 : 백터 글꼴을 정의하는데 사용되는 하나의 언어로, 주어진 점을 선분과 베지어 곡선 의 교점으로 정의하는 공식(?)
  • 웹폰트 : 동적 폰트의 일종으로 사용자 컴퓨터에 설치되지 않아도 사용할 수 있도록 고안된 개념이다.

글꼴 확장자

이런 형식에 따라 글꼴 확장자가 다르다.

  • EOT (Embedded OpenType) - 윈도우개발, IE9 이전버전은 이 포맷만 인식한다.
  • TTF (TrueTypeFont) - Chrome 4+, Firefox 3.5, Opera 10+, Sarafi 3+
  • OTF (OpenTypeFont) - Chrome 4+, Firefox 3.5, Opera 10+, Sarafi 3+
  • WOFF (Web Open Font Format) - 불법복제 문제로 모질라와 여러단체가 웹에 사용할 목적으로 개발했고, 라이센스명시가 메타정보로 들어가 있다.
  • SVG (Scalable Vector Graphics) - Chrome, Safari, Opera 최근버전 지원

최근에 인터넷익스플로어가 자사개발 브라우저엔진을 포기하고, 웹킷엔진을 기반으로 버전업을 하기로 발표가 났다. 즉, WOFF 웹폰트는 브라우저에 상관없이 적용할 수 있게 됬다.

고정폭과 가변폭

글꼴은 고정폭과 가변폭으로 나뉘어 지는데, 어떤 폰트를 쓰면 폰트에 표현되는 너비가 균일한데 반해, 어떤 폰트는 글자마다 너비가 다르다. 이것이 고정폭과 가변폭의 차이다.

)

Serif 와 Sans Serif

두가지 종류의 폰트의 가장 큰 차이점은 삐침이 있는가 없는가 이다.

Serif 는 삐침이 있다.

Sans serif 는 삐침이 없다.

이 구별은 삐침이 있다 없다 정도로 구분하는것이 좋아보인다. 왜냐하면, 폰트를 디자인한 디자이너들은 삐침이 있기도 하고 없기도 하고, 끝이 둥글기도 하고 안둥글기도 해서, 전체가 삐침이 있다 없다 정도만 구분하는게 정신건강(?)에 좋다.

font-family 의 Serif, Sans Serif

브라우저에서 사용해 보자.

CSS 에는 추상적 글꼴 지정법이 있다.

  • font-family: Serif : 삐침글꼴 자동선택
  • font-family: Sans-serif : 삐침아닌거 자동선택
  • font-family: Monospace : 고정폭폰트 자동선택
  • font-family: Cursive : 필기체 자동선택
  • font-family: Fantasy : 약간의 그림등이 포함될 수도 있는 폰트 자동선택

끝이 삐쳐있는 글꼴이 많은데, 어떤걸 선택해서 보여주는 걸까? 가장 명확한 것은 폰트를 명시하는 것이다.

  • `font-family: Dotum'

맥 에서 SerifSans-serifMonospace 를 테스트 해보면

<style>
.a { font-family:Serif; }
.b { font-family:Sans-serif; }
.c { font-family:Monospace; }
.d { font-family:Cursive; }
.e { font-family:Fantasy; }
</style>

<p class="a">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- AppleMyungjo -->
<p class="b">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- Apple SD Gothic Neo -->
<p class="c">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- Courier -->
<p class="d">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- Apple Chancery -->
<p class="e">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- Papyrus -->

이렇게 컴퓨터 맘대로 설정됐다.

<style>
.a { font-family:Dotum, Serif; }
</style>

<p class="a">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- AppleMyungjo -->

맥은 돋움이 없기 때문에 물론 애플명조로 나온다.

윈도우7/10 테스트해 보면

<style>
.a { font-family:Serif; }
.b { font-family:Sans-serif; }
.c { font-family:Monospace; }
.d { font-family:Cursive; }
.e { font-family:Fantasy; }
</style>

<p class="a">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- Batang -->
<p class="b">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- Malgun Gothic -->
<p class="c">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- GulimChe -->
<p class="d">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- Gungsuh -->
<p class="e">우리나라 좋은나라. Aa Bb Cc Kk Ii Zz</p> <!-- Impact -->

시스템마다 지원하는 브라우저 폰트

폰트는 거의 명시한 상태로 디자인이 나오기 떄문에, 스타일 코드상 으로는 고민의 여지가 없다. 그냥 정한 폰트를 사용하면 된다.

하지만 구별할 필요가 있는게, 스타일 개발자도 시스템 지원폰트 를 헷갈리기 쉽고, 웹디자이너 또한 헷갈릴수 있기 때문에, 정리한게 도움이 된다.

이것은 WEB Safe Font 로 불린다. 모든 브라우저와 모든 디바이스 에서 정상적으로 동작하는 폰트 라는 의미이다. 이외에 폰트는 웹폰트를 써야 한다.

영문폰트에 한해서 일반적으로 선언되는 font-family 들을 조사해 봤는데,

font-family: Arial, Helvetica, sans-serif;
font-family: 'Arial Black', Gadget, sans-serif;
font-family: Impact, Charcoal, sans-serif;
font-family: 'MS Sans Serif', Geneva, sans-serif;
font-family: Tahoma, Geneva, sans-serif;
font-family: 'Trebuchet MS', Helvetica, sans-serif;
font-family: Verdana, Geneva, sans-serif; 

font-family: 'Book Antiqua', 'Palatino Linotype', Palatino, serif;
font-family: Bookman, serif;
font-family: Georgia, serif;
font-family: 'MS Serif', 'New York', serif;
font-family: 'Times New Roman', Times, serif;

font-family: Courier, monospace;
font-family: 'Courier New', Courier, monospace;
font-family: 'Lucida Console', Monaco, monospace; 

font-family: 'Comic Sans MS', cursive; 

font-family: Impact, Charcoal, fantasy; 

font-family: Symbol;
font-family: Webdings;
font-family: Wingdings, 'Zapf Dingbats'; 

등이라고 한다. 한글폰트 대상으로 WEB Safe Font 라는 타이틀의 정리본은 없고, OS 에서 지원하는 폰트를 그대로 따라가기에, OS별 지원폰트를 보는게 도움이 된다.

참고로 안드로이드는 이전에는

  • normal (Droid Sans)
  • serif (Droid Serif),
  • monospace (Droid Sans Mono)

였으나, 아이스크림 샌드위치 버전(after android4) 이후에는 Roboto 로 교체했다.

웹폰트

웹의 안전한 폰트가 있지만, 다른 폰트를 사용하고 싶을 때, 웹폰트를 지정해서 사용할 수 있다.

사용법

기본사용법은 이렇다.

@font-face {
        font-family: Elena;
        src: url(elena-regular.woff);
}

글꼴이름을 지정하고, 대상 폰트의 경로는 src에 넣어주면 설정은 끝난다.

p {
    font-family: Elena, serif;
}

동일한 폰트에 대해서 다른설정을 하고 싶을때, 특정조건을 지정해 두면 구분할 수 있다.

@font-face {
    font-family: Elena;
    src: url(elena-regular.woff);
    font-weight: normal;
}

@font-face {
    font-family: Elena;
    src: url(elena-bold.woff);
    font-weight: bold;
}
p {
    font-family: Elena, serif;
}

p strong {
    font-weight: bold;
}

조건은 다양하게 사용할 수 있다. 예를 들어 font-sytle 을 조합한다던지, font-stretch 를 조합해 둔다던지 해서, 특정 폰트를 적용할 수 있다.

@font-face {
    font-family: Elena;
    src: url(elena-regular.woff);
    font-style: italic;
}

@font-face {
    font-family: Elena;
    src: url(elena-bold.woff);
    font-weight: bold;
}
p {
    font-family: Elena;
    font-style: italic;
}

p strong {
    font-weight: bold;
}

src 속성은 콤마(,) 로 다중선언을 할 수 있다.

@font-face {
    font-family: Elena;
    src: url(elena-regular.woff2) format("woff2"),
        url(elena-regular.woff) format("woff");
}

브라우저는 format 을 보고, 자신이 가장 잘 표현할 수 있는 폰트를 선택 후 렌더링 한다.

@font-face {
    font-family: Elena;
    src: url(elena.eot?#iefix) format("embedded-opentype"),
         url(elena.woff2) format("woff2"),
         url(elena.woff) format("woff"),
         url(elena.otf) format("opentype"),
         url(elena.svg#elena) format("svg");
}

ie8 은 오래된 브라우저이고 eot 만 지원하기 때문에, #iefix 라는 식별자를 붙이면 ie9 이전 버전 빼고는 인식하지 않는다. (정확히는 다른 브라우저는 eot를 지원안하기 때문에 무시)

또다른 옵션으로 local 속성이 있다.

@font-face {
    font-family: Elena;
    src: local("Elena"),
         url(elena-regular.woff2) format("woff2"),
         url(elena-regular.woff) format("woff");
}

만약 시스템폰트에 해당이름의 글꼴이 설치되어 있다면 다운로드 하지 않는다.

마지막으로 unicode-range 속성이 있는데, 이는 유니코드 범위지정 을 통해서 좀더 세분화 하는 것이다. 이를 활용해서 각 나라별로 폰트를 재지정할 수가 있다.

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2'), 
       url('/fonts/awesome-l.woff') format('woff'),
       url('/fonts/awesome-l.ttf') format('truetype'),
       url('/fonts/awesome-l.eot') format('embedded-opentype');
  unicode-range: U+000-5FF; /* Latin glyphs */
}

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-jp.woff2') format('woff2'), 
       url('/fonts/awesome-jp.woff') format('woff'),
       url('/fonts/awesome-jp.ttf') format('truetype'),
       url('/fonts/awesome-jp.eot') format('embedded-opentype');
  unicode-range: U+3000-9FFF, U+ff??; /* Japanese glyphs */
}

이렇게 범위를 지정해서 OS 나라를 자동으로 구별해서 다운로드 하는 것이다.

최적화

폰트 로딩의 알고리즘은 아래와 같다.

  • 브라우저가 HTML 문서 요청
  • 브라우저가 HTML 응답 파싱 및 DOM 생성 작업을 시작
  • 브라우저가 CSS, JS 및 기타 리소스를 발견하고 요청을 발송
  • 모든 CSS 콘텐츠가 수신된 후 브라우저가 CSSOM을 생성하고 이를 DOM 트리와 결합하여 렌더링 트리를 생성
    • 렌더링 트리가 페이지에 지정된 텍스트를 렌더링하는 데 필요한 글꼴 버전이 무엇인지 나타내면 글꼴 요청이 발송
  • 브라우저가 레이아웃을 수행하고 콘텐츠를 화면에 페인팅
    • 글꼴을 아직 사용할 수 없으면, 브라우저가 텍스트 픽셀을 렌더링할 수 없음
    • 글꼴을 사용할 수 있게 되면, 브라우저가 텍스트 픽셀을 페인팅

이렇게 다운로드 되는 웹의 폰트를 사용하면 3가지 현상이 생긴다.

  • Flash of Invisible Text - FOIT 현상

웹폰트가 로딩될 동안 텍스트가 아예 안보인다.

  • Flash of Unstyled Text - FOUT 현상

웹폰트가 로딩되기 전에 깨진듯한 화면을 봐야 한다. 로딩된 후에는 폰트렌더링을 다시 한다.

  • Flash of Faux Text - FOFT 현상

폰트 적용전에 Regular 였다가 Bold로 바뀌는 현상 (폰트다운로드 타이밍 문제로 발생)

둘중 하나의 현상이 생기고, 크롬&파이어폭스는 FOIT 그 외는 FOUT 가 재현되고, FOFT는 브라우저 상관없이 발생한다. 어떤 브라우저가 됐든 이 현상이 눈에 거슬리기는 매한가지 이다.

피할수 있는 완벽한 방법은 없고, 몇가지 대안방법인데, 대안방법인 만큼 웹폰트는 안쓰는게 최고다.

Font Loading API 로 최적화

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
  style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});

font.load(); // don't wait for the render tree, initiate an immediate fetch!

font.ready().then(function() {
  // apply the font (which may re-render text and cause a page reflow)
  // after the font has finished downloading
  document.fonts.add(font);
  document.body.style.fontFamily = "Awesome Font, serif";

  // OR... by default the content is hidden, 
  // and it's rendered after the font is available
  var content = document.getElementById("content");
  content.style.visibility = "visible";

  // OR... apply your own render strategy here... 
});

호환성 문제가 있기 때문에 사용하기는 좀 기달려야 한다.

Google Webfont Loader

<a href="https://ajax.googleapis.com/ajax/libs/webfont/1.6.16/webfont.js">https://ajax.googleapis.com/ajax/libs/webfont/1.6.16/webfont.js</a>

WebFont.load({
  custom: {
    families: ['NanumSquare'], // @font-face에 선언한 폰트 패밀리명
    urls: ['../css/NanumSquare.css'], // @font-face가 선언된 css 경로
  }
});

이 스크립트는 웹폰트가 정상적으로 다운로드 되었을 때, 화면에 동적으로 붙여준다. 이미지의 preloading 같은 원리이다.

data-uri

img src="base64.ddhlskhdflkhsdlkhf" 이런식의 실제 이미지를 사용하지 않고, 바이너리 코드를 직접 삽입하는 방법이 있는데, 폰트도 이와같이 다운로드가 아니라 실제코드를 집어넣을 수 있다.

@font-face {
  font-family: NanumSquare;
  src: url(data:application/font-woff;base64,d09GRgABAAAAADEFFFFFEDCrgAAA...);
}

preload

태그의 속성을 이용해서 폰트를 지정하면 상황을 보고 브라우저가 리소스를 다운받을지 안받을지 판단한다.

<head>
  <link rel="preload" href="../webfont/NanumSquare/NanumSquare.woff" as="font" crossorigin>
</head>

호환성 문제가 있어서 이것도 보류.

서브셋 으로 폰트 줄이기

갂, 갅 등의 문자를 줄여준다.

폰트압축

  • 폰트 압축 : 압축해주는 사이트가 있는데, 호환성이 좋지 못하다. 서버의 GZIP 을 통해서 압축할 수 있다.
  • Zopfli 압축 : 약 5% 절감할 수 있다.