색상 시스템
개요
네 가지 도메인 — 웹 앱 UI, 마케팅/랜딩, 데이터 시각화, 터미널/TUI — 에 걸쳐 조명 + 다크 모드용으로 선별된 기성 색상 팔레트 라이브러리와, 새로운 팔레트를 구축하고 접근성을 검증하는 방법론을 제공합니다.
핵심 원칙: 원시 색상값이 아닌 의미론적 역할(배경, 텍스트, 기본 색상, 오류…)별로 색상을 선택하세요. 여기의 모든 팔레트는 16진수 값을 역할에 매핑하므로, 테마를 쉽게 교체하고 일관성과 접근성을 유지할 수 있습니다. 먼저 역할을 선택한 다음 해당 16진수 값을 읽으세요. 역할이 있어야 할 자리에 16진수 값을 하드코딩하면 나중에 테마가 깨집니다.
탐색
아래 색인과 역할 계약은 "어떤 팔레트"를 선택할지 자체적으로 결정합니다. 작업에 필요할 때 하나의 참조 파일을 로드하고, 네 개를 모두 로드하지 마세요.
| 로드 | 시기 |
|---|---|
| references/carbon.md | Carbon을 사용해야 하는 페이지나 아티팩트를 구축할 때 — 이 파일만 읽으면 됩니다. Carbon의 역할, 대시보드 키트 및 두 모드의 트라이어드가 포함되어 있습니다. |
| references/palettes.md | 다른 팔레트의 16진수 값이 필요할 때 — 네 가지 도메인, 밝은/어두운 모드, 채움/미묘함/강조 트라이어드, Dusk, Driftwood 및 Meadow 뒤에 있는 12단계 스케일 |
| references/contrast.md | WCAG/APCA 임계값 확인, 색맹 안전성 확인, 또는 실패하는 쌍 디버깅 |
| references/build-your-own.md | 라이브러리 팔레트가 적합하지 않고 새 스케일을 생성할 때 (OKLCH 레시피) |
| references/theory.md | 하모니 구성표를 선택하거나, 색상 공간/스케일 결정을 정당화할 때 |
팔레트 라이브러리 (빠른 색인)
하나의 팔레트가 가장 먼저 적합할 경우 ⭐로 표시됩니다. 마케팅 및 TUI에는 기본값이 없습니다. 선택은 브랜드나 사용자 자신의 터미널 테마를 따르기 때문입니다.
웹 앱 UI — 밝은 + 어두운, 13개의 의미론적 역할 + 색상당 트라이어드
- Carbon ⭐ (기본값) — 짙은 슬레이트 블루, 다크 퍼스트. 분석 대시보드, 성능 보고서 및 개발 도구. 전체 대시보드 키트(A–F 등급 알약, 정렬된 단계 시퀀스, 인라인 코드 톤, 성공 강조 표시)를 제공합니다. 밝은 모드가 동일하게 수동 조정되어야 할 경우 대신 Graphite를 사용하세요.
- Graphite — 차가운 슬레이트 + 블루. 밀도 높은 B2B 대시보드, 개발 도구; 밝음+어두움 동등성의 기본값.
- Evergreen — 진정한 중성 아연 위의 에메랄드 브랜드. 신선하고 자신감 있으며 블루가 아닌 아이덴티티.
- Terracotta — 따뜻한 클레이/에스프레소 중성 + 녹슨 색상. 에디토리얼, 콘텐츠 플랫폼, 글쓰기 도구.
- Bloom — 파스텔 페리윙클/바이올렛, 짙은 다크 모드. 친근한 개발 도구, 장난기 있지만 깔끔한 앱.
- Teal Slate — 차가운 슬레이트 위의 짙은 청록색, 단일 따뜻한 악센트. 기술 보고서, SRE / 속도 제한 대시보드; 수치용 단색 글꼴과 짝을 이룹니다.
역할과 함께 제공되어 확장하거나 재파생할 수 있는 12단계 OKLCH 스케일에서 생성:
- Dusk — 인디고 기본, 청록색 악센트, 중성에 가까운 차가운 회색. 집중 도구, 편집기, 장시간 사용 앱.
- Driftwood — 따뜻한 모래 중성 위의 짙은 해양 기본, 클레이 악센트. 어두운 모드에서 중성을 차갑게 바꾸는 팔레트.
- Meadow — 음소거된 세이지 기본, 올드 골드 악센트, 따뜻한 뼈 중성. 세트 중 가장 부드러움; 자신감보다는 편안함.
마케팅 / 랜딩 — 밝은 + 어두운, 히어로 그라디언트
- Sunbloom — 정제된 산호/호박색 따뜻함. 접근하기 쉬운 소비자/크리에이터 브랜드.
- Tidewater — 청록색/세이지. 핀테크, 웰빙, B2B 신뢰.
- Obsidian & Gold — 거의 검은색 + 메탈릭 골드. 프리미엄, 럭셔리, 에이전시.
- Paper & Ink — 따뜻한 종이 + 잉크 블랙 + 하나의 테라코타 악센트. 블로그, 장문, 포트폴리오.
데이터 시각화 — 색맹 인식, 따뜻함/차가움의 자연스러운
- 범주형: Lunar Valley ⭐ (기본값) · Hearthstead · Vintage Warm · Glass Wall · Okabe-Ito (CVD 안전이 필수 요구사항일 때 사용)
- 순차형: Viridis ⭐ (기본값) · Magma · Inferno · Plasma · ColorBrewer Blues · YlOrRd (모두 지각적으로 균일)
- 발산형: Console & Window ⭐ (기본값) · Alien Sun · Orchard Dusk · Coffee & Coolant — 모두 따뜻함↔차가움, 빨강↔초록 없음
터미널 / TUI — 16-ANSI + 배경/전경/커서/선택
- Solarized Dark · Nord · Catppuccin Mocha · Catppuccin Latte (유일한 밝은 구성표) · Dracula · Tokyo Night
→ 전체 16진수 표: Carbon은 references/carbon.md, 다른 모든 팔레트는 references/palettes.md에 있습니다.
의미론적 역할 (계약)
UI 팔레트는 이러한 역할을 채웁니다. 의도를 역할에 매핑한 다음 역할을 16진수에 매핑하세요.
| 역할 | 설명 |
|---|---|
background | 앱/페이지 기본 캔버스 |
surface | 카드, 패널, 시트 |
surface-elevated | 올라간 표면 (팝오버, 모달); 다크 모드에서는 더 밝을수록 더 높음 |
border | 구분선, 입력 테두리, 포커스 링 |
text-primary | 높은 강조 전경 |
text-secondary | 흐릿한 레이블, 힌트, 캡션 |
primary / primary-hover | 브랜드 액션 색상 + 호버 상태 |
accent | 보조 강조, 기본과 구별됨 |
success / warning / error / info | 의미론적 상태 (서양 관례상 초록 / 호박색 / 빨강 / 파랑) |
각 색상 역할은 트라이어드가 필요합니다. 하나의 16진수로 세 가지 작업을 수행할 수 없기 때문입니다. 위에 앉도록 작성된 값이 텍스트로 자동으로 읽기 쉬운 것은 아니며, 단색 채우기는 테이블 밀도의 배지 배경으로 너무 큽니다.
| 토큰 | 작업 | Bootstrap 5.3에서의 명칭 | Material 3에서의 명칭 |
|---|---|---|---|
{c}-fill + {c}-on-fill | 버튼, 활성 칩 | --bs-{c} + color-contrast() | primary + on-primary |
{c}-subtle + {c}-emphasis | 배지 / 콜아웃 배경 + 레이블 | --bs-{c}-bg-subtle + -text-emphasis | primary-container + on-primary-container |
{c}-subtle-border | 해당 배경 주변 테두리 | --bs-{c}-border-subtle | — |
link | surface 위의 텍스트인 브랜드 색상 | (v6에서 분할) | — |
Carbon의 트라이어드는 carbon.md에 있고, 나머지 9개 UI 팔레트의 기성 트라이어드는 palettes.md에 있습니다. 다크 모드 채우기는 밝은 색상이므로 레이블은 흰색이 아니라 팔레트의 가장 어두운 중성색입니다.
데이터 시각화 팔레트는 대신 순서가 지정된 색상 목록을 제공합니다 (범주형 = 고유한 시리즈; 순차형 = 낮음→높음 경사; 발산형 = 중립 중간점을 가진 따뜻함↔차가움). TUI 구성표는 16개의 ANSI 슬롯과 4개의 특수 역할을 제공합니다.
핵심 개념
- HSL이 아닌 OKLCH로 설계하세요. OKLCH는 지각적으로 균일합니다. HSL "명도"는 거짓말을 합니다 (동일 L의 파란색은 동일 L의 노란색보다 훨씬 어둡게 보임). 따라서 HSL 단계조차 고르지 않은 스케일을 생성합니다.
- 하모니: 구성표를 선택하고 (단색 / 유사 / 보색 / 삼색…) 하나의 색상이 채도와 면적에서 지배하도록 하고, 나머지는 채도를 낮추세요.
- 스케일: 10-12단계, 단계 명도를 균등하게 하고, 중간 범위에서 최고 채도를 유지하며 극단에서는 테이퍼링하여 틴트가 바래지 않고 셰이드가 탁해지지 않도록 하세요.
- 대비: WCAG AA — 본문 텍스트 ≥ 4.5:1, 큰 텍스트 및 UI/테두리 ≥ 3:1.
- 밝음과 어두움은 반전이 아니며, WCAG 2 비율은 검정색 근처에서 대비를 과장합니다. 두 가지 실패 모드와 수정 방법은 아래 주의 사항에 있습니다. 임계값 및 APCA 절차는 references/contrast.md에 있습니다.
- 색맹 안전성: 남성의 약 8%가 색상만으로 구분할 수 없으므로, 색상 외에도 텍스트, 아이콘 또는 위치로 의미를 인코딩하세요. 발산형 데이터에는 빨강↔초록 대신 따뜻함↔차가움 (파랑/주황, 청록/장미)을 사용하세요.
예시
예시: SaaS 대시보드 색상 선택
✅ 권장
사용자: "관리자 대시보드용 색상이 필요해요, 밝은 것과 어두운 것."
→ Carbon을 추천합니다 (짙은 슬레이트 블루, 다크 퍼스트, 밀도 높은 데이터 UI용으로 제작) — 기본값;
밝은 모드 동등성을 직접 조정하는 것이 대시보드 키트보다 더 중요하다면 Graphite를 제안합니다.
→ carbon.md에서 역할→16진수 표를 복사합니다 (두 모드 모두).
→ 역할별로 적용합니다: background→surface→border→text, 주요 CTA에는 primary,
상태 배지에는 success/warning/error. background에 대한 text-primary가 ≥ 4.5:1인지 확인합니다.
❌ 안티 패턴
→ Coolors 팔레트에서 네 가지 색상을 선택하고 임시로 할당합니다: #2b2d42 nav, #8d99ae text,
#edf2f4 background, #ef233c buttons. 다크 모드 = 16진수 반전.
작동 이유: 역할에 매핑된 팔레트는 CSS 변수에 바로 적용할 수 있으며 구조적으로 접근 가능합니다. 임시 버전에는 중립 경사, 고도 계층, 상태 색상이 없으며, 밝은 팔레트를 반전하면 순수 검정색 표면과 바랜 브랜드 색상이 생성됩니다 (주의 사항: 밝음과 어두움은 반전이 아님 참조).
예시: 상태 배지 색상
✅ 권장
.badge-error { background: var(--error); color: #fff; } /* 역할, 하드코딩된 빨간색이 아님 */
❌ 안티 패턴
.badge-error { background: #ff0000; color: #000; } /* 원시 색상; #f00 on #000 ≈ 5.2:1이지만 눈부심이 있고,
테마를 적용하거나 다크 모드로 전환할 수 없음 */
실패 이유: 색상을 하드코딩하면 테마 지정 및 다크 모드가 깨지고, 순수 빨강/순수 검정은 후광 현상을 유발합니다.
예시: 차트 팔레트 선택
✅ 권장
범주형 시리즈 (≤8) → Lunar Valley (기본값), 또는 CVD 안전이 필요한 경우 Okabe-Ito.
연속형 낮음→높음 → Viridis (지각적으로 균일, 색맹 안전).
중간점이 있는 부호 데이터 → Console & Window (따뜻함↔차가움, 중립 중심).
약 8개의 범주형 색상을 넘으면 시리즈를 구분할 수 없습니다 — 대신 "기타"로 집계하세요.
❌ 안티 패턴
UI 팔레트의 success/warning/error/info 역할과 브랜드 틴트에서 12개의 범주형 시리즈 색상을 가져옴; 수익/손실을 레이블 없이 초록↔빨강으로 인코딩.
작동 이유: 데이터 구조를 올바른 팔레트 제품군과 일치시키고 식별 가능성 제한을 존중합니다. 안티 패턴은 시리즈 정체성과 충돌하는 UI 상태 역할을 재사용하고, 약 8-색상 한계를 초과하며, 색맹 사용자를 위한 텍스트 또는 아이콘 백업 없이 빨강↔초록을 인코딩합니다.
주의 사항
- 증상: 브랜드 색상이 본문 텍스트로 읽을 수 없음. 원인: 채도가 높은 중간 톤 (호박색, 산호, 청록)은 종종 자체 배경에서 4.5:1을 실패합니다 — 채우기 색상과 텍스트 색상은 동일한 경사의 다른 단계입니다. 수정:
fill과link를 별도 값으로 유지하고, 텍스트를 통과할 때까지 한 단계 더 어둡게 만듭니다. 이 라이브러리에서 Evergreen light만 다릅니다 (#059669는 4.70:1의 버튼 레이블을 제공하지만 흰색 위의 링크로는 3.77:1에 도달하므로link는#00875b입니다). 이것이 바로 분할이 누락되는 이유입니다. - 증상: 상태 배지가 올바르게 보이지만 테이블 밀도에서 너무 큼. 원인: 흰색 텍스트 뒤의 단색
--error채우기는 버튼에는 적합하지만 행 수준 배지에는 너무 큽니다. 수정:{c}-subtle배경과 쌍을 이루는{c}-emphasis레이블을 사용하세요. 해당 색조에서 상태 색상을 자체 레이블로 재사용하면 4.5:1을 놓치는 경우가 많습니다 — 가정하지 말고 palettes.md (Carbon은 carbon.md)에서 쌍을 이루는 값을 가져오세요. - 증상: 12단계 스케일에서 생성된 팔레트가 여전히 대비에 실패함. 원인: 단계 맵은 대비를 보장하지 않습니다. Radix는 단계 11 및 12가 단계 2에 대해 보장하고 그 외에는 아무것도 보장하지 않습니다. 단계 9는 4.5:1 버튼 레이블을 거의 제공하지 않으며, 단계 8은 컨트롤 가장자리로 3:1에 거의 도달하지 않습니다. 수정: 실제 배경에 대해 이 두 가지를 해결하세요. 밝은 모드에서 흰색 레이블을 사용하고 채우기를 더 어둡게 만드세요 — 이미 더 높은 점수를 받은 레이블을 향해 해결하면 통과하지만 약해 보이는 창백한 워시가 생성됩니다.
- 증상: 밝은 모드에서 올바르게 보이는 팔레트가 어두운 모드에서 탁해 보임. 원인: 중성 색조가 한 번 선택되어 상속되었습니다. 높은 명도에서 종이로 읽히는 따뜻한 색상은 낮은 명도에서 갈색으로 읽힙니다. 수정: 모드별로 중성 색조와 채도를 다시 결정하세요. 매우 낮은 채도에서 차가워지는 것이 일반적인 해결책입니다. palettes.md의 Driftwood는 이렇게 합니다 (색조 64 밝음, 224 어두움); Meadow의 세이지는 필요하지 않았습니다.
- 증상: Color Hunt, Coolors 또는 트렌드 기사에서 복사한 팔레트로 인터페이스를 구축할 수 없음. 원인: 갤러리 팔레트는 중립 경사, 어두운 잉크 및 상태가 없는 4개의 장식용 색상입니다 — 가장 좋아하는 Color Hunt 팔레트 30개 중 16개는 해당 색상의 어떤 쌍으로도 4.5:1 본문 텍스트를 제공할 수 없습니다. 수정: 색상을 시드 재료로 가져와서 스케일을 구축하세요 (build-your-own.md); Dusk, Driftwood 및 Meadow는 이렇게 만들어졌습니다.
- 증상: 보조/흐릿한 텍스트 ("dimmed",
text-secondary)가 디자인 도구에서는 괜찮아 보이지만 앱에서 대비에 실패함. 원인: 컴포넌트 라이브러리는 대비가 아닌 시각적 계층 구조에 맞게 조정된 기본 흐릿한 텍스트 색상 (예: Mantine의dimmed)을 제공합니다. 일반적으로 약 ~3.4:1로, 4.5:1 AA 기준선보다 훨씬 낮습니다. 수정: 라이브러리 기본값을 상속하는 대신 contrast.md에 대해 자신의text-secondary16진수를 선택하고 확인하고, 테마별로 다시 확인하세요 — 동일한 재정의가 한 테마에서는 통과하고 다른 테마에서는 실패할 수 있습니다. 평평한 캔버스뿐만 아니라 색조가 있는/올라간 표면 (카드, 줄무늬 행)에서도 다시 확인하세요. - 증상: 다크 모드가 "WCAG를 통과"하지만 읽기 어려움. 원인: WCAG 2 수학은 검정색 근처에서 대비를 과장합니다. 수정: 4.5:1 비율만 사용하지 말고 APCA (Lc)로 어두운 쌍을 다시 확인하세요.
- 증상: 어두운 테마가 평평해 보이고, 고도를 읽을 수 없음. 원인: 순수
#000배경과 동일 명도의 표면. 수정: 베이스를 약#0d1117–#1e1e2e로 올리고 각 고도 계층을 더 밝게 만드세요. - 증상: 색맹 사용자에게 차트를 읽을 수 없음. 원인: 빨강↔초록 인코딩 또는 색상 전용 의미. 수정: 따뜻함↔차가움 발산 팔레트로 전환하고 레이블/아이콘을 추가하세요. 범주형의 경우 Okabe-Ito 안전 세트 (palettes.md)를 사용하세요.
- 증상: 팔레트가 올바른 텍스트 색상을 정의하더라도 차트 텍스트가 낮은 대비를 유지함. 원인: 차트 라이브러리 (Recharts, Mantine charts)는 축/범례/값 텍스트를 자체 인라인
fill이 있는 SVG로 렌더링하여 색상 토큰을 우회합니다. 수정: 라이브러리의 텍스트 요소를 직접 타겟팅하세요 (예:.recharts-wrapper text { fill: var(--text) }) — CSS 캐스케이드가 거기에 도달하지 않습니다. - 증상: TUI 색상이 일부 터미널에서 사라짐. 원인: 하드코딩된 16진수, 또는 밝은 검정색 (슬롯 8)에 배치된 중요한 텍스트. 수정: ANSI 슬롯 1-6에 의미를 바인딩하여 사용자 자신의 테마가 렌더링하도록 하고, 슬롯 8은 비강조용으로만 유지하세요.
- 증상: 팔레트 단계가 고르지 않음/울퉁불퉁함. 원인: HSL/RGB에서 명도 단계를 설정합니다. 수정: OKLCH에서 스케일을 재구축하세요 (build-your-own.md 참조).
- 증상: 밝은 모드/다크 모드 전환이 색상 값을 뒤집습니다. 원인: 일반적인 실수입니다. 수정: 조명이 어두워지면 배경, 표면 및 테두리는 더 어두워져야 하지만 텍스트, 아이콘 및 경계선은 더 밝아져야 합니다. 테두리/제어 윤곽보다 배경에서 한 단계 더 떨어진 서로 다른 방향으로 이동합니다. 위의 역할 표를 따르고 반전하지 마세요.
참조 파일
- references/carbon.md — Carbon Design System 색상 (역할, 대시보드 키트, 트라이어드, 두 모드)
- references/palettes.md — 모든 기성 팔레트 (UI, 마케팅, 데이터 시각화, TUI) 전체 16진수 표 및 트라이어드
- references/contrast.md — WCAG 2.1/APCA 대비 임계값, 색맹 안전 점검 시트
- references/build-your-own.md — OKLCH 스케일 생성 레시피
- references/theory.md — 하모니, 색상 공간 선택 및 디자인 원칙
실행 참고 사항: 사용자가 작업을 설명하면, 먼저 이 문서의 색인을 사용하여 적절한 팔레트 제품군 (UI / 마케팅 / 데이터 시각화 / TUI)을 식별한 다음, 필요한 참조 파일 하나를 로드하세요. 항상 역할로 적용하세요 (의도 → 의미론적 역할 → 16진수). 두 개의 16진수 쌍이 의심스러운 경우 contrast.md를 확인하세요. 새 스케일이 필요한 경우 build-your-own.md를 참조하세요.