우리가 오랫동안 사용해온 HEX, RGB, HSL은 모니터를 위한 색상 모델입니다. 하지만 사람의 눈이 색을 인식하는 방식과는 차이가 있어서 "지각적으로 균일하지 않다"는 문제가 있습니다. OKLCH는 이 문제를 해결하는 현대적인 CSS 색상 함수입니다.

기존 색상 모델의 문제점

HSL은 색상(Hue), 채도(Saturation), 명도(Lightness)로 색을 표현합니다. 얼핏 직관적으로 보이지만, 실제로 동일한 L 값이라도 색조에 따라 밝기가 다르게 느껴집니다.

예를 들어 노란색 hsl(60, 100%, 50%)과 파란색 hsl(240, 100%, 50%)는 L값이 같아도 노란색이 훨씬 밝게 보입니다.

이런 불균일함은 버튼 hover 상태, 다크모드 색상 팔레트 설계 시 예측 불가능한 결과를 낳습니다.

OKLCH란?

OKLCH는 L(밝기, Lightness), C(채도, Chroma), H(색조, Hue) 세 가지 축으로 색을 표현합니다. OKLab 색상 공간을 기반으로 하며, 사람의 시각적 인식과 수학적 값의 변화가 일치하도록 설계되었습니다.

/* oklch(밝기 채도 색조) */
.button {
  background-color: oklch(65% 0.25 290); /* 보라색 계열 */
  color: oklch(99% 0 0);                 /* 거의 흰색 */
}
항목HSLOKLCH
지각 균일성❌ 낮음✅ 높음
밝기 예측성❌ 색조마다 다름✅ 항상 일관
다크모드 설계😓 어려움😊 쉬움
브라우저 지원✅ 전부✅ 모던 브라우저

다크모드 색상 시스템에 적용하기

OKLCH의 진가는 CSS 변수와 함께 쓸 때 드러납니다. L 값만 조정하면 자동으로 밝기가 일관되게 바뀝니다.

:root {
  --primary:    oklch(65% 0.25 290);
  --bg:         oklch(98% 0.01 240);
  --text:       oklch(25% 0.05 240);
  --surface:    oklch(99% 0.005 240);
}

[data-theme="dark"] {
  /* L 값만 뒤집으면 됩니다 */
  --primary:    oklch(70% 0.25 290);  /* 조금 더 밝게 */
  --bg:         oklch(15% 0.01 240);
  --text:       oklch(88% 0.03 240);
  --surface:    oklch(22% 0.01 240);
}

HSL로 같은 작업을 하면 각 색조별로 다른 L 값을 실험해가며 맞춰야 하지만, OKLCH는 수학적으로 균일하기 때문에 공식처럼 적용할 수 있습니다.

채도(Chroma) 다루기

OKLCH의 C(Chroma)는 색의 선명함을 나타냅니다. 0에 가까울수록 무채색, 높을수록 선명합니다. 단, 채도의 최대값은 색조마다 다릅니다 — 이 점이 HSL의 S와 다릅니다.

/* 같은 보라색 계열에서 채도 변화 */
.muted   { color: oklch(65% 0.05 290); } /* 흐린 보라 */
.normal  { color: oklch(65% 0.15 290); } /* 보통 보라 */
.vivid   { color: oklch(65% 0.30 290); } /* 선명한 보라 */

실전 팁: 색상 팔레트 한 줄로 만들기

OKLCH와 CSS calc()를 조합하면 반복 없는 팔레트를 만들 수 있습니다.

:root {
  --hue: 290;  /* 이것만 바꾸면 전체 팔레트 색조 변경 */

  --color-100: oklch(95% 0.05 var(--hue));
  --color-300: oklch(80% 0.15 var(--hue));
  --color-500: oklch(65% 0.25 var(--hue));
  --color-700: oklch(45% 0.20 var(--hue));
  --color-900: oklch(25% 0.10 var(--hue));
}
핵심 정리
OKLCH는 사람의 시각과 일치하는 지각 균일 색상 모델입니다. CSS 변수와 함께 사용하면 다크모드 설계, 팔레트 시스템 구축이 훨씬 예측 가능하고 쉬워집니다. 모던 브라우저는 모두 지원합니다.

브라우저 지원과 폴백 전략

OKLCH는 최신 브라우저에서 폭넓게 지원됩니다. 하지만 구형 브라우저를 지원해야 한다면 폴백 색상을 함께 선언해야 합니다.

브라우저OKLCH 지원버전
Chrome / Edge✅ 지원111+
Firefox✅ 지원113+
Safari✅ 지원15.4+
iOS Safari✅ 지원15.4+
Samsung Internet✅ 지원21+
/* 폴백 패턴: 구형 브라우저는 hex를 사용 */
.button {
  background-color: #0066cc;                    /* 폴백 */
  background-color: oklch(52% 0.2 264);         /* 최신 브라우저 */
}

/* @supports로 조건부 적용 */
@supports (color: oklch(0% 0 0)) {
  :root {
    --brand: oklch(65% 0.2 264);
    --brand-dark: oklch(45% 0.2 264);
  }
}

OKLCH 색상 도구

