ai-rules 09-design · 디자인 시스템 규칙

09-design 디자인 시스템 규칙

우선순위

우선순위

이 규칙은 02-code 다음 적용된다. 코드 규칙과 충돌 시 02-code 우선.


1. 공통 금지 패턴 (Hard Bans — 항상 적용)

디자인 시스템 유무, 목업 유무, 글로벌/한국 서비스 무관하게 모든 UI 구현에 적용된다. 아래 패턴은 "AI가 만든 티"가 나거나 퀄리티 저하를 유발하므로 사용 금지.

레이아웃 & 컴포넌트

금지 패턴 대안
라운드박스 + 좌측/상단 컬러 보더 조합 카드, 인라인 레이아웃, 타이포 중심 구성
대시보드식 카드 격자 남발 (이유 없는 3열 카드) 실제 정보 구조에 맞는 레이아웃
카드 안에 카드 (card-in-card, 3단 이상 컨테이너 중첩) 계층 1~2단계 이내 유지
과도한 그라디언트 (여러 색 + 강한 불투명도) 단색 또는 절제된 단방향 그라디언트
목적 없는 배경 블러 (blur 장식용 남용) 실제 레이어 분리 목적에만 사용
아이콘 + 텍스트 모든 항목에 반복 적용 필요한 곳에만 아이콘 사용
progress bar 장식용 남용 실제 진행 상태가 있을 때만 사용
뱃지/태그 모든 항목에 붙이기 상태 구분이 필요한 항목에만
큰 숫자 + 작은 레이블 + gradient accent bar 조합 정보가 진짜 대시보드일 때만

로고/심볼 금지 패턴:

 로고 앞 네모/원 컬러 심볼 + 텍스트 조합 (AI 자동 생성 로고)
   예: [■] AppName  /  [●] ServiceName  /  [◆] BrandName

   이유: 실제 디자이너가 만든 로고처럼 보이려다 오히려 AI 생성 티를 냄.
         무의미한 도형은 브랜드 아이덴티티가 없고 전문성이 낮아 보임.

 대안:
   - 텍스트 로고만 사용 (wordmark) — 폰트 굵기와 자간으로 차별화
   - 실제 SVG 로고 파일이 있으면 그것을 사용
   - 로고가 없으면 "로고 없음" 상태로 두고 사용자에게 보고

색상

