← 모든 글

인터페이스 디자이너를 위한 색채 과학: 무채색 사이트를 만들며 배운 것들

W3C 웹 콘텐츠 접근성 지침은 일반 텍스트에 대해 최소 4.5:1의 명암비를 요구하지만, 2023년 WebAIM 조사에 따르면 상위 백만 개 웹사이트 중 83.6%가 홈페이지에서 WCAG 2 명암비 위반을 보였습니다. 저는 blakecrosley.com을 정반대의 접근 방식으로 구축했습니다: 모든 곳에서 최대 명암비(21:1)를 적용한 후, 선택적으로 낮추는 방식입니다.1

TL;DR

저는 개인 사이트를 브랜드 색상 없이 디자인했습니다. 전체 시각적 계층 구조는 절대 검정(#000000) 위의 흰색 텍스트로, 네 가지 불투명도 단계(100%, 65%, 40%, 10%)를 통해 운영됩니다. 이 결정 덕분에 지각적 색채 과학을 깊이 공부하게 되었습니다 — sRGB가 왜 균일한 간격에 대해 거짓말을 하는지, OKLCH가 이를 어떻게 해결하는지, 그리고 다크 모드가 왜 라이트 모드와 다른 명암 관계를 필요로 하는지를 배웠습니다. 아래의 인터랙티브 도구를 통해 명암비와 색 공간 차이를 직접 탐색할 수 있습니다. 핵심 교훈은 다음과 같습니다: 색채 인지의 과학을 이해하면 미적 직관보다 더 나은 디자인 결정을 내릴 수 있습니다.



나의 무채색 팔레트

대부분의 디자인 시스템은 색상 팔레트에서 시작합니다. 제 시스템은 색상 팔레트의 부재에서 시작합니다:

:root {
  --color-bg-dark:        #000000;
  --color-bg-elevated:    #111111;
  --color-bg-surface:     #1a1a1a;
  --color-text-primary:   #ffffff;
  --color-text-secondary: rgba(255,255,255,0.65);
  --color-text-tertiary:  rgba(255,255,255,0.4);
  --color-border:         rgba(255,255,255,0.1);
  --color-border-subtle:  rgba(255,255,255,0.05);
  --color-accent:         #ffffff;
}

토큰 10개. 브랜드 색상 없음. 시맨틱 에러/성공/경고 팔레트 없음. 전체 시각적 계층 구조는 네 가지 투명도 단계를 통해 운영됩니다.2

네 가지 단계가 효과적인 이유

각 단계는 특정한 커뮤니케이션 기능을 담당합니다:

단계 불투명도 CSS 토큰 기능 WCAG 비율 (#000 기준)
Primary 100% --color-text-primary 헤드라인, 본문, 핵심 콘텐츠 21:1 (AAA)
Secondary 65% --color-text-secondary 부제목, 내비게이션, 메타데이터 13.7:1 (AAA)
Tertiary 40% --color-text-tertiary 타임스탬프, 보조 텍스트, 비활성 상태 8.4:1 (AAA)
Structural 10% --color-border 테두리, 구분선, 배경 분리 N/A (비텍스트)

모든 텍스트 단계가 WCAG AAA(7:1) 기준을 통과합니다. 40% 불투명도의 Tertiary 단계는 8.4:1 비율을 산출하며, 이는 AA 최소 기준인 4.5:1의 거의 두 배에 해당합니다. 절대 검정(#0a0a0a#1a1a1a가 아닌 #000000)이라는 브루탈리스트적 선택이 모든 텍스트 단계에 최대한의 여유 공간을 제공합니다.3

--spacing-2xs 사건

엄격한 디자인 토큰의 가치를 깨달은 것은 부제목 마진에 --spacing-2xs를 사용했을 때였습니다. 해당 토큰은 :root 정의에 존재하지 않았습니다. CSS는 조용히 실패했고, 레이아웃이 깨졌으며, 컴파일 타임 에러로 잡혔어야 할 간격 문제를 디버깅하는 데 20분을 소비했습니다. 해결책은 --spacing-xs(제가 정의한 가장 작은 토큰)로 변경하는 것이었습니다. 교훈: 시스템에 존재하지 않는 값이라면, 디자인이 잘못된 것이지 시스템이 잘못된 것이 아닙니다.4


sRGB가 디자이너를 속이는 이유

지각적 비균일성 문제

sRGB(웹의 표준 색 공간)는 각 축(빨강, 초록, 파랑)이 0-255 범위인 큐브에 색상을 매핑합니다. 빨강 채널에서 50 단위를 이동하는 것은 초록 채널에서 50 단위를 이동하는 것과 동일한 지각적 변화를 만들지 않습니다. 인간의 눈은 빨강이나 파랑보다 초록에 민감한 원추세포를 더 많이 가지고 있어, 초록 변화가 동일한 빨강 변화보다 더 뚜렷하게 인지됩니다.5

실질적인 결과는 이렇습니다: 16진수 값을 균등하게 배치하여 색상 팔레트를 만드는 디자이너는 실제로 불균등하게 보이는 색상을 만들게 됩니다. #000000#FFFFFF 사이의 “중간” 회색은 수학적 중간점인 #808080이 아니라 지각적 중간점인 약 #777777입니다. 인간의 밝기 인지가 선형 함수가 아닌 거듭제곱 법칙을 따르기 때문입니다.6

제 사이트는 이 문제를 완전히 우회합니다. 다양한 불투명도의 흰색만 사용함으로써 sRGB 균일성 함정을 피합니다. 불투명도는 검정 배경에 대한 인지적 투명도와 선형적으로 비례하는데, 이는 sRGB 색상 혼합에는 해당되지 않는 특성입니다.

OKLCH 해결책

OKLCH(Oklab 명도, 채도, 색조)는 동일한 수학적 거리가 동일한 인지적 차이에 대응하는 지각적으로 균일한 색 공간입니다. 10 단위의 명도 변화는 시작 색상에 관계없이 항상 동일한 양의 변화로 보입니다.7

/* sRGB: mathematically even, perceptually uneven */
--gray-100: #f5f5f5;
--gray-200: #e5e5e5;
--gray-300: #d4d4d4;

/* OKLCH: perceptually even steps */
--gray-100: oklch(96% 0 0);
--gray-200: oklch(88% 0 0);
--gray-300: oklch(80% 0 0);

최신 CSS는 oklch()를 네이티브로 지원합니다. 색상 팔레트가 필요한 다음 프로젝트에서는 OKLCH로 팔레트를 정의할 것입니다. 현재 사이트에서는 불투명도 기반 시스템이 다른 방식으로 동일한 지각적 균일성을 달성하고 있습니다.


나의 다크 모드 결정: 라이트 모드 없음

제 사이트에는 prefers-color-scheme 미디어 쿼리가 없습니다. 다크 모드에서만 운영됩니다. 이는 의도적인 결정이었습니다.8

이중 모드를 지지하는 주장: 사용자는 라이트 모드 옵션을 기대합니다. 시스템 환경설정 통합은 사용자의 선택을 존중하는 것입니다.

반대 주장 (제가 선택한 방향): 두 개의 시각 시스템을 유지하면 필연적으로 두 시스템 모두 타협하게 됩니다. 검정 위에서 65% 불투명도로 작동하는 디자인은 흰색 위에서 동일한 지각적 무게를 달성하려면 다른 불투명도(약 45%에 가까운)가 필요합니다. 모든 인터랙션 상태, 모든 테두리, 모든 그림자를 다시 보정해야 합니다. 저는 두 개의 시스템을 적당히 만드는 것보다 하나의 시스템을 잘 디자인하는 것을 선택했습니다.

절대 검정 배경(#000000)은 모든 텍스트 단계에 사용 가능한 명암비를 극대화합니다:

/* My actual typography contrast hierarchy */
.hero__title     { color: var(--color-text-primary); }   /* 21:1 */
.hero__subtitle  { color: var(--color-text-secondary); }  /* 13.7:1 */
.nav a           { color: var(--color-text-secondary); }  /* 13.7:1 */
.nav a:hover     { color: var(--color-text-primary); }    /* 21:1 */

호버 상태 전환(secondary → primary)은 명암비 변화만으로 기능적 피드백을 제공합니다 — 색상 변화가 필요하지 않습니다.


명암비와 가독성

WCAG 명암비 요구사항

수준 일반 텍스트 (< 18pt) 큰 텍스트 (≥ 18pt 또는 14pt 굵게)
AA 4.5:1 3:1
AAA 7:1 4.5:1

명암비는 전경색과 배경색 사이의 상대적 휘도 차이를 측정합니다. 1:1 비율은 명암이 없는 상태(동일한 색상)를 의미합니다. 21:1 비율은 최대 명암(검정 위의 흰색 또는 흰색 위의 검정)을 의미합니다.9

WCAG를 넘어서: APCA

WCAG 2 명암비 알고리즘에는 알려진 한계가 있습니다. 이 알고리즘은 극성(어두운 배경 위 밝은 텍스트 vs. 밝은 배경 위 어두운 텍스트)에 관계없이 모든 색상을 동일하게 취급하지만, 연구에 따르면 인간의 명암 인지는 두 모드 사이에서 상당히 다릅니다.10

APCA(Accessible Perceptual Contrast Algorithm)는 다음을 고려하여 이러한 한계를 해결합니다: - 극성 민감도: 밝은 배경 위의 어두운 텍스트는 동일한 수학적 명암비에서 어두운 배경 위의 밝은 텍스트보다 더 읽기 쉽습니다 - 공간 주파수: 얇은 폰트는 동일한 크기에서 굵은 폰트보다 더 높은 명암비를 요구합니다 - 적응: 눈은 주변 페이지의 휘도에 적응하여 인지되는 명암비에 영향을 줍니다

APCA는 WCAG 3.0 명암비 요구사항의 기반이 될 것으로 예상됩니다. 제 사이트는 극성에 관한 통찰의 혜택을 받습니다: 밝은 텍스트-어두운 배경 조합만 사용하므로, 라이트 모드 사이트보다 더 높은 명암비가 필요합니다. 가장 낮은 텍스트 단계(40% 불투명도, 8.4:1 비율)는 어두운 배경에서의 본문 텍스트에 대한 APCA 권장 최소값도 초과합니다.


색상 없는 시맨틱 컬러

프로덕션 색상 시스템은 일반적으로 기능에 색상을 할당합니다(성공은 초록, 에러는 빨강). 제 사이트는 트랜잭션 UI가 없기 때문에 기능적 색상을 완전히 배제합니다 — 폼, 상태 메시지, 성공/에러 상태가 없습니다. 콘텐츠는 정적입니다.

시맨틱 컬러가 필요하다면, 외과적으로 추가할 것입니다:

기능 일반적인 접근 방식 가설적 접근 방식
성공 초록색 흰색 텍스트 + 체크 아이콘
에러 빨간색 흰색 텍스트 + X 아이콘 + 테두리 강조
경고 황색 흰색 텍스트 + 느낌표 아이콘

아이콘과 텍스트를 함께 사용하면, 남성의 약 8%가 가진 색각 이상에서 실패하는 색상 전용 커뮤니케이션을 제거할 수 있습니다. 이 접근 방식은 또한 단색 시스템을 유지합니다. 색상은 구조적 요소가 아닌 악센트 역할을 하게 됩니다.11


타이포그래피 우선 계층 구조

색상이 계층을 담당하지 않으므로, 제 사이트에서는 타이포그래피가 모든 것을 담당합니다:

:root {
  --font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text",
                 "SF Pro Display", "Helvetica Neue", Arial, sans-serif;
  --font-size-display: 5rem;     /* 80px — hero headlines */
  --font-size-7xl:     3.875rem; /* 62px */
  --font-size-base:    1rem;     /* 16px — body text */
  --font-size-xs:      0.75rem;  /* 12px — metadata */
}

커스텀 웹 폰트가 아닌 시스템 폰트를 사용합니다. 이는 브루탈리스트적 결정(플랫폼의 네이티브 재료를 사용)이자 성능적 결정(폰트 로딩 지연 제로, Lighthouse 100점 만점에 기여)입니다. 디스플레이 크기(80px)에 촘촘한 자간(-0.03em)을 적용하여 장식 없이 헤드라인에 무게감을 부여합니다. 16px 본문 텍스트에 넉넉한 줄 높이(1.7)를 적용하여 밀도보다 가독성을 우선합니다.12

0.75rem에서 5rem까지의 13단계 타입 스케일은 크기만으로 계층을 표현하기에 충분한 세분성을 제공합니다. 네 가지 불투명도 단계와 결합하면 52가지의 가능한 조합(13가지 크기 × 4가지 불투명도)을 갖게 되며, 이는 색상에 의존하지 않고도 어떤 콘텐츠 계층이든 표현하기에 충분합니다.


핵심 교훈

디자이너를 위한 조언: - 색상 팔레트는 sRGB가 아닌 OKLCH로 정의하세요; 지각적으로 균일한 색 공간은 예측 가능한 계층 구조와 팔레트 전체에 걸쳐 일관된 명암비를 제공합니다 - 보조 텍스트 단계를 AA(4.5:1)가 아닌 WCAG AAA(7:1) 기준으로 테스트하세요; AAA 기준은 실제 화면 조건(낮은 밝기, 눈부심, 노후된 디스플레이)에서 충분한 여유 공간을 제공합니다 - 프로젝트에 실제로 색상이 필요한지 고려하세요; 제 사이트는 타이포그래피와 불투명도만으로 완전한 시각적 계층 구조를 구현할 수 있음을 증명합니다

개발자를 위한 조언: - CSS oklch()로 색상을 정의하고 WCAG 2(현행 표준)와 APCA(차기 표준) 모두에서 명암비를 테스트하세요; oklch()의 브라우저 지원은 모든 최신 브라우저에서 가능합니다 - 다크 모드 구현 시 16진수 값을 반전하는 대신 OKLCH 공간에서 명도와 채도를 조정하세요; 지각적 조정이 수학적 반전보다 더 나은 결과를 만듭니다 - 엄격한 디자인 토큰 적용은 CSS의 조용한 실패를 방지합니다; 토큰이 존재하지 않는다면, 토큰 시스템이 아닌 디자인이 변경되어야 합니다


참고 문헌


  1. WebAIM, “The WebAIM Million: 2023 Accessibility Analysis,” 2023. 

  2. 저자의 critical.css CSS 커스텀 속성. 10개의 색상 토큰, 모두 흰색-검정 불투명도 관계에서 파생. 

  3. 저자의 WCAG 명암비 계산. Primary(21:1), Secondary(13.7:1), Tertiary(8.4:1), 모두 AAA 최소 기준 7:1 초과. 

  4. 저자의 디버깅 경험. --spacing-2xs를 사용했으나 :root에 정의되지 않았음. MEMORY.md 에러 항목에 기록. 

  5. Hunt, R.W.G., The Reproduction of Colour, Wiley, 2004. 

  6. Poynton, Charles, Digital Video and HD, Morgan Kaufmann, 2012. 감마 보정과 지각적 선형성. 

  7. Ottosson, Bjorn, “A perceptual color space for image processing,” 2020. OKLCH 사양. 

  8. 저자의 디자인 결정. 단일 다크 모드는 병렬 라이트/다크 시스템 유지에 내재된 시각적 타협을 방지. 

  9. W3C, “Web Content Accessibility Guidelines (WCAG) 2.1,” 2018. 

  10. Somers, Andrew, “APCA Contrast Calculator,” 2023. 

  11. W3C, “WCAG 2.1 Success Criterion 1.4.1: Use of Color,” 2018. 

  12. 저자의 타이포그래피 시스템. 0.75rem(12px)에서 5rem(80px)까지의 13단계 폰트 스케일. 시스템 폰트 스택으로 FOIT/FOUT 제거.