본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 17. 04:37

100개의 사이트를 대상으로 직접 만든 도구를 실행해 보았습니다. 5개 중 1개는 잘못된 기본 폰트(Primary font)를 반환했습니다.

요약

npm CLI 도구인 brandmd는 웹사이트의 디자인 시스템을 추출하여 DESIGN.md 파일로 생성합니다. 이 도구는 원래 모든 DOM 요소에서 가장 빈도가 높은 폰트를 기본 폰트로 지정했지만, 테스트 결과 많은 사이트에서 잘못된 기본 폰트를 반환하는 문제가 발견되었습니다. 개발자는 분석을 통해 '디스플레이(Display) 우선', 'mono 제외', '폴백 건너뛰기'의 세 가지 원칙을 적용하여 도구를 개선했으며, 이로써 정확도가 크게 향상되어 대부분의 사례에서 올바른 브랜드 폰트를 보고합니다.

핵심 포인트

  • brandmd는 웹사이트 디자인 시스템 추출을 위한 npm CLI 도구입니다.
  • 초기 버전은 모든 요소의 빈도수 기반으로 기본 폰트를 결정하여 부정확했습니다.
  • 개선된 버전(v0.8)은 '디스플레이 영역 우선', '코드 폰트 제외', '실제 사용 가능한 폰트 사용' 원칙을 적용합니다.
  • 이러한 개선 덕분에 잘못된 기본 폰트 보고율이 크게 감소하여 정확도가 높아졌습니다.

저는 6개월 전에 brandmd를 만들었습니다. 이것은 어떤 웹사이트의 디자인 시스템(Design system)이라도 추출하여 DESIGN.md 파일로 만들어주는 npm CLI 도구입니다. 아이디어는 이렇습니다. 이 파일을 프로젝트 루트에 넣으면, AI 코딩 에이전트(Claude Code, Cursor, Gemini CLI, Stitch)가 이를 읽고 일반적인 shadcn-default 대신 브랜드에 맞는 UI를 생성하게 하는 것입니다. 잘 작동하고 있었습니다. Stripe, GitHub, Vercel, Linear — 기본 폰트(Primary fonts)가 정확하게 추출되었습니다. 그러다 지난주 한 사용자가 저에게 DM을 보냈습니다. "당신의 도구는 제 기본 폰트가 Inter라고 말합니다. 실제로는 Manrope입니다. 브랜드 폰트는 본문이 아니라 히어로(Hero) 섹션에 있습니다." 맞는 말이었습니다. 그래서 저는 이 버그가 얼마나 광범위한지 확인하기 위해 100개의 인기 있는 디자인 시스템 사이트를 대상으로 brandmd를 실행했습니다. 결과는 45개의 성공적으로 추출된 사이트 중 9개가 잘못된 기본 폰트(Primary font)를 반환했습니다. 20%였습니다.

brandmd가 지목한 사이트:
mantine.dev Reality
remix.run Menlo
neon.tech Outfit
valura.ai JetBrains Mono
railway.app Inter Variable
resend.com GeistMono
svelte.dev Inter
workday.design Manrope
htmx.org Times (히어로 섹션에 있는 브랜드 폰트)
Three different failure modes (세 가지 서로 다른 실패 모드):

  1. 코드 폰트의 승리: mantine과 remix는 홈페이지에 코드가 너무 많아서 JetBrains Mono / Menlo가 폰트 빈도수(Font frequency count)를 압도했습니다.
  2. 본문 텍스트가 브랜드를 압도함: valura는 737개의 요소(유틸리티)에 Inter를 사용하고, 28개(히어로)에 Manrope를 사용합니다. 빈도 순위는 Inter를 선택합니다. 대체 폰트(Fallback)는 Times입니다.
  3. 커스텀 폰트가 없는 사이트: Playwright의 기본 대체 폰트(Default fallback)를 로드합니다. 오래된 로직이 Times를 기본 폰트(Primary)로 나타냈습니다.

근본 원인 // analyze.js, v0.7.2
const primaryFont = fontList [ 0 ]?.[ 0 ];
그게 전부였습니다. 기본 폰트(Primary)는 단순히 모든 DOM 요소 전체에서 가장 빈도가 높은 폰트였던 것입니다. 본문 텍스트가 항상 이깁니다.

수정 사항 (v0.8, 방금 출시됨) // analyze.js, v0.8

const primaryFont = pickNonExcluded ( displayFonts ) || // fontSize >= 40px (hero)
pickNonExcluded ( headingFonts ) || // h1-h6
pickNonExcluded ( bodyFonts ) || // p, li, span, div
fontList [ 0 ]?.[ 0 ];

// 기본 폰트(Primary)에서 제외되는 항목: mono 폰트 (Menlo, JetBrains Mono, GeistMono 등),
// 기본 폴백(default fallbacks) (Times, Arial, Georgia), 아이콘 폰트 (Material Icons,
// Font Awesome, Heroicons).

세 가지 원칙:

  1. 디스플레이(Display) 우선. 히어로(Hero) 폰트가 브랜드 폰트입니다. 브랜드는 h2/h3 부제목이 아니라 fontSize >= 40px 영역에 존재합니다.
  2. mono 제외. 코드용 폰트는 보조(Secondary) 슬롯을 차지할 수는 있지만, 결코 기본(Primary)이 될 수 없습니다. mantine.dev의 경우 Outfit을 최상단에, JetBrains Mono를 코드 블록에 배치하기를 원합니다.
  3. 폴백(fallbacks) 건너뛰기. 사이트에 실제 커스텀 폰트가 없다면, Times를 정직하게 노출하는 것은 괜찮습니다. 하지만 실제 사용 가능한 폰트가 있다면, 그것들을 사용해야 합니다.

함께 출시된 기능:

  • 인용구 인식 font-family 파서 (v0.7.2에서 잘못 분리되었던 var(--font, 'Inter') 및 백슬래시 이스케이프(backslash escapes) 처리)
  • 역할별 캐스케이드 (heading은 display로, display는 body로 폴백)
  • 느린 SPA를 위해 내비게이션 타임아웃을 30초에서 45초로 연장

결과: 9개 중 7개의 잘못된 기본(Primary) 사례가 이제 올바른 브랜드 폰트를 보고합니다. 나머지 2개(railway.app, workday.design)는 히어로 영역에 실제로 구별되는 브랜드 폰트가 없으므로, 출력 결과는 정직합니다.

설치:
npm i brandmd

또는 설치 없이 실행

npx brandmd https://your-site.com

Repo: github.com/yuvrajangadsingh/brandmd

brandmd가 시간을 절약해 주었다면, 레포지토리에 별(star)을 눌러주세요. 다른 개발자들이 찾는 데 도움이 됩니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0