금지 패턴 대안
파란 계열 + 보라 계열 기본값 (AI 최빈출 색조) 프로젝트 고유 포인트 컬러 명시적 정의
purple-to-blue gradient 단색 또는 브랜드 기반 단방향 그라디언트
빨/주/노/초/파/남/보 6색 이상 동시 사용 메인 컬러 1개 + semantic 2~3색 (success/warning/error)
연한 컬러 배경 + 진한 동색 보더 + 진한 텍스트 조합 (어드민 스타일) 단일 배경색 + 텍스트 대비 확보
순수 흑백만 (#000, #fff) tinted neutral — 중성색에 색상 미량 혼합
하드코딩 색상값 (#xxx, rgb()) CSS 변수 또는 Tailwind 시맨틱 클래스
디자인 시스템 외 임의 컬러 추가 기존 팔레트 내에서만 선택

어드민 배지 패턴 구체 금지:

 아래 조합을 항목마다 반복하는 패턴
   bg-red-50   border border-red-200   text-red-700   "위험"
   bg-yellow-50 border border-yellow-200 text-yellow-700 "주의"
   bg-green-50  border border-green-200  text-green-700  "정상"
   bg-blue-50   border border-blue-200   text-blue-700   "정보"
   bg-purple-50 border border-purple-200 text-purple-700 "처리중"

 대안: 상태값이 필요하면 텍스트 컬러 변화만으로 구분
   또는 단일 neutral 배지에 아이콘/텍스트로 상태 표현

색상을 써야 하는 곳 (금지 ≠ 무채색만)

금지 목록은 남용을 막는 것이지, 색을 쓰지 말라는 뜻이 아니다. 색이 없으면 정보 구분이 어렵고, 브랜드가 사라지며, UI가 죽어 보인다.

반드시 색을 써야 하는 상황:

상황 사용 색상 이유
Primary CTA 버튼 포인트 컬러 사용자 행동 유도 — 가장 중요한 버튼은 눈에 띄어야 함
에러 메시지 / 에러 필드 destructive (빨간 계열) 사용자가 즉시 인지해야 하는 정보
성공 상태 success (초록 계열) 완료/정상 상태 명확히 구분
경고 상태 warning (노란/주황 계열) 주의가 필요한 정보
링크 텍스트 포인트 컬러 또는 underline 클릭 가능함을 나타냄
Active / 선택된 항목 포인트 컬러 배경 or 텍스트 현재 위치/선택 상태
브랜드 로고 영역 브랜드 컬러 아이덴티티

semantic 컬러 3종 세트는 항상 정의되어야 한다:

"colors": {
  "success": "#16a34a",
  "success-foreground": "#ffffff",
  "warning": "#d97706",
  "warning-foreground": "#ffffff",
  "destructive": "#dc2626",
  "destructive-foreground": "#ffffff"
}

절제의 기준 — 한 화면에 포인트 컬러가 몇 군데?

  • 적정: 1~3군데 (CTA 버튼, active 탭, 링크)
  • 과다: 5군데 이상 (시선이 분산되고 중요도 구분 불가)
  • 부족: 0군데 (무채색만 → 브랜드 없고 클릭 포인트 불명확)

폰트 (AI 기본값 금지)

아래 폰트는 AI 학습 데이터 최빈출값으로, 지정하지 않으면 자동으로 선택됨 — 명시적으로 금지:

금지 폰트 이유
Inter 글로벌 AI 기본값 — 한글 지원 없음
Roboto Android 기본값
Arial Windows 기본값
system-ui / -apple-system OS fallback — 브랜드 없음

한국 서비스 기본: 'Pretendard', 'Noto Sans KR', sans-serif 글로벌 서비스 기본: 레퍼런스 스타일에 맞는 폰트 지정 (섹션 6 참조)

타이포그래피

금지 패턴 대안
임의 간격값 (p-[13px], mt-[7px]) Tailwind 표준 스케일 (4px 단위)
폰트 크기 4단계 이상 혼용 타입 스케일 3단계 이내 유지
굵기 3가지 이상 혼용 2가지 굵기만 사용 (regular + bold 또는 medium + bold)

이모지 & 아이콘

이모지는 마크다운 문서처럼 구조적으로 꼭 필요한 곳 외에는 사용하지 않는다.

 이모지 남발 패턴 (모두 금지)
   🚀 빠른 시작          ← 버튼/메뉴 앞 이모지
   ✨ 새로운 기능         ← 카드 헤더 이모지
   📊 분석 대시보드       ← 섹션 제목 이모지
   💡 도움말             ← 리스트 아이템 이모지
   🎉 완료되었습니다!     ← 상태 메시지 이모지
   ❤️ 즐겨찾기  ⭐ 평점   ← 기능 설명 이모지

 이모지 허용 범위
   - README, CHANGELOG 같은 마크다운 문서의 섹션 구분
   - 사용자가 직접 입력한 콘텐츠 (채팅, 리뷰 등)
   - 사용자가 명시적으로 이모지 사용을 요청한 경우
  • UI에서 아이콘이 필요하면 SVG 아이콘 라이브러리 사용 (Lucide, Heroicons 등)
  • 이모지를 아이콘 대용으로 쓰는 것은 전면 금지

애니메이션

금지 패턴 대안
ease / linear (기본값) cubic-bezier(0.16, 1, 0.3, 1) (ease-out-expo)
bounce easing 자연스러운 감속 곡선
애니메이션 미구현 (정적 only) hover/focus 전환에 transition 필수
/* 기본 전환 기준 */
transition: all 150ms cubic-bezier(0.16, 1, 0.3, 1);

/* prefers-reduced-motion 대응 필수 */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

톤 & 표현

  • 자극적/과장된 표현 금지 ("완벽한", "놀라운", "최강의")
  • 흥미를 유발하되 신뢰감 있는 톤 유지
  • 불신을 일으키는 마케팅성 문구 금지

2. 공통 적용 원칙 (항상)

시각적 절제

  • 컬러는 메인 컬러 1개 중심 — 추가 색은 중성 톤으로 보완
  • 컴포넌트 스타일은 일관되게 — 같은 역할의 컴포넌트는 같은 스타일
  • 정보 계층은 크기/굵기/색상 중 한 가지 변화로 표현 — 세 가지 동시 적용 금지
  • 강조는 절제 — 모든 것을 강조하면 아무것도 강조되지 않음

사용자 경험 (UX) 우선 원칙

디자인은 보기 좋은 것보다 쓰기 편한 것이 먼저다.

클릭/탭 타겟

  • 버튼, 링크, 인터랙티브 요소의 최소 크기: 44×44px (모바일 기준)
  • 클릭 가능한 영역이 시각적 요소보다 충분히 커야 함

입력 편의성

  • 폼 필드 순서는 사용자 사고 흐름을 따름 (이름 → 이메일 → 비밀번호)
  • 에러 메시지는 필드 바로 아래 즉시 표시 (submit 후 페이지 상단에만 표시 금지)
  • placeholder만으로 레이블 대체 금지 — label 요소 별도 필수
  • 자동완성(autocomplete) 속성 적용

피드백

  • 액션 후 200ms 이내 시각적 반응 (버튼 색 변화, 로딩 표시 등)
  • 로딩 2초 이상 → 진행 상태 표시 필수
  • 성공/실패 결과를 명확하게 — "처리되었습니다" 대신 "주문이 완료되었습니다"

네비게이션

  • 사용자가 현재 어디 있는지 항상 알 수 있어야 함 (breadcrumb, active 상태)
  • 뒤로 가기 / 취소 / 닫기는 항상 제공

상태 구현 (State Design)

모든 UI 컴포넌트는 아래 상태를 구현한다 — 누락 시 auto-fail:

상태 구현 방법
hover 배경색 변화 또는 underline
focus ring-2 + 포인트 컬러 (접근성 필수)
disabled opacity-50 + cursor-not-allowed
loading skeleton 또는 spinner
error 빨간 테두리 + 에러 메시지 텍스트 (필드 바로 아래)
empty empty state 안내 텍스트 또는 일러스트

3. 한글 UI 필수 설정

한글이 포함된 UI에는 아래를 반드시 적용한다.

CSS 필수 속성

body {
  font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
  word-break: keep-all;       /* 한글 단어 중간 줄바꿈 방지 */
  line-height: 1.7;           /* 한글 가독성 (영문 기준 1.4보다 넉넉하게) */
  letter-spacing: -0.02em;    /* 한글 자간 미세 조정 */
}

한글 타이포그래피 기준

항목 영문 일반 한글 권장
line-height 1.4~1.5 1.6~1.8
letter-spacing 0 -0.02em ~ -0.05em
word-break 기본 keep-all 필수
본문 최소 크기 12px 가능 14px 이상 (그 이하 가독성 급락)

자주 하는 실수

  • word-break 미설정 → 한글 단어 중간에서 줄바꿈
  • 행간 1.4 → 한글이 좁고 붙어 보임
  • 버튼 패딩 부족 → 한글 텍스트가 버튼을 넘침
  • 폰트 미지정 → OS별 다른 렌더링 (Windows/macOS/Android)

한글 폰트 선택 기준

폰트 특징 추천 용도
Pretendard UI 최적화, 9웨이트, 가변 폰트, 한국 스타트업 표준 웹/앱 UI 전반
Noto Sans KR 11,172 음절 전체 지원, Google CDN 넓은 지원 필요 시
Noto Serif KR 명조 계열 에디토리얼, 아티클

4. 디자인 시스템 확인 절차 (UI 작업 시작 전)

프론트엔드 구현 시작 전 아래 순서로 확인한다.

1. docs/design/design-tokens.json 존재 여부 확인
2. 있으면 → 토큰 읽고 구현에 적용
3. 없으면 → 아래 "디자인 시스템 없을 때" 절차 실행

5. 디자인 시스템 없을 때

디자인 시스템(docs/design/design-tokens.json)이 없고 목업도 없을 때:

Step 1 — 서비스 성격 파악 후 레퍼런스 제안

사용자에게 아래 옵션을 제시하고 선택을 받는다:

"디자인 시스템이 없습니다. 스타일 방향을 먼저 정하겠습니다.
 아래 중 가장 가까운 느낌을 선택해주세요:

 [한국 서비스 스타일]
 A) 토스 스타일 — 흰 배경, 강한 포인트 컬러, 원터치 UX, 금융/핀테크
 B) 당근마켓 스타일 — 따뜻한 오렌지, 리스트 중심, 로컬 커뮤니티
 C) 배민 스타일 — 브랜드 민트, 카테고리 강조, 푸드테크

 [글로벌 서비스 스타일]
 D) Linear / Vercel 스타일 — 다크 베이스, 모노톤, 개발자 도구
 E) Notion 스타일 — 라이트, 깔끔, 문서/생산성
 F) Stripe 스타일 — 라이트, 프리미엄, 결제/B2B
 G) Shadcn/ui 기본 — 미니멀, 컴포넌트 라이브러리

 H) 직접 설명해주세요"

