Local Font Access API를 사용하여 사용자의 로컬에 설치된 글꼴에 액세스하고 글꼴에 관한 하위 수준 세부정보를 가져오는 방법을 알아보세요.
웹 안전 글꼴
웹 개발을 오래 해 왔다면 소위 웹 안전 글꼴을 기억하실 것입니다.
이러한 글꼴은 가장 많이 사용되는 운영체제(Windows, macOS, 가장 일반적인 Linux 배포, Android, iOS)의 거의 모든 인스턴스에서 사용할 수 있는 것으로 알려져 있습니다. 2000년대 초반에 Microsoft는 '이러한 글꼴을 지정하는 웹사이트를 방문할 때마다 사이트 디자이너가 의도한 대로 페이지가 표시되도록' 하는 것을 목표로 이러한 글꼴을 무료로 다운로드할 수 있도록 하는 웹용 TrueType 핵심 글꼴이라는 이니셔티브를 주도하기도 했습니다. 예, Comic Sans MS로 설정된 사이트가 포함됩니다. 다음은 클래식 웹 안전 글꼴 스택 (sans-serif
글꼴의 최종 대체 글꼴 포함)의 예입니다.
body {
font-family: Helvetica, Arial, sans-serif;
}
웹 글꼴
웹 안전 글꼴이 정말로 중요했던 시대는 이미 오래전에 지났습니다. 오늘날에는 웹 글꼴이 있으며, 이 중 일부는 다양한 노출된 축의 값을 변경하여 추가로 조정할 수 있는 가변 글꼴이기도 합니다. CSS 시작 부분에 다운로드할 글꼴 파일을 지정하는 @font-face
블록을 선언하여 웹 글꼴을 사용할 수 있습니다.
@font-face {
font-family: 'FlamboyantSansSerif';
src: url('flamboyant.woff2');
}
그런 다음 평소와 같이 font-family
를 지정하여 맞춤 웹 글꼴을 사용할 수 있습니다.
body {
font-family: 'FlamboyantSansSerif';
}
지문 벡터로 사용되는 로컬 글꼴
대부분의 웹 글꼴은 웹에서 가져옵니다. 하지만 흥미로운 사실은 @font-face
선언의 src
속성이 url()
함수 외에도 local()
함수를 허용한다는 점입니다. 이를 통해 맞춤 글꼴을 로컬로 로드할 수 있습니다. 사용자의 운영체제에 FlamboyantSansSerif가 설치되어 있는 경우 다운로드되는 대신 로컬 사본이 사용됩니다.
@font-face {
font-family: 'FlamboyantSansSerif';
src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}
이 접근 방식은 대역폭을 절약할 수 있는 좋은 대체 메커니즘을 제공합니다. 인터넷에서는 안타깝게도 좋은 것을 누릴 수 없습니다. local()
함수의 문제는 브라우저 지문 인식에 악용될 수 있다는 것입니다. 사용자가 설치한 글꼴 목록은 식별력이 매우 높을 수 있습니다. 많은 회사에서 직원 노트북에 설치된 자체 기업 글꼴을 사용합니다. 예를 들어 Google에는 Google Sans라는 기업 글꼴이 있습니다.

