이성열 Seongyeol Yi

디자인 시스템

2026-07-01

개인 블로그를 위한 디자인 시스템.

이 글은 스펙이자 그 스펙으로 렌더된 예시이다.

아이디어

유행을 덜 타고 관리하기 쉬운 디자인 시스템을 만든다. RFC 문서에서 영감받았다.

두 원칙에서 출발한다. 가능한 텍스트와 그 배치·변형만으로 정보를 전달한다. 그림자·라운드·불필요한 토큰 같은 장식은 두지 않는다.

토큰

토큰으로 정의된 값만 사용한다. 위계는 색·크기·굵기가 아닌 번호·들여쓰기·빈 줄로 만들고, 정해둔 토큰 밖의 새 값은 늘리지 않는다. 다크 모드는 마크업·규칙을 그대로 두고 토큰만 재매핑한다.

stone 계열의 순흑백 5색. 값은 그대로 두고 이름만 shadcn 관례에서 빌린다 (background·foreground·muted·muted-foreground·border). 채운 강조(반전)는 별도 색 없이 배경·텍스트를 뒤집어(bg-foreground + text-background) 쓰고, 포커스 링과 선도 이 5색을 재사용한다.

토큰라이트 / 다크용도
background#faf9f5 / #0c0a09배경
foreground#1c1917 / #e7e5e4텍스트
muted#f1efe8 / #1c19172차 배경
muted-foreground#78716c / #8f887e2차 텍스트
border#a8a29e / #44403c

서체

아래 두 서체를 사용한다.

  • Pretendard: 읽는 글(본문·제목·목록·설명)은 가독성 좋은 서체
  • MonoplexKR: 정렬이 의미를 갖는 곳(코드·표·ASCII 괘선·[ ] 컨트롤·번호)은 고정폭.

아래 값을 사용한다.

  • 17px
  • 행간 1.75
  • 굵기는 400

아이콘

정보는 되도록 텍스트로 전한다. 버튼·컨트롤의 라벨은 아이콘이 아니라 글자로 쓴다 ([ 구독 ], [ 재생 ]). 방향·로딩처럼 글자로 대체하기 어렵거나, 좁은 도구 막대처럼 라벨이 공간을 해치는 곳에서만 아이콘을 쓰고, 그때는 lucide 한 벌로 통일한다. ASCII·유니코드 유사문자로 아이콘을 흉내 내지 않는다. 아이콘은 currentColor 단색, 크기는 글자에 맞춘다.

여백

  • 기본 상하 간격은 0.5lh
  • 헤딩 앞은 1lh
  • 읽기 폭은 40rem

마크다운 요소

글은 일반 마크다운으로 쓴다.

강조는 볼드가 아니라 배경 하이라이트로 나타낸다.

이탤릭은 쓰지 않는다.

링크는 내부는 밑줄, 외부는 끝에 화살표가 붙는다. 인라인 코드는 const x = 1 처럼 배경만.

첨자는 지원한다. 물 H2O, 210 = 1024.

순서 없는 목록은 - 로 쓰면 * 불릿에 행잉 인덴트로 렌더된다:

  • 이 항목처럼 짧게 쓸 수 있고, 항목이 길어져 줄이 넘어가면, 접힌 이 줄은 불릿이 아니라 첫 글자 아래로 정렬된다.
    • 중첩하면 이 항목처럼 한 단 더 들여쓴다.

순서 있는 목록도 마찬가지.

  1. 첫번쨰
  2. 두번째

인용은 평문처럼 > 마커로 시작한다

이미지는 읽기 폭에 꽉 차게(100%) 넣고, alt 텍스트가 아래 muted 한 줄 캡션이 된다:

캡션은 이미지의 alt 텍스트로 단다
캡션은 이미지의 alt 텍스트로 단다

구문 강조

tonsky.me 참조.

예측 가능한 노이즈(키워드·구두점·연산자)는 muted-foreground, 읽는 대상(이름·문자열· 숫자·정의·주석)은 모두 foreground.

import time

def worker(name):
    for i in range(10):
        print(f"{name}: {i}")  # 노이즈는 muted, 나머지(주석 포함)는 ink
        time.sleep(0.01)

컴포넌트

Button

누르면 동작(action)만. 호버 시 배경이 옅게 찬다. 켜고 끄는 상태는 Button 이 아니라 Checkbox 로 나타낸다.

Checkbox

켜고 끄는 이진 상태. [x] 켬 / [ ] 끔. 하나면 단일 토글로 쓴다.

여럿을 독립적으로 켜고 끌 땐 세로로 쌓는다(같은 표기를 공유한다).

Radio

여럿 중 하나만. 가로로 정렬한다.

Select

여럿 중 하나만 — 옵션이 많아 라디오가 길어질 때. 브래킷 [ 값 ▾ ]을 눌러 펼친다.

Slider

드래그로 값을 조절. 순수 텍스트(유니코드) — 가는 트랙() 위 손잡이, 채운 구간은 굵은 선().

Input

셸 프롬프트 $ 와 내용 폭에 맞는 필드.

Textarea

여러 줄 입력. 고정폭, 1px 선, 라운드·채움 없이 선과 포커스 아웃라인만.

Table

표는 마크다운(| |)으로 쓰면 1px faint 실선 격자로 렌더된다. 헤더 행은 배경으로 구분한다. 정렬이 의미라 셀은 고정폭. 값이 바뀌는 동적 표는 ui/Table을 쓰면 같은 격자·배경으로 렌더된다.

라벨
추천42
조회1,234

구분선

문단·구역을 가르는 대시 가로선. 코드블록 상하 보더와 같은 1px dashed 선이다. 마크다운 --- 이나 ui/Divider 로 넣는다.