Skip to content
Back to skills

Typeface

ASecurity

폰트와 스크립트 — 임베딩 라이선스, 로케일 스크립트 커버리지, 두부(tofu) 검증 증거, RTL 셰이핑, 서브셋 안전성. 트리거 "폰트 커버리지", "폰트 라이선스", "두부", "tofu", "글리프", "스크립트 커버리지", "RTL", "서브셋".

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 19, 2026
ai-agentsbashnode

Security analysis

A100/100

Scanned September 19, 2026

npx -y skills add snwlee/Nereus --skill typeface --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Typeface?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Typeface
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/snwlee-typeface/badge)](https://www.skillsdirectory.com/skills/snwlee-typeface)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: typeface
description: 폰트와 스크립트 — 임베딩 라이선스, 로케일 스크립트 커버리지, 두부(tofu) 검증 증거, RTL 셰이핑, 서브셋 안전성. 트리거 "폰트 커버리지", "폰트 라이선스", "두부", "tofu", "글리프", "스크립트 커버리지", "RTL", "서브셋".
---

# typeface

nereus:common 규칙을 따른다. 담당 에이전트: l10n-engineer.

## 0. 진짜 제약은 번역이 아니라 폰트다

도너(19 로케일 실운영, 읽기 전용)에서 나온 실측이다:

- **Oswald/Rubik/Didot 은 한국어·일본어·태국어를 빈 네모로 그린다.**
- **렌더러는 빠진 글리프를 `.notdef` 로 그리고 `exit 0` 한다.**
  로케일 하나가 통째로 두부로 나가는데 **모든 게이트가 초록이다.**
- RTL 에서 두 톤 타이틀이 문자열을 쪼개면 셰이퍼가 공백을 잃고 순서를 뒤집는다.
- **아랍 우선 폰트에는 라틴 숫자가 없다** — "4K" 가 아랍어 옆에서 두부가 됐다.
  라틴·아랍을 같이 덮는 얼굴이 필요하다.
- CJK 는 "Bold" 요청이 **SemiBold 에 이름 매칭**되어 한국어만 얇게 나왔다.

19 에서 이미 이랬다. **86 이면 스크립트 커버리지가 지배적 제약이다** —
RTL 만 7종(`ar`·`ur`·`iw-IL`·`fa` 4변종)이고 인도계·동남아 스크립트가 크게 는다.

**폰트를 찾기 전에 폰트 트리 전체를 `find` 한다.** 도너가 "없다"고 결론낸 얼굴들이
전부 있었고, 잘못된 경로를 본 것이었다.

## 1. 하네스는 폰트를 파싱하지 않는다 — 증거를 요구한다

이유 둘:
1. 폰트 파싱은 새 런타임 의존성을 부른다.
2. **하네스가 파싱해도 그 사고를 못 막는다.** 실제 렌더러가 고른 얼굴과 다를 수 있고,
   사고는 "폰트에 글리프가 없다"가 아니라 **"렌더러가 두부를 그리고 성공했다"** 였다.
   검증은 **렌더 직후 그 자리에서** 해야 의미가 있다.

그래서 프로젝트가 증거를 제출한다:

```json
"render": {
  "ko-KR": { "glyphCheck": { "ranAt": "2026-09-13", "tool": "fonttools", "missing": [] }, "titleRuns": 1 }
}
```

| 위반 코드 | 뜻 |
|---|---|
| `tofu-unverified` | 렌더 대상인데 증거가 없다. **미설정을 통과로 읽지 않는다** |
| `glyph-missing` | 증거에 빠진 글리프가 있다. 그대로 렌더하면 두부로 발행된다 |
| `rtl-split-run` | RTL 인데 타이틀을 여러 조각으로 그린다 |

RTL 판정은 `locales.json` 의 `direction` 으로만 한다 — 코드에 목록을 박지 않는다.
`render` 를 주지 않은 로케일은 렌더 대상이 아니라 두부 검사를 하지 않는다.

## 2. 폰트 검사

```bash
echo '{"requiredEmbedding":"game","typography":{"maxFontKb":900,"minSizePx":18},"fonts":[…],"targetLocales":["ko-KR"]}' \
  | node "${CLAUDE_PLUGIN_ROOT}/lib/font-check.mjs"
```

폰트 선언 형태:
```json
{ "name": "GameSans", "embedding": ["game"], "scripts": ["latin", "hangul"], "sizeKb": 400, "minSizePx": 18, "subset": false }
```

| 위반 코드 | 뜻 |
|---|---|
| `required-embedding-undeclared` | 요구 임베딩 종류를 안 줬다. **건너뛰지 않는다** |
| `license-embedding` | 폰트가 그 임베딩을 선언하지 않았다 |
| `script-uncovered` | 대상 로케일이 요구하는 스크립트를 어떤 폰트도 안 덮는다 |
| `subset-unsafe` | 유저 생성 텍스트가 있는데 서브셋했다 |
| `font-size-budget` | 폰트 용량 합이 예산을 넘는다 |
| `min-size` | 최소 표시 크기가 하한 미만이다 |

### 요구 임베딩은 제품이 정한다

게임은 `"game"`, 앱은 그 제품의 라이선스가 요구하는 종류다. **코드에 박지 않는다.**

**선언이 없으면 허용으로 치지 않는다.** 상당수 폰트가 특정 임베딩을 금지하거나 별도
계약을 요구한다. 웹폰트 라이선스로 게임에 넣는 것은 위반이다. **모름은 허용이 아니다.**

### 예산 기준은 값으로 받는다

`typography: { maxFontKb, minSizePx }`. 장르 프로파일은 게임 고유라 이 모듈이 전제하지 않는다
(게임은 `nereus-game:localization` 이 `profile.typography` 를 꺼내 넘긴다).
기준이 없으면 예산·크기는 `unmeasured` 에 남고 **통과로 내지 않는다.**
라이선스·스크립트·서브셋은 기준과 무관하므로 계속 판정된다.

### 유저 생성 텍스트가 있으면 서브셋을 금지한다

한글 11,172자를 다 넣으면 폰트가 수 MB 라 서브셋이 표준 해법이다. 그런데 닉네임·채팅은
**어떤 글자가 올지 모른다** — 서브셋한 폰트에서 유저 이름이 두부(□□□)가 된다.
용량 최적화의 대가가 그거면 최적화가 아니다.

## 3. 폭 판정은 폰트 메트릭이 있을 때만 실측이다

`avgCharWidth` 는 `expansion` 과 **다른 축**이다. 한글은 번역하면 글자 수가 줄지만
(`expansion` 0.8) 글자당 폭은 전각이라 라틴의 두 배다(`avgCharWidth` 1.0). 섞지 않는다.
메트릭을 주지 않으면 확장률 근사이고, 위반에 **`approx: true`** 가 붙는다.

## 4. 하지 말 것

- **글리프 증거 미제출을 통과로 읽지 않는다.** 성공처럼 보이는 것이 정확히 그 사고였다.
- **RTL 타이틀을 색 입히려고 쪼개지 않는다.** 두 톤 타이틀은 올바른 텍스트의 대가다.
- **요구 임베딩 기본값을 박지 않는다.** 제품이 정한다.
- **폰트 파일을 파싱하지 않는다.** 새 런타임 의존성을 추가하지 않는다.
- **스크립트가 없다고 결론내기 전에 폰트 트리 전체를 `find` 한다.**

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.