Step 2 — 최소 디자인 시스템 생성

선택 받은 후 docs/design/design-tokens.json을 생성하고 사용자 확인 후 구현 시작:

{
  "_meta": {
    "style_reference": "선택된 레퍼런스명",
    "locale": "ko / global",
    "created": "YYYY-MM-DD",
    "note": "프로젝트 디자인 시스템 초안 — 사용자 확인 필요"
  },
  "colors": {
    "primary": "",
    "primary-foreground": "",
    "background": "",
    "foreground": "",
    "muted": "",
    "muted-foreground": "",
    "border": "",
    "destructive": ""
  },
  "typography": {
    "fontFamily": "",
    "lineHeight": "1.7",
    "letterSpacing": "-0.02em",
    "scale": {
      "xs": "12px", "sm": "14px", "base": "16px",
      "lg": "18px", "xl": "20px", "2xl": "24px", "3xl": "30px"
    },
    "weight": { "normal": "400", "medium": "500", "bold": "700" }
  },
  "spacing": {
    "unit": "4px",
    "scale": [0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96]
  },
  "radius": {
    "sm": "4px", "md": "8px", "lg": "12px", "full": "9999px"
  },
  "components": {
    "button": { "height": "44px", "paddingX": "20px", "radius": "md" },
    "input": { "height": "44px", "radius": "md" },
    "card": { "radius": "lg", "padding": "20px" }
  }
}

