텍스타일텍스트와 스타일을 합치다

폰트 API

폰트 89종의 메타데이터를 JSON 으로 제공합니다. 인증도, 키도 필요 없습니다. CORS 가 열려 있어 브라우저에서 바로 부를 수 있고, IP당 시간당 300회까지 호출됩니다.

키 불필요CORS 어디서나ETag 캐시시간당 300회JSON · UTF-8

엔드포인트

메서드경로설명
GET/api엔드포인트 안내 + 폰트 수
GET/api/fonts전체 폰트 목록 (count, fonts[])
GET/api/fonts/{slug}폰트 상세 · 없으면 404 {"error":"not_found"}

응답 예시 GET /api/fonts/noto-sans-kr

JSON
{
    "slug": "noto-sans-kr",
    "name": "Noto Sans KR",
    "ko": "노토 산스 KR",
    "category": "산세리프",
    "license": "OFL 1.1",
    "weights": [
        400,
        700
    ],
    "stack": "'Noto Sans KR', sans-serif",
    "copyright": "(c) 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'.",
    "maker": "Adobe",
    "hangul": {
        "covered": 11172,
        "total": 11172,
        "percent": 100
    },
    "coverage": {
        "hanja": 8138,
        "kana": 189,
        "box": 128,
        "jamo": 256,
        "latin": 53
    },
    "webfont": {
        "subset": true,
        "files": 286,
        "bytes": 5697444,
        "sample_load_bytes": 125696
    },
    "metrics": {
        "ink": 0.2114,
        "width": 0.92
    },
    "line_height": {
        "default": 1.448,
        "recommended": 1.45,
        "consistent": true,
        "spread_em": 0,
        "by_env": {
            "mac_linux": 1.448,
            "windows": 1.448
        }
    },
    "readability": {
        "role": "body",
        "grade": "A",
        "score": 96,
        "label": "본문 권장",
        "notes": [
            "굵기가 2종이라 본문·강조 사이의 중간 계조가 없습니다."
        ]
    },
    "css": "https://cdn.textyle.net/f/noto-sans-kr.css",
    "url": "https://textyle.net/font/noto-sans-kr",
    "likes": 0,
    "views": 64
}

필드

필드타입설명
slugstring폰트 식별자. CSS·페이지 URL 에 그대로 쓰입니다
ko / namestring한글 이름 / 원래 패밀리명
weightsint[]제공하는 굵기 (400, 700 …)
stackstringCSS font-family 에 그대로 넣는 값
hangul.coveredint한글 음절 11,172자 중 실제로 가진 글자 수. 부족하면 없는 글자가 □ 로 깨집니다
webfont.subsetboolunicode-range 조각 서빙 여부. false 면 글자 하나만 써도 파일 전체를 받습니다
webfont.sample_load_bytesint200자 표준 문단을 렌더할 때 실제로 전송되는 바이트. 폰트 간 비교용 고정 기준입니다
line_height.recommendedfloat이 값을 CSS line-height 에 넣으면 어디서 열어도 줄간격이 같습니다. 폰트 안 높이 값(hhea·typo·win)에서 계산합니다
line_height.consistentboolfalseline-height 를 안 적었을 때 맥과 윈도우에서 줄간격이 다르게 잡힙니다 (spread_em 만큼)
cssstring<link> 에 바로 넣는 웹폰트 CSS 주소

호출 예시

JavaScript
// 한글 전체 지원 + 가벼운 폰트만 골라내기
const r = await fetch('https://textyle.net/api/fonts');
const { fonts } = await r.json();

const safe = fonts.filter(f =>
  f.hangul?.percent === 100 &&          // 두부 안 나는 폰트
  f.webfont?.sample_load_bytes < 150_000  // 본문 150KB 미만
);
console.log(safe.map(f => f.ko));
curl
curl https://textyle.net/api/fonts/noto-sans-kr

요청 제한

IP당 시간당 300회 · 매 정시 초기화

인증이 없는 공개 API라 서버 보호를 위해 IP 기준으로 제한합니다. 모든 응답에 남은 호출 수가 헤더로 붙으니 미리 확인하고 조절할 수 있습니다.

헤더의미
X-RateLimit-Limit시간당 허용 횟수 (300)
X-RateLimit-Remaining이번 시간에 남은 횟수
X-RateLimit-Reset초기화 시각 (Unix 타임스탬프, 다음 정시)
Retry-After429 일 때만 — 몇 초 뒤 재시도하면 되는지

304 응답은 한도에서 차감하지 않습니다. 아래처럼 ETag 를 재사용하면 사실상 제한 없이 폴링할 수 있습니다 — 캐시를 잘 쓰는 쪽에 불이익이 없도록 한 설계입니다. 한도를 넘기면 429 와 함께 {"error":"rate_limited"} 가 돌아옵니다.

JavaScript · ETag 재사용 폴링
let etag = null;

async function poll() {
  const r = await fetch('https://textyle.net/api/fonts', {
    headers: etag ? { 'If-None-Match': etag } : {}
  });

  console.log('남은 호출', r.headers.get('X-RateLimit-Remaining'));

  if (r.status === 304) return null;        // 변경 없음 — 한도 차감 안 됨
  if (r.status === 429) {                    // 한도 초과
    const wait = +r.headers.get('Retry-After');
    console.warn(`${wait}초 뒤 재시도`);
    return null;
  }
  etag = r.headers.get('ETag');
  return (await r.json()).fonts;
}

캐시

목록·상세 모두 Cache-Control: public, max-age=120 이고 ETag 가 붙습니다. 목록 응답은 서버에서도 120초간 캐시되므로, 같은 시간대의 반복 호출은 항상 같은 결과를 즉시 받습니다. 조회수·좋아요가 최대 120초 늦게 반영될 수 있다는 뜻이기도 합니다.

자주 묻는 질문

API 키가 필요한가요?

아니요. 인증 없이 바로 호출할 수 있습니다. 다만 서버 보호를 위해 IP당 시간당 300회 제한이 있습니다.

브라우저에서 바로 부를 수 있나요?

네. Access-Control-Allow-Origin: * 이라 어느 도메인에서도 fetch 로 호출됩니다. 남은 호출 수도 X-RateLimit-Remaining 헤더로 읽을 수 있습니다.

한도에 걸리면 어떻게 되나요?

429Retry-After 를 돌려줍니다. 매 정시에 초기화되며, ETag304 를 받은 요청은 한도에서 차감하지 않습니다.

응답이 자주 바뀌나요?

폰트 목록은 자동 발견 파이프라인이 월·수·금 새벽에 갱신합니다. 목록 응답은 서버에서 120초간 캐시됩니다.