Typography
폰트를 분류가 아니라 역할로 부르고, 한글은 어느 역할에서든 Pretendard 가 그립니다.
역할과 담당 폰트
serif/sans 로 부르지 않는 이유 — 한글은 어느 스택이든 Pretendard 로 떨어지므로 font-serif 와 font-sans 가 한글에서 완전히 같아집니다. 이름이 거짓말을 하게 됩니다.
본문 · 제목 · UI 라벨
영문 Newsreader · 한글 Pretendard — html 기본값. 따로 붙이지 않아도 이게 적용된다.
숫자 (날짜 · 기간 · 카운터)
영문 Geist · 한글 Pretendard — tabular-nums 와 함께 써서 자릿수를 고정한다.
코드 · 식별자 · 토큰 이름
영문 Geist Mono · 한글 Pretendard — 본문의 강조도 대부분 코드라 백틱으로 처리한다.
같은 문장, 세 역할
라틴과 한글을 나란히 두어야 차이가 보입니다 — 한글만 보면 세 역할이 똑같아 보입니다(전부 Pretendard 이므로).
Typography carries the tone of a place.
서체는 그 공간의 결을 나릅니다.
26.08.03 · 1,234 · 0123456789
26.08.03 · 1,234 · 0123456789 (기본 폰트)
const items = posts.map(toRow);
제목 스케일
Heading 컴포넌트가 소유합니다. 굵기는 400~500 선에서 해결하고 굵은 고함(700)은 제목에 쓰지 않습니다.
조용히 쌓아가는 공간
h1 만 반응형입니다. 36px 고정이면 390px 화면에서 긴 제목이 2줄·90px 를 먹습니다(실측). 좁은 화면에서 한 단계 낮춥니다.
느림을 설계한다
코드 블록을 흑백으로
본문은 넉넉한 줄 간격으로 천천히 읽히게 둡니다. leading-loose 는 정체성의 일부라 줄이지 않습니다.
이탤릭을 쓰지 않습니다
한글에는 이탤릭체가 없습니다. 브라우저가 글자를 억지로 기울여 가짜 이탤릭을 만들기 때문에, 강조는 농도와 굵기로 합니다.
로드하는 폰트는 전부 font-style: normal 뿐입니다. 그래서 본문의 <em> 은 기울이지 않고 농도(gray-9)로 강조합니다.
글에서는 *이탤릭* 대신 **굵게** 나 백틱을 씁니다. 실제로 이 블로그의 강조는 인라인 코드 131건 대 이탤릭 2건입니다.
한글 폴백과 아이콘 정렬
한글은 앞 폰트에 글리프가 없어 글자 단위로 Pretendard 로 내려옵니다. 그 메트릭 차이가 아이콘 정렬을 어긋나게 합니다.
그래서 아이콘+한글 라벨은 line-box 중심이 아니라 items-baseline 으로 맞추고, 아이콘을 0.14em 내립니다. baseline 기준 잉크 중심이 맥락과 무관하게 ≈−0.36em 이기 때문입니다(Canvas TextMetrics 실측). 구현은 RouteLinkButton 이 소유합니다.
폰트 파일
Pretendard 는 self-host 서브셋입니다 — 시스템 한글 폰트에 의존하지 않아 전 플랫폼에서 같게 보입니다.
- · 한글 2,350자(KS X 1001 완성형) + 가변축 wght 400~700 → 343KB (원본 2,020KB 에서 83% 감축)
- · 서브셋 밖 음절은 시스템 폰트로 새므로
pnpm check:font가 콘텐츠를 전수 검사합니다 — 서브셋의 유일한 리스크를 배포 전에 잡습니다 - · Newsreader · Geist · Geist Mono 는 next/font 로 로드(라틴 subset)