OKLCH 값을 직접 계산하기 어렵다면 다음 도구들을 활용하세요.

  • oklch.com — 인터랙티브 OKLCH 피커. HEX ↔ OKLCH 변환과 팔레트 생성 지원
  • Figma OKLCH 플러그인 — 디자인 툴에서 바로 OKLCH 색상 사용
  • PostCSS OKLCH 플러그인 — 빌드 시 구형 브라우저용 색상으로 자동 변환
  • Chrome DevTools — 색상 피커에서 OKLCH 모드로 전환 가능 (Chrome 112+)
# PostCSS로 OKLCH → sRGB 자동 변환 (구형 브라우저 지원)
npm install postcss postcss-oklab-function
# postcss.config.js에 플러그인 추가 후 빌드하면 자동 변환

실전 디자인 시스템 적용 예시

OKLCH를 활용한 시맨틱 색상 토큰 설계 예시입니다. Lightness를 조정해 일관된 명도 계층을 만들 수 있습니다.

:root {
  /* 브랜드 색상 — 같은 Hue, 같은 Chroma, Lightness만 변경 */
  --color-brand-50:  oklch(97% 0.05 264);   /* 매우 밝은 배경 */
  --color-brand-100: oklch(93% 0.08 264);
  --color-brand-200: oklch(86% 0.12 264);
  --color-brand-300: oklch(78% 0.16 264);
  --color-brand-400: oklch(68% 0.20 264);
  --color-brand-500: oklch(58% 0.22 264);   /* 기본 브랜드 색 */
  --color-brand-600: oklch(48% 0.22 264);
  --color-brand-700: oklch(38% 0.20 264);
  --color-brand-800: oklch(28% 0.16 264);
  --color-brand-900: oklch(20% 0.10 264);   /* 매우 어두운 색 */

  /* 시맨틱 토큰 */
  --color-primary: var(--color-brand-500);
  --color-primary-hover: var(--color-brand-600);
  --color-primary-light: var(--color-brand-100);
}

@media (prefers-color-scheme: dark) {
  :root {
    /* 다크모드: 숫자만 뒤집으면 자동으로 적절한 명도 확보 */
    --color-primary: var(--color-brand-400);
    --color-primary-hover: var(--color-brand-300);
    --color-primary-light: var(--color-brand-900);
  }
}

이렇게 설계하면 라이트/다크 모드 전환이 CSS 변수 값 교체만으로 끝납니다. OKLCH의 균일한 지각적 밝기 덕분에 -500-400의 밝기 차이가 모든 Hue에서 동일하게 유지됩니다.

OKLCH 전환 시 실무에서 겪는 어려움과 해결법

OKLCH는 분명히 우월한 색상 모델이지만, 실제로 프로젝트에 도입할 때는 몇 가지 현실적인 장벽이 존재합니다. 가장 흔한 문제는 디자인 툴과의 호환성입니다. Figma나 Adobe XD 같은 도구들은 여전히 HEX와 HSL을 기본 색상 표기로 사용하기 때문에, 디자이너와 개발자 간의 색상 전달 과정에서 변환 작업이 필요합니다. 이 문제는 oklch.com이나 Colorjs.io 같은 변환 도구를 공유 워크플로에 포함시킴으로써 완화할 수 있습니다.

또 다른 어려움은 기존 코드베이스 마이그레이션입니다. 수백 개의 HEX 값이 흩어진 레거시 프로젝트를 OKLCH로 일괄 전환하려면 상당한 시간이 필요합니다. 현실적인 접근법은 전면 전환보다 점진적 도입입니다. 신규 컴포넌트는 OKLCH로 작성하고, 기존 컴포넌트는 리팩토링 기회가 생길 때마다 하나씩 전환하는 방식이 팀의 부담을 줄여줍니다. CSS 변수 레이어를 중간에 두면 내부적으로 OKLCH를 사용하면서도 외부 API는 그대로 유지할 수 있어서 마이그레이션 위험이 낮아집니다.

브라우저 지원 문제도 실무에서 자주 언급됩니다. OKLCH는 2023년부터 모든 주요 브라우저에서 지원되지만, 기업 환경에서 여전히 사용되는 구형 Internet Explorer나 오래된 Chrome 버전을 지원해야 한다면 폴백 전략이 필요합니다. @supports (color: oklch(0 0 0)) 쿼리로 지원 여부를 확인하고, 미지원 환경에는 HSL 값을 제공하는 방식으로 안전하게 구현할 수 있습니다.

OKLCH가 접근성에 미치는 긍정적 영향

OKLCH의 지각적 균일성은 색각 이상을 가진 사용자에게 특히 유리합니다. 전통적인 색상 모델에서는 특정 Hue 조합이 명도 대비 기준을 통과하더라도 실제로 구분이 어려운 경우가 있습니다. OKLCH에서는 명도(L) 값이 실제 인지 밝기와 정확하게 일치하기 때문에, L값 차이가 크면 색각 이상 여부와 관계없이 충분한 대비를 확보할 수 있습니다. WCAG 2.1의 AA 기준(대비비 4.5:1)을 만족하는 색상 쌍을 OKLCH로 설계하면, HSL 대비 훨씬 예측 가능하고 일관된 결과물을 얻을 수 있습니다. 색상 팔레트를 처음 설계하는 단계부터 접근성을 함께 고려하고 싶다면, OKLCH 기반 설계가 가장 효율적인 방법 중 하나입니다.