글리프 디자인 규약
모든 글리프는 이 규약을 따라야 폰트로 컴파일된다. 규약 위반은 빌드 단계에서 조용히 사라지는 버그가 된다.
자모 조합 시스템이 구축된 콘셉트(천지인)에서는 개별 음절 SVG를 직접 그리거나 고치지 말 것. 자모 정의(JSON)를 수정하고 재생성하라 — hangul-composition 스킬의 "자모 조합 시스템" 섹션 참조. 이 문서의 SVG 규약은 신규 콘셉트 탐색·시스템이 없는 글리프(라틴 등)에 적용된다. 시스템 엔진의 출력도 이 규약을 따른다.
좌표계
- 한 파일 = 한 글리프.
<svg viewBox="0 0 1000 1000">, y축은 아래로 증가 (SVG 표준) - 베이스라인 y=880. 한글 몸통은 대략 x 60–940, y 60–880 안에 그린다
- 라틴: 캡하이트 y≈180, x-하이트 y≈420, 디센더 y≈880–1000 (g, p 등만 880 아래로)
- 컴파일 시
y' = 880 − y로 폰트 좌표(y-up)로 변환된다 — 디자이너는 신경 쓸 필요 없음
경로 규약 (위반 시 빌드에서 소실)
- filled path만 사용한다.
stroke속성 금지. 이유: 폰트 글리프는 채워진 아웃라인만 존재한다. stroke로 그린 획은 컴파일 시 완전히 사라진다. 획은 반드시 두께를 가진 닫힌 도형으로 그린다. - 최상위
<path>요소만 사용한다.<rect><circle><g>transform속성<defs><use>금지 — 컴파일러가 path의 d 속성만 읽는다. - path 명령은 M L H V Q C A Z를 사용할 수 있다. 신뢰성을 위해 M L Q C Z를 권장한다.
- 겹치는 도형은 nonzero 규칙으로 합쳐진다. 속을 파려면(ㅇ·ㅁ의 카운터) 바깥 윤곽과 반대 방향으로 안쪽 윤곽을 그린다 (바깥 시계방향 → 안쪽 반시계방향).
fill="currentColor"를 지정한다 — 시안 페이지의 다크/라이트 테마 대응.
획 구성법
프리핸드 곡선을 즉흥으로 그리지 말고, 스켈레톤 → 아웃라인 순서로 작업한다:
- 획의 중심선(스켈레톤)을 좌표로 정의한다: 시작점, 끝점, 경유점
- 스펙의 획 굵기(예: 90)의 절반씩 양쪽으로 확장해 닫힌 도형을 만든다
- 수직획: 중심 x=c, 굵기 w →
M {c-w/2} y1 L {c+w/2} y1 L {c+w/2} y2 L {c-w/2} y2 Z - 곡선획은 Q/C로 바깥쪽·안쪽 윤곽을 각각 그려 닫는다
명시적 좌표 계산이 어림짐작보다 항상 낫다. 각 획의 좌표를 주석이 아닌 숫자로 확정하고 그려라.
시각 보정 원리 (수치보다 눈이 우선)
| 현상 | 보정 |
|---|---|
| 곡선·사선은 같은 크기여도 작아 보임 | 오버슈트: 기준선을 1.5~2.5% 넘겨 그림 (ㅇ·ㅅ 등) |
| 수평획은 수직획과 같은 굵기여도 굵어 보임 | 수평획을 6~10% 가늘게 |
| 획이 많은 글자(ㅃ·겹받침)는 검게 뭉침 | 해당 글리프만 굵기 5~15% 축소 (밀도 보정) |
| 획 교차부가 뭉쳐 보임 | 교차부에서 한쪽 획을 살짝 가늘게 (잉크트랩적 처리) |
적용한 보정값은 manifest.json에 기록해 다른 디자이너가 같은 논리를 재사용하게 한다.
디자인 언어 스펙 포맷
콘셉트마다 concept.md에 아래 JSON을 포함한다. 모든 디자이너는 이 값을 공유 상수로 사용한다:
{
"concept": "콘셉트명",
"unitsPerEm": 1000,
"strokeMain": 90,
"strokeHorizontalRatio": 0.92,
"contrast": 1.0,
"terminals": "round | flat | cut | ...",
"joins": "miter | round | 콘셉트 고유 규칙",
"counters": "open | closed",
"primitives": ["콘셉트를 구성하는 기본 도형/획 단위"],
"rules": ["형태 규칙을 문장으로 — 예: 모든 획의 시작은 원호로 연다"],
"unresolved": ["아직 규칙이 성립하지 않는 블록 유형/자모"]
}
시각 검증 (제출 전 권장)
좌표 검산만으로는 오독을 못 잡는다 (예: 브리지 위치가 다른 자모의 곁줄기로 읽히는 경우). 번들 스크립트로 렌더링해 눈으로 확인하라:
python3 .claude/skills/glyph-design/scripts/render_contactsheet.py _workspace/concepts/{콘셉트}/glyphs --out sheet.png
생성된 PNG를 Read 도구로 열어 각 글자가 의도한 음절로 읽히는지 확인한다.
자가 검증 체크리스트 (제출 전 필수)
- viewBox="0 0 1000 1000"이고 최상위 path만 있는가
- stroke 속성이 어디에도 없는가 (
grep stroke *.svg로 확인) - 모든 path가 Z로 닫혔는가
- 카운터(속공간)가 있는 글리프는 안팎 윤곽 방향이 반대인가
- 획 굵기가 스펙 ±5% 이내인가 (보정 적용분은 manifest에 기록했는가)
- 글리프가 슬롯 박스(slots.json 또는 기본값) 안에 있는가 (의도적 돌출은 manifest에 기록)