버튼/인풋 height를 44px로 기본 설정 — 모바일 터치 타겟 최소 기준 (Apple HIG 권장)

Step 3 — 토큰 없이 구현 금지

디자인 시스템 확인/생성 없이 임의 스타일로 UI 구현 시작 → auto-fail


6. 레퍼런스 스타일별 기본 토큰값

A) 토스 스타일 (Toss)

{
  "colors": {
    "primary": "#3182f6",
    "primary-foreground": "#ffffff",
    "background": "#ffffff",
    "foreground": "#191f28",
    "muted": "#f2f4f6",
    "muted-foreground": "#6b7684",
    "border": "#e5e8eb",
    "destructive": "#f04452"
  },
  "typography": {
    "fontFamily": "'Pretendard', 'Noto Sans KR', sans-serif",
    "lineHeight": "1.7",
    "letterSpacing": "-0.03em"
  },
  "_note": "흰 배경 + 파란색 포인트. 정보 위계 명확, 불필요한 장식 없음."
}

B) 당근마켓 스타일 (Karrot)

{
  "colors": {
    "primary": "#ff6f0f",
    "primary-foreground": "#ffffff",
    "background": "#ffffff",
    "foreground": "#1a1a1a",
    "muted": "#f5f5f5",
    "muted-foreground": "#868686",
    "border": "#ebebeb",
    "destructive": "#e84141"
  },
  "typography": {
    "fontFamily": "'Pretendard', 'Noto Sans KR', sans-serif",
    "lineHeight": "1.6",
    "letterSpacing": "-0.02em"
  },
  "_note": "따뜻한 오렌지. 이미지+텍스트+가격 리스트 중심."
}

C) 배민 스타일 (Baemin)

{
  "colors": {
    "primary": "#2ac1bc",
    "primary-foreground": "#ffffff",
    "background": "#ffffff",
    "foreground": "#333333",
    "muted": "#f8f8f8",
    "muted-foreground": "#888888",
    "border": "#e8e8e8",
    "destructive": "#ff4444"
  },
  "typography": {
    "fontFamily": "'Pretendard', 'Noto Sans KR', sans-serif",
    "lineHeight": "1.6",
    "letterSpacing": "-0.02em"
  },
  "_note": "민트 포인트. 카테고리 상단 노출, 텍스트 레이블 강조."
}

D) Linear / Vercel 스타일

{
  "colors": {
    "primary": "#ffffff",
    "primary-foreground": "#000000",
    "background": "#0a0a0a",
    "foreground": "#ededed",
    "muted": "#1a1a1a",
    "muted-foreground": "#a0a0a0",
    "border": "#2a2a2a",
    "destructive": "#ef4444"
  },
  "typography": { "fontFamily": "'Geist', 'Geist Mono', sans-serif" },
  "_note": "다크 모드 베이스. Inter 대신 Geist 사용."
}

E) Notion 스타일

{
  "colors": {
    "primary": "#2383e2",
    "primary-foreground": "#ffffff",
    "background": "#ffffff",
    "foreground": "#1a1a1a",
    "muted": "#f7f7f5",
    "muted-foreground": "#787774",
    "border": "#e9e9e7",
    "destructive": "#eb5757"
  },
  "typography": { "fontFamily": "'Plus Jakarta Sans', 'Pretendard', sans-serif" },
  "_note": "문서 중심. Inter 대신 Plus Jakarta Sans 사용."
}

F) Stripe 스타일