공격자는 Google Sans와 같은 알려진 기업 글꼴이 많이 있는지 테스트하여 사용자가 어떤 회사에 근무하는지 파악하려고 시도할 수 있습니다. 공격자는 캔버스에서 이러한 글꼴로 설정된 텍스트를 렌더링하고 글리프를 측정하려고 시도합니다. 글리프가 알려진 회사 글꼴 모양과 일치하면 공격자가 적중한 것입니다. 글리프가 일치하지 않으면 공격자는 회사 글꼴이 설치되지 않았으므로 기본 대체 글꼴이 사용되었음을 알 수 있습니다. 이 공격 및 기타 브라우저 지문 공격에 관한 자세한 내용은 Laperdix et al.의 설문조사 논문을 참고하세요.
회사 글꼴 외에도 설치된 글꼴 목록만으로도 식별이 가능합니다. 이 공격 벡터의 상황이 너무 심각해져서 최근 WebKit팀은 '[사용 가능한 글꼴 목록에] 웹 글꼴과 운영체제에 포함된 글꼴만 포함하고 로컬로 사용자 설치된 글꼴은 포함하지 않기로' 결정했습니다. (그리고 여기에는 로컬 글꼴에 대한 액세스 권한 부여에 관한 도움말이 있습니다.)
Local Font Access API
이 도움말의 시작 부분으로 인해 기분이 좋지 않을 수도 있습니다. 정말 좋은 물건을 가질 수 없나요? 걱정하지 마세요. 할 수 있다고 생각합니다. 모든 것이 절망적인 것은 아닐지도 모릅니다. 하지만 먼저 여러분이 궁금해할 수 있는 질문에 답변해 드리겠습니다.
웹 글꼴이 있는데 Local Font Access API가 필요한 이유는 무엇인가요?
전문가 수준의 디자인 및 그래픽 도구는 웹에서 제공하기가 어려웠습니다. 한 가지 걸림돌은 디자이너가 로컬로 설치한 다양한 전문적으로 구성되고 힌트가 지정된 글꼴에 액세스하고 이를 사용할 수 없다는 점입니다. 웹 글꼴은 일부 게시 사용 사례를 지원하지만, 래스터라이저가 글리프 윤곽선을 렌더링하는 데 사용하는 벡터 글리프 모양과 글꼴 테이블에 대한 프로그래매틱 액세스를 지원하지는 않습니다. 웹 글꼴의 바이너리 데이터에 액세스할 방법도 없습니다.
- 디자인 도구는 자체 OpenType 레이아웃 구현을 실행하고 디자인 도구가 글리프 모양에 벡터 필터나 변환을 실행하는 등의 작업을 위해 하위 수준에서 연결되도록 허용하기 위해 글꼴 바이트에 액세스해야 합니다.
- 개발자는 웹으로 가져오는 애플리케이션에 기존 글꼴 스택이 있을 수 있습니다. 이러한 스택을 사용하려면 일반적으로 글꼴 데이터에 직접 액세스해야 하는데, 웹 글꼴은 이를 제공하지 않습니다.
- 일부 글꼴은 웹을 통한 전송에 대한 라이선스가 없을 수 있습니다. 예를 들어 Linotype에는 데스크톱 사용만 포함된 일부 글꼴의 라이선스가 있습니다.
Local Font Access API는 이러한 문제를 해결하기 위한 시도입니다. 다음 두 부분으로 구성됩니다.
- 사용자가 사용 가능한 전체 시스템 글꼴에 대한 액세스 권한을 부여할 수 있는 글꼴 열거 API
- 각 열거 결과에서 전체 글꼴 데이터를 포함하는 하위 수준 (바이트 지향) SFNT 컨테이너 액세스를 요청하는 기능
브라우저 지원
Local Font Access API 사용 방법
기능 감지
Local Font Access API가 지원되는지 확인하려면 다음을 사용하세요.
if ('queryLocalFonts' in window) {
// The Local Font Access API is supported
}
로컬 글꼴 열거
로컬에 설치된 글꼴 목록을 가져오려면 window.queryLocalFonts()
를 호출해야 합니다. 처음에는 권한 메시지가 트리거되며 사용자는 이를 승인하거나 거부할 수 있습니다. 사용자가 로컬 글꼴의 쿼리를 승인하면 브라우저에서 반복할 수 있는 글꼴 데이터가 포함된 배열을 반환합니다. 각 글꼴은 속성 family
(예: "Comic Sans MS"
), fullName
(예: "Comic Sans MS"
), postscriptName
(예: "ComicSansMS"
), style
(예: "Regular"
)이 있는 FontData
객체로 표현됩니다.
// Query for all available fonts and log metadata.
try {
const availableFonts = await window.queryLocalFonts();
for (const fontData of availableFonts) {
console.log(fontData.postscriptName);
console.log(fontData.fullName);
console.log(fontData.family);
console.log(fontData.style);
}
} catch (err) {
console.error(err.name, err.message);
}
글꼴의 하위 집합만 필요한 경우 postscriptNames
매개변수를 추가하여 PostScript 이름을 기준으로 필터링할 수도 있습니다.
const availableFonts = await window.queryLocalFonts({
postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});
SFNT 데이터 액세스
FontData
객체의 blob()
메서드를 통해 전체 SFNT 액세스를 사용할 수 있습니다. SFNT는 PostScript, TrueType, OpenType, Web Open Font Format (WOFF) 글꼴 등 다른 글꼴을 포함할 수 있는 글꼴 파일 형식입니다.
try {
const availableFonts = await window.queryLocalFonts({
postscriptNames: ['ComicSansMS'],
});
for (const fontData of availableFonts) {
// `blob()` returns a Blob containing valid and complete
// SFNT-wrapped font data.
const sfnt = await fontData.blob();
// Slice out only the bytes we need: the first 4 bytes are the SFNT
// version info.
// Spec: https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organization-of-an-opentype-font
const sfntVersion = await sfnt.slice(0, 4).text();
let outlineFormat = 'UNKNOWN';
switch (sfntVersion) {
case '\x00\x01\x00\x00':
case 'true':
case 'typ1':
outlineFormat = 'truetype';
break;
case 'OTTO':
outlineFormat = 'cff';
break;
}
console.log('Outline format:', outlineFormat);
}
} catch (err) {
console.error(err.name, err.message);
}
데모
데모에서 Local Font Access API의 실제 작동을 확인할 수 있습니다. 소스 코드도 확인하세요. 데모에서는 로컬 글꼴 선택기를 구현하는 <font-select>
이라는 맞춤 요소를 보여줍니다.
개인정보 보호 고려사항
"local-fonts"
권한은 지문이 매우 잘 찍히는 표면을 제공하는 것으로 보입니다. 하지만 브라우저는 원하는 것을 자유롭게 반환할 수 있습니다. 예를 들어 익명성에 중점을 둔 브라우저는 브라우저에 내장된 기본 글꼴 세트만 제공할 수 있습니다. 마찬가지로 브라우저가 디스크에 표시되는 대로 정확하게 표 데이터를 제공할 필요는 없습니다.
가능한 경우 Local Font Access API는 언급된 사용 사례를 지원하는 데 필요한 정보만 정확하게 노출하도록 설계되었습니다. 시스템 API는 무작위 또는 정렬된 순서가 아닌 글꼴 설치 순서로 설치된 글꼴 목록을 생성할 수 있습니다. 이러한 시스템 API에서 제공하는 설치된 글꼴 목록을 정확하게 반환하면 지문 생성에 사용될 수 있는 추가 데이터가 노출될 수 있으며, 사용 설정하려는 사용 사례는 이 순서를 유지하는 데 도움이 되지 않습니다. 따라서 이 API에서는 반환되는 데이터를 반환하기 전에 정렬해야 합니다.
보안 및 권한
Chrome팀은 사용자 제어, 투명성, 인체 공학을 비롯해 강력한 웹 플랫폼 기능에 대한 액세스 제어에 정의된 핵심 원칙을 사용하여 로컬 글꼴 액세스 API를 설계하고 구현했습니다.
사용자 제어
사용자 글꼴에 대한 액세스는 완전히 사용자가 제어하며 권한 등록부에 나열된 "local-fonts"
권한이 부여되지 않는 한 허용되지 않습니다.
투명성
사이트에 사용자의 로컬 글꼴에 대한 액세스 권한이 부여되었는지 여부는 사이트 정보 시트에 표시됩니다.
권한 지속성
"local-fonts"
권한은 페이지 새로고침 간에 유지됩니다. 사이트 정보 시트를 통해 취소할 수 있습니다.
의견
Chrome팀은 Local Font Access API 사용 경험에 관한 의견을 듣고 싶습니다.
API 설계에 대해 알려주세요.
API가 예상대로 작동하지 않는 부분이 있나요? 아이디어를 구현하는 데 필요한 메서드나 속성이 누락되어 있나요? 보안 모델에 관해 궁금한 점이나 의견이 있으신가요? 해당 GitHub 저장소에 사양 문제를 제출하거나 기존 문제에 의견을 추가하세요.
구현 문제 신고
Chrome 구현에서 버그를 발견하셨나요? 아니면 구현이 사양과 다른가요?
new.crbug.com에서 버그를 신고합니다. 최대한 많은 세부정보와 재현을 위한 간단한 안내를 포함하고 구성요소 상자에 Blink>Storage>FontAccess
를 입력합니다.
API 지원 표시
Local Font Access API를 사용할 계획인가요? 공개적인 지원은 Chrome팀이 기능의 우선순위를 지정하는 데 도움이 되며 다른 브라우저 공급업체에 이러한 기능을 지원하는 것이 얼마나 중요한지 보여줍니다.
#LocalFontAccess
해시태그를 사용하여 @ChromiumDev에 트윗을 보내 어디에서 어떻게 사용하고 있는지 알려주세요.
유용한 링크
- 설명
- 사양 초안
- 글꼴 열거를 위한 Chromium 버그
- 글꼴 테이블 액세스 관련 Chromium 버그
- ChromeStatus 항목
- GitHub 저장소
- TAG 검토
- Mozilla 표준 포지션
감사의 말씀
Local Font Access API 사양은 Emil A. Eklund, Alex Russell, Joshua Bell, Olivier Yiptong 이 도움말은 조 메들리, 도미닉 뢰트셰스, 올리비에 입통이 검토했습니다. Unsplash의 브렛 조던이 촬영한 히어로 이미지