9장 컬러 모델
Leysys의 색은 손으로 고르지 않고 OKLCH에서 공식으로 만들며, 모든 색이 같은 11단계 명도를 공유합니다. 공식은 수학 검증을 통과하지만 대비 기준과 부딪히는 지점이 있고, 색의 강도와 형태는 서로 다른 어휘로 부릅니다.
왜 필요한가
팔레트를 눈으로 고르면 새 색을 더하거나 한 단계를 고칠 때 근거가 없습니다. 같은 「500」이라도 색마다 밝기가 제각각이면 단계 이름에 기대는 규칙도 세우기 어렵습니다.
Leysys는 색을 공식에서 도출합니다. 입력은 기준 색상각 셋과 명도 범위·기본 간격 같은 몇 개의 상수뿐이고, 정본은 이 모델을 「다른 입력 없음, 참조표 없음, 손으로 고친 예외 없음」으로 요약합니다. 공식을 알면 사람도 AI도 같은 값에 도착합니다.
모델
OKLCH와 세 영역
색은 OKLCH 색공간으로 표현합니다. L은 명도, C는 채도, H는 색상각입니다. OKLCH는 지각적으로 균일한(perceptually uniform) 색공간이라, 모든 색에 같은 명도 단계를 적용하는 이 모델의 바탕이 됩니다. 색역 기준은 sRGB가 아니라 Display P3입니다. 색은 세 영역(domain)으로 나눕니다.
| 영역 | 정의 | 변수 예 |
|---|---|---|
| 유채색 (chromatic) | 아래 채도 모델로 만든 색 | --e-palette-color-blue-500 |
| 틴트 무채색 (tinted achromatic) | 같은 색상각, 채도는 유채색의 정확히 20% | --e-palette-color-blue-gray-500 |
| 순수 무채색 (pure achromatic) | 채도 0 | --e-palette-color-pure-gray-500 |
EDS의 기본 회색이 바로 파랑의 틴트 무채색(blue-gray)입니다.
공유 명도 스케일
모든 색은 같은 11개 명도를 씁니다. 단계 이름은 Tailwind와 같은 950(가장 어두움)~50(가장 밝음)입니다.
text
L(0) = 21.40% (950 단계)
L(i) = L(i−1) + SB + SA × sin(π × i / 11)
SB = 3.50 (기본 간격)
SA ≈ 5.981 = (98.00 − 21.40 − 10 × SB) / Σ sin(πk/11), k = 1..10| 단계 | 950 | 900 | 800 | 700 | 600 | 500 | 400 | 300 | 200 | 100 | 50 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| L (%) | 21.40 | 26.59 | 33.32 | 41.34 | 50.28 | 59.70 | 69.12 | 78.06 | 86.08 | 92.81 | 98.00 |
- 단계 간격이 좌우 대칭입니다. 5.19 · 6.73 · 8.02 · 8.94 · 9.42 | 9.42 · 8.94 · 8.02 · 6.73 · 5.19로, 양 끝은 촘촘하고 가운데는 넓습니다.
- 500은 정확히 양 끝의 중간입니다. (21.40 + 98.00) / 2 = 59.70.
- 기준 파랑의 색상각 258°는 sRGB 색역 경계의 채도 정점이 이 500 명도 근처에 오도록 고른 각도입니다. 그래서 밝기의 가운데와 채도의 정점이 겹칩니다.
채도
채도는 파랑의 곡선 하나에서 모든 색으로 퍼집니다.
- 각 단계 명도에서 파랑이 sRGB 안에서 낼 수 있는 최대 채도를 구하고, 500에서 1이 되도록 나눕니다. 이 곡선은 밝은 쪽에서 가파르게 떨어져 형광 느낌을 억제합니다.
- 500의 목표 채도는 파랑의 Display P3 최대값(약 0.2376)입니다. 각 색은 이 목표와 자기 P3 한계 중 작은 값을 정점으로 씁니다.
- 단계별 채도는 「정점 × 곡선 비율」입니다. 목표에 닿는 선명한 색(vivid)은 그대로 쓰고, 닿지 못하는 색은 단계마다 자기 P3 한계로 자릅니다. 어느 색이 선명한지는 이 계산으로 정해집니다.
그래서 모든 색의 채도가 정확히 500에서 정점에 이르고, 어느 단계에서도 색 사이의 채도 순위가 뒤바뀌지 않습니다. 색상각은 반대색 이론의 고유 색상에서 고른 빨강 25°, 초록 150°, 파랑 258° 세 기준점 사이를 보간해 정합니다.
17개 색은 Tailwind 색 이름과 같다
생성기는 24개 색상각을 계산하고, Leysys 팔레트는 그중 17개를 씁니다. red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose로, Tailwind의 색 이름과 1:1입니다. 사람과 AI가 이미 아는 이름이라 새로 배울 것이 없습니다. 나머지 7개는 생성기에 남겨 두었습니다. 팔레트 변수는 (17 + 17 + 1) × 11단계에 흰색·검정·투명을 더해 388개입니다.
검증
모델에는 여섯 묶음의 자동 점검표가 있습니다. 2026-09-28 KST에는 모델을 처음부터 다시 도출해 팔레트 CSS의 385개 값과 비교했고, 명도와 채도 차이는 0건이었습니다.
대비와 접근성
같은 재검증은 불편한 사실도 확인했습니다. 500 단계와 흰색의 대비가 WCAG AA 글자 기준(4.5:1)을 통과하는 색은 17개 중 red, fuchsia, pink, rose 4개뿐이었습니다. 주색 blue는 4.15:1, green은 3.63:1입니다.
원인은 두 겹입니다.
- 명도축이 휘도가 아닙니다. WCAG 2의 대비는 상대 휘도 Y로 계산하고, 모델의 명도축은 지각 명도 L입니다. L이 같아도 색에 따라 Y가 달라, 500 단계의 흰색 대비는 3.63에서 4.55까지 벌어집니다.
- 500이 WCAG 중간점보다 밝습니다. 흰색과 4.5:1을 내려면 무채색 기준으로 L이 약 56.8% 이하여야 합니다. 500은 59.70%라, 500을 흰 글자를 올리는 면과 흰 배경 위 글자에 함께 쓰는 한 미달이 구조적으로 생깁니다.
대비를 기준으로 명도축을 다시 짜는 대안도 계산했습니다. 그 안은 17개 색 모두 500에서 AA를 통과하지만, 같은 단계의 색은 같은 OKLab 명도를 갖고 지각 간격이 대칭이라는 현재 모델의 공리를 포기해야 했습니다. 2026-09-28 KST 결정은 다음과 같습니다.
- 모델, 팔레트 값, EDS·MDS의 시맨틱 연결을 그대로 둡니다.
- 대비 미달은 차단 사유가 아니라 알림으로 관리합니다. EDS 시맨틱 조합 대비표(
semantic-contrast.json)에서 라이트 모드 112쌍 중 AA를 통과하는 쌍은 20쌍입니다. - 공개 문서와 패키지 README에 「기본 테마는 모든 조합에서 WCAG 2.2 AA 대비를 보장하지 않습니다」라고 적습니다.
- 접근성 인증이 필요한 제품은 제품에서 대응합니다. 강조 글자와 흰 글자를 올리는 면을 600 단계에 연결하면 17개 색 모두 흰색 대비 5.17:1 이상입니다.
흰 배경 기준의 보수적 규칙은 CDS의 color-accessibility.json에 있습니다. 글자 AA는 600 이상, UI 요소 (3:1)는 500 이상, AAA는 700 이상입니다.
강도 어휘와 형태 어휘
EDS 강도 다섯 단계
EDS는 색의 강도(weight)를 다섯 단어로 부릅니다.
text
minimal < subtle < moderate < bold < maximalmaximal은 그 토큰 묶음이 가진 최상위 단계라는 뜻입니다. 모든 컴포넌트가 다섯 단계를 갖지 않고 필요한 연속 구간만 씁니다. Button은 아래 넷, 중립 테두리는 다섯 모두, Input과 Tabs의 선형(line) 모양은 위 셋을 씁니다. 쓰지 않는 단계의 빈 토큰은 만들지 않습니다.
형태 일곱 가지와 Button의 두 갈래
형태(form)는 강도가 아니라 모양의 처방입니다. solid, soft, surface, outline, dashed, ghost, link 일곱 가지이며 순서가 있는 척도가 아닙니다. EDS Button은 두 어휘를 모두 갖지만 한 버튼에서는 하나만 씁니다.
| 갈래 | 색 | 변형 | 예 |
|---|---|---|---|
| 역할 갈래 | color: primary, secondary, tertiary, destructive, neutral | 강도 4단계 | e-button-primary-bold |
| 직접 색 갈래 | hue: 17개 색과 gray | 형태 7가지 | e-button-blue-solid |
primary-solid나 blue-bold는 정의되지 않은 조합입니다. 강도 단어는 이미 모양을 품고 있습니다(bold는 채움, subtle은 테두리, minimal은 고스트). 역할 갈래는 「왜 이 버튼이 있는가」를, 직접 색 갈래는 「어떤 색과 모양이 필요한가」를 말합니다. 섞으면 같은 것을 두 번 표현하고, 있을 법한 조합을 추정해 정의되지 않은 클래스를 만들게 됩니다. 그래서 타입으로 막습니다.
ts
type EButtonColorContract =
| { color?: EButtonActionColor; hue?: never; variant?: EButtonWeightVariant }
| { color?: never; hue: EButtonHueColor; variant?: EButtonFormVariant };공개 속성 이름은 두 갈래 모두 variant입니다. shadcn/ui, Nuxt UI, Ant Design, Primer, Radix Themes의 공식 Button 문서도 외형 선택을 variant로 노출합니다. form이라는 속성은 만들지 않습니다. form은 <button>과 <input>을 바깥 폼에 연결하는 HTML 속성이라, 시각 속성으로 쓰면 그 기능을 끊을 수 있습니다.
대비 글자색은 문맥으로
어떤 면 위의 글자색인지는 문맥 어휘가 말해 줍니다. --e-button-primary-bold-text는 primary bold 버튼 위의 글자, --e-text-selected-bold는 선택된 진한 면 위의 글자입니다. 그래서 on- 접두를 쓰지 않습니다. fg(foreground)는 특정 면이 기본과 다른 전경색을 짝으로 가져야 할 때만 쓰고, text의 별칭으로 쓰지 않습니다.
MDS는 다른 체계
MDS는 Nuxt UI를 본뜬 별도 체계라 EDS 강도 사다리를 쓰지 않습니다. MDS Button은 역할 색 5개 × 형태 6가지(solid, outline, soft, surface, ghost, link)이며 주 버튼은 m-button-primary-solid입니다. MDS의 옛 subtle 형태는 EDS 강도의 subtle과 겹치지 않도록 surface로 바꿨습니다.
경계와 예외
- Print DS의 색은 이 모델이 아닙니다. Print DS는 Ant Design 계열 유채색과 순수 무채색을 쓰고, 단계 이름만 50~950으로 맞춥니다.
- 상태와 행동은 다른 색 타입입니다. 오류 상태는
error, 파괴적 행동은destructive입니다. 같은 빨강을 참조해도 서로 대신하지 않습니다. - 화면의 색은 근사값일 수 있습니다. 채택한 유채색 187개 중 83개는 sRGB 밖이라, sRGB 화면에서는 브라우저가 잘라 그립니다. 그래서 green-500의 흰색 대비는 3.63에서 3.43이 됩니다.
정리
- 색은 OKLCH에서 공식으로 만듭니다. 11단계 명도를 모든 색이 공유하고, 500은 정확히 양 끝의 중간인 59.70%입니다.
- 채도는 파랑의 sRGB 곡선 모양과 P3 정점에서 도출하며, 채택한 17개 색은 Tailwind 색 이름과 같습니다.
- 모델은 수학 검증을 통과하지만 500 단계의 WCAG 대비는 구조적으로 부족합니다. 이를 알림으로 관리하고, 인증이 필요하면 600 단계 연결로 대응합니다.
- EDS의 강도 다섯 단계와 형태 일곱 가지는 다른 축이며, Button 한 개에서는 둘 중 하나만 씁니다. MDS는 형태 축만 씁니다.
정본
leysys-designdocs/specs/COLOR-MODEL.md— 컬러 수학 모델, 상수, 검증 절차와 이력leysys-designdocs/specs/EDS.md「Color Model」, 「Button 스펙」 — EDS 적용과 Button 두 갈래(명도표는 옛 단계 이름 010~110을 씁니다. 010이 50, 060이 500, 110이 950입니다)leysys-designdocs/decisions/COLOR-MODEL-REV4-CONTRAST-ALERT-ONLY-2026-09-28.md— 대비 미달의 원인과 유지 결정leysys-designdocs/decisions/DS-3.0-SCOPE-AND-SUPPORT-POLICY-2026-09-28.md— 공개 문서·패키지 README의 대비 미보장 고지leysys-designdocs/decisions/WEIGHT-VOCABULARY-FIVE-TIER-2026-08-01.md— EDS 강도 다섯 단계leysys-designdocs/decisions/COMPONENT-VISUAL-AXIS-GOVERNANCE-2026-08-01.md—variant이름과 갈래 배타 규칙leysys-designdocs/decisions/BUTTON-SUPPLEMENT-UNIFICATION-2026-06-12.md— 형태 어휘와 단일 Buttonleysys-designdocs/decisions/MDS-SOLID-FILL-DARK-REPRESENTATIVE-2026-06-15.md—on-대신 문맥 어휘와fg사용 범위leysys-designdocs/specs/DS-GOTCHAS.md— 헷갈리기 쉬운 축과 어휘(outline·outlined등)