{
  "colors": {
    "primary": "#635bff",
    "primary-foreground": "#ffffff",
    "background": "#ffffff",
    "foreground": "#0a2540",
    "muted": "#f6f9fc",
    "muted-foreground": "#425466",
    "border": "#e6ebf1",
    "destructive": "#df1b41"
  },
  "typography": { "fontFamily": "'DM Sans', 'Pretendard', sans-serif" },
  "_note": "프리미엄 B2B. Sohne는 유료라 DM Sans 대체."
}

G) Shadcn/ui 기본

{
  "colors": {
    "primary": "#18181b",
    "primary-foreground": "#fafafa",
    "background": "#ffffff",
    "foreground": "#09090b",
    "muted": "#f4f4f5",
    "muted-foreground": "#71717a",
    "border": "#e4e4e7",
    "destructive": "#ef4444"
  },
  "typography": { "fontFamily": "'Geist', sans-serif" },
  "_note": "미니멀 컴포넌트. Inter 대신 Geist 사용."
}

7. 한국 서비스 UI 패턴 기준

한국 서비스 스타일(A/B/C) 선택 시 아래 패턴을 기본 적용한다.

정보 밀도 — 서비스 유형별 구분 필수

⚠️ "한국 유저 = 정보 밀도 높음"은 포털/어드민/공공 시스템 한정이다. 소비자 SaaS/앱에 이 인식을 그대로 적용하면 잘못된 방향으로 간다.

서비스 유형 정보 밀도 대표 사례
포털 높음 네이버, 다음 메인
어드민/사내 시스템 높음 ERP, CRM, 사내 관리툴
공공/금융 레거시 높음 정부24, 인터넷뱅킹
소비자 SaaS/앱 낮음~중간 토스, 당근, 배민, 카카오뱅크

소비자 SaaS/앱 원칙: 토스·당근·배민은 서양 동급 서비스보다 여백을 더 넓게, 폰트를 더 크게 쓴다. 이 구분을 먼저 파악한 후 밀도를 결정한다.

업무용 SaaS (B2B): Linear/Notion 정도의 중간 밀도. 포털 수준 압축은 금지.

포털/어드민 스타일로 구현하는 경우에 한해:

  • 카드에 보조 텍스트(가격, 날짜, 위치, 상태) 포함
  • 리스트 아이템: 이미지 + 제목 + 보조정보 2줄 구성이 기본
  • 중요 기능은 숨기지 말고 화면에 직접 노출

네비게이션

  • 하단 탭바 5탭 기본 (글로벌은 4탭 권장이나 한국은 5탭이 일반적)
  • 탭바 아이콘에 텍스트 레이블 항상 병기 (아이콘만 사용 금지)
  • 중요 기능은 플로팅 버튼보다 탭바 배치 선호

버튼 & CTA

  • 주요 CTA 버튼: full-width 스타일 (화면 하단 고정 버튼)
  • 버튼 텍스트: 아이콘만 쓰지 않고 텍스트 레이블 직접 명시
    • 또는 아이콘만
    • "쿠폰 받기", "무료 배달", "바로 시작하기"

바텀시트

컨텍스트 유지하며 추가 정보 제공 시 모달 대신 바텀시트 적극 사용.


8. 디자인 시스템 변경 규칙

  • design-tokens.json 임의 수정 금지 → 사용자 승인 필요
  • 새 토큰 추가 시 → 이유와 값 제안 후 승인 대기
  • 기존 토큰 삭제 금지 (deprecated 마킹 후 사용자 결정)

9. 커밋 전 디자인 셀프 체크

UI 변경이 포함된 커밋 전 확인:

공통 (항상)

  • Hard Ban 패턴 없음 (라운드박스+보더, 다색, card-in-card 등)
  • AI 기본 폰트(Inter/Roboto/Arial) 미사용
  • design-tokens.json 외 임의 색상값 없음
  • 이모지 남발 없음
  • hover/focus/disabled 상태 구현됨
  • loading skeleton / error / empty state 구현됨
  • transition easing 지정됨 (ease/linear 사용 금지)
  • prefers-reduced-motion 대응됨

한글 포함 시 추가

  • font-family: Pretendard 또는 Noto Sans KR 지정됨
  • word-break: keep-all 설정됨
  • line-height: 1.6 이상
  • 본문 폰트 14px 이상

10. 적용 범위

작업 Hard Ban 디자인 시스템 확인 한글 설정
신규 페이지/컴포넌트 구현 필수 필수 한글 포함 시 필수
기존 UI 대규모 변경 필수 필수 한글 포함 시 필수
단순 버그 수정 (1~2줄) 필수 생략 가능 생략 가능
이메일/문서/인포그래픽 필수 생략 가능 한글 포함 시 필수
백엔드 전용 작업 적용 안 함 적용 안 함 적용 안 함