2P by GN⁺ | ★ favorite | 댓글 1개
  • Postmark의 기존 색상 팔레트는 색상별 체감 밝기가 들쭉날쭉하고 단계 간 대비율을 예측하기 어려워, WCAG 권장 대비를 매번 수동 확인해야 했음
  • HSL/HSV는 RGB를 단순 변환한 모델이라 인간의 밝기·채도 지각을 반영하지 못하며, 단일 색상 선택에는 쓸 수 있어도 색상 시스템 구축에는 부적합함
  • CIELAB와 LCh는 수치 변화가 체감 변화와 더 가깝도록 설계된 지각 균일 색공간이라, 같은 밝기 수준의 색상 스케일을 더 일관되게 만들 수 있음
  • Accessible Palette는 LCh 기반으로 밝기, 대비율, Hue 보정, 기존 브랜드 색상 반영을 조정해 일관된 팔레트를 생성하는 앱임
  • WCAG 2.1 대비율과 WCAG 3 Working Draft의 APCA를 함께 확인해야 현재 지침 준수와 향후 대비 알고리듬 변화에 모두 대응하기 쉬움

Postmark 색상 시스템의 문제

  • 기존 Postmark 팔레트에는 두 가지 문제가 있었음
    • 파랑과 빨강은 노랑과 초록보다 훨씬 어둡게 보이는 등 체감 밝기가 일관되지 않았음
    • 색상 변형 간 대비율을 예측하기 어려워, 색상 쌍이 WCAG 권장 사항을 만족하는지 쉽게 알 수 없었음
  • 색상 쌍을 고를 때마다 대비율을 수동으로 확인해야 했고, 실제로는 확인하지 않을 가능성도 컸음
  • 원인은 HSL 색상 모델 자체의 한계와, 더 나은 대안을 디자인 도구가 충분히 지원하지 않는 상황에 있었음

HSL이 색상 시스템에 맞지 않는 이유

  • RGB는 화면이 작동하는 방식을 반영하는 모델이며, 사람이 색을 고르기 쉬운 직관적 모델은 아님
  • HSL과 HSV/HSB는 1970년대에 RGB를 사람이 생각하는 색상 방식에 가깝게 표현하려고 만든 대안임
    • HSL은 Hue, Saturation, Lightness를 뜻함
    • HSV/HSB는 Hue, Saturation, Value 또는 Brightness를 뜻함
  • 당시에는 더 정교한 모델의 계산 비용이 컸기 때문에, HSL과 HSV는 계산 속도를 위해 지각적 정확성을 희생했음
  • 결과적으로 HSL과 HSV는 RGB의 쉬운 수학적 변환일 뿐이며, 사람이 느끼는 밝기나 채도를 제대로 반영하지 못함
  • 예를 들어 HSL에서 Saturation 100, Lightness 50으로 맞춘 색상 스케일은 모델상 같은 밝기지만, 실제로는 파랑 #00F가 노랑 #FF0이나 시안 #0FF보다 훨씬 어둡게 보임
  • HSL에서는 완전 채도 색상이 RGB의 최대값에 매핑되고 Lightness 50의 Hue 원에 놓이며, Lightness 0과 100은 각각 검정과 흰색에 대응함
    • 더 밝거나 어두운 변형은 흰색 또는 검정과 “섞이는” 방식으로 만들어짐
    • 중앙 세로축은 Saturation 0인 중립색 또는 회색 범위임

CIELAB와 LCh

  • HSL과 HSV가 정식화되던 시기에는 이미 더 나은 대안인 CIELAB 색공간이 존재했음
  • International Commission on Illumination, 즉 CIE는 1976년에 CIELAB 또는 L*a* b* 색공간을 정의했음
  • CIELAB는 수치 변화가 비슷한 체감 색상 변화에 대응하도록 설계된 지각 균일 색공간
    • RGB와 달리 보이는 색상의 전체 범위를 포괄하도록 설계됨
    • Lightness인 L* 성분은 인간의 밝기 지각과 가깝게 맞춰짐
  • CIELAB는 세 축으로 구성됨
    • L* 값은 0에서 검정, 100에서 흰색을 정의함
    • a* 축은 초록-빨강 반대색 축이며, 음수는 초록, 양수는 빨강 방향임
    • b* 축은 파랑-노랑 반대색 축이며, 음수는 파랑, 양수는 노랑 방향임
  • CIELCh, LCh, 또는 Lch(ab)는 CIELAB의 원통형 표현임
    • a*와 b* 대신 Chroma와 Hue 각도를 사용함
    • Lightness는 그대로 유지됨
  • LCh의 Hue 각도는 HSL의 Hue와 비슷하지만 동일하지 않음
    • HSL/HSV는 빨강, 초록, 파랑의 3가지 가산 원색을 H=0, 120, 240°에 둠
    • LCh는 빨강, 노랑, 초록, 파랑을 h=0, 90, 180, 270°에 둠
  • HCL 또는 LCh(uv)라는 유사 색공간도 있으며, LCh(ab)와 달리 Chroma가 0부터 100까지 균일한 스케일을 가짐

LCh에서 색상 스케일을 만드는 방식

  • LCh는 HSL/HSV와 달리 원통 안에 맞지만 원통을 꽉 채우지는 않음
  • Lightness, Chroma, Hue의 일부 조합은 존재할 수 없는 색상을 만듦
    • 예를 들어 어둡고 채도 높은 노랑은 존재하지 않음
  • Lightness 스케일에서 검정과 흰색에 가까워질수록 사람이 구분할 수 있는 색상 수는 줄어듦
  • 실제 화면에는 보이는 색상 전체를 표시할 수 없음
    • sRGB 색역은 일반적인 화면을 나타내며 LCh 색공간의 약 ⅓만 포함함
    • CSS에서도 적어도 현재는 이 범위로 제한됨
  • HSL에서 Saturation 100, Lightness 50인 색상 스케일을 LCh 기준으로 보면 노랑이 가장 밝고 파랑이 가장 어두움
    • 초록은 파랑보다 거의 세 배 밝고, 빨강보다 약 두 배 밝음
  • LCh에서 같은 Lightness 수준으로 스케일을 다시 만들면 색상별 밝기가 시각적으로 일관됨
    • Chroma가 달라 일부 색상은 다른 색상보다 채도가 높을 수 있음
    • 알림과 경고 색상은 기본 텍스트 색상보다 더 채도가 높기를 원할 수 있어, 색상 시스템에서는 이런 차이가 유용할 수 있음
  • Chroma까지 더 일관되게 맞추면 제한된 sRGB 색공간 안에서도 부드러운 스케일을 만들 수 있음

디자인 도구의 한계와 Accessible Palette

  • 현재 Figma, Sketch, Adobe XD는 CIELAB나 LCh를 지원하지 않음
  • Figma에는 LCH color pickerChromatic 플러그인이 있지만, 유연한 색상 시스템을 만들기에는 충분하지 않았음
  • 필요한 도구는 세 가지 조건을 만족해야 했음
    • 색상 변형을 만들 때 밝기 일관성을 유지함
    • 단계 간 대비율을 제어할 수 있음
    • 기존 브랜드 색상을 수용할 만큼 유연함
  • LCh 지원이 좋은 Chroma.js 라이브러리를 발견한 뒤, 코드로 새 팔레트를 생성하는 간단한 도구를 만들었음
  • 내부 사용과 일부 지인 공유를 거친 뒤, 이 도구는 Accessible Palette 앱으로 공개됨
  • Accessible Palette는 색상 레벨 전반에서 일관된 밝기와 예측 가능한 대비율을 갖는 색상 시스템을 만드는 앱임

Accessible Palette의 작동 방식

  • 시작 색상을 조정하거나 기존 디자인의 색상을 붙여 넣으면, 도구가 해당 색상의 Chroma와 Hue를 사용해 여러 Lightness 단계의 스케일을 계산함
  • Lightness는 완전히 사용자 지정할 수 있으며 밝은 팔레트와 어두운 팔레트 모두에 사용할 수 있음
    • 기존 브랜드 색상을 포함하도록 세밀하게 조정할 수 있음
    • Postmark에서는 기존 팔레트에서 가장 많이 쓰인 노랑 #FFDE00, 파랑 #007DCC, 초록 #4FC47F를 보존하려 했음
    • 이 색상들의 Lightness 값 88.6, 75.2, 50.6을 각각 레벨 200, 400, 600의 밝기로 사용함
  • 대비율은 Lightness에 따라 달라지며, 각 레벨에 대해 WCAG 2.1 권장 방식과 WCAG 3.0 Working Draft의 새 알고리듬을 모두 사용해 계산함
    • 기본적으로 모든 색상의 대비는 흰색 배경을 기준으로 측정됨
    • 원하는 색상 견본을 선택해 그 색상을 기준으로 대비율을 측정할 수 있음
  • 레벨은 RGB 또는 CIELAB 색공간을 사용해 생성할 수 있음
    • 경우에 따라 결과가 달라질 수 있어 실험해볼 가치가 있음
    • Postmark 색상 체계에서는 CIELAB 사용이 밝은 빨강의 보라색 기운은 줄였지만, 파랑에서는 보라색 기운을 늘렸음
  • 일부 색상은 범위 전체에서 Hue 보정이 필요할 수 있음
    • 밝은 노랑은 어두워질수록 초록색 기운이 생김
    • 이를 오렌지에 조금 더 가깝게 만들기 위해 음수 Hue 보정을 사용함
  • 앱은 사용 중 URL을 업데이트해 변경 사항을 저장함
    • 팀과 공유하거나 Figma 라이브러리와 CSS 색상 변수 파일에 추가해 이후 참조할 수 있음
  • 예시 팔레트로는 새 Postmark color palette, Google’s Material Design, TailwindCSS 기반 팔레트가 있음
    • 이 예시는 원본을 정확히 복제한 것이 아니라, 원래 색상과 밝기 단계에서 영감을 받은 대안임

대비율 계산과 WCAG

  • Accessible Palette가 두 가지 대비율을 보여주는 이유는 WCAG 2.1 방식에 한계가 있기 때문임
  • WCAG 2.1은 전경색의 휘도를 배경색의 휘도로 나누어 대비율을 계산함
  • 이 공식은 선형 응답을 제공하지만, 사람은 밝은 색상 간 대비를 어두운 색상 간 대비보다 더 높게 지각함
  • 실제 예시에서는 WCAG 2.1 권장 사항을 만족하는 샘플이 “불충분” 대비율로 표시된 샘플보다 읽기 어려울 수 있음
  • W3C는 이 문제를 인지하고 있으며, Andrew Somers는 2019년에 공개 논의를 시작했음
  • Andrew Somers가 제안한 새 작업 알고리듬은 WCAG 3 Working Draft의 일부가 되었고, APCA Contrast Calculator도 만들었음
  • APCA는 Advanced Perceptual Contrast Algorithm의 약자이며, 지각적으로 더 정확하고 글꼴 크기와 굵기도 고려함
  • Accessible Palette는 APCA를 사용하며, 읽을 수 있는 텍스트의 최소 권장 수준으로 점수 60을 사용함
    • 이는 WCAG 2.1의 기존 4.5:1 대비율 권장과 유사한 기준임
  • WCAG 2.1 대비율이 완전히 쓸모없는 것은 아님
    • 중간 범위 색상에서는 여전히 꽤 정확함
    • 다만 전체적으로는 새 알고리듬이 큰 개선임
  • WCAG 3 방식은 아직 Working Draft라 시간이 지나며 바뀔 수 있음
  • 현재 지침 준수와 향후 변화 대응을 모두 고려하려면 두 가이드라인을 함께 염두에 두고 색상 시스템을 만드는 편이 좋음

댓글과 토론

Hacker News 의견들
  • 일반적인 디스플레이와 인쇄 시스템에서는 포화된 빨강과 파랑이 초록보다 실제로 더 어둡다고 봐야 함
    색공간에 따라 정확한 공식은 달라지지만 Grayscale = 0.299R + 0.587G + 0.114B가 흔히 인용되고, 이 경우 가장 밝은 순수 빨강은 약 30%, 순수 파랑은 11% 밝기라서 대부분의 경우 밝은 빨강은 모순에 가까움
    이런 색을 쓸 수는 있지만 항상 어둡게 보일 수밖에 없고, 단순히 대비 규칙만 적용하면 접근성은 맞출 수 있어도 보기 좋은 결과까지 원한다면 글에서 다룬 기법이 훨씬 유리함
    https://en.wikipedia.org/wiki/Anaglyph_3D 같은 적청 입체사진을 만들 때도 나무와 풀은 초록이지만 실제로 빨강 성분이 많아 채널 균형이 좋아서 입체감과 색이 모두 잘 나옴
    참고: https://www.dynamsoft.com/blog/insights/image-processing/ima...

    • NTSC 방송 안전 범위 시절과 빨강을 너무 좋아하던 클라이언트들이 떠오름
      아름다운 빨간 아트워크가 TV에서는 전혀 아름답게 보이지 않을 거라고 설명하는 일은 늘 힘들었고, 방송용이면 특히 더 그랬음
      방송용이 아니어도 규격 밖 빨강은 몇 프레임 뒤까지 남아 보이고, 목이 베인 것처럼 번져 보일 수 있었음
    • 여기에는 틀린 내용이 여러 가지 있음
      답글들을 읽었다면 답을 달아주면 몇 가지를 더 명확히 설명해 보겠음
  • 실제로 WCAG 2.1 권장 기준을 만족하는 샘플이 “불충분한” 대비율을 가진 샘플보다 읽기 더 어렵다는 점이 오래전부터 거슬렸음
    “접근성 지침” 공식이 오히려 반대 효과를 내는데 왜 표준화됐는지 궁금함

    • 대비 접근성에서 가장 널리 쓰이는 알고리즘과 지침에 동료 검토된 근거가 없다는 점은 좀 안타까움
      2.1도 그렇고 차기 표준도 마찬가지라서, 이렇게 영향력이 큰 영역이라면 업계가 더 엄밀한 연구를 후원했으면 함
    • W3C/WCAG 안에서 대비 판정 공식을 바꾸려는 움직임이 있었던 것으로 기억함
      어쩌면 단순히 그런 요구가 있었을 뿐 아직 공식적으로 채택되지는 않았을 수도 있음
  • 이 주제에서 본 최고의 글은 https://www.handprint.com/HP/WCL/color1.html
    엄청 긴 글이라 하루를 쓰게 될 각오가 필요함
    놀랄 수도 있지만, ClickHouse에서 로그 색을 예쁘게 칠할 때도 이 글의 몇 가지 아이디어를 사용하고 있음: https://github.com/ClickHouse/ClickHouse/blob/master/base/ba...

    • 이 ANSI 색을 RGB로 변환하는 구체적인 방법은 찾기 어려웠고, 실제로는 색 요청일 뿐이며 터미널 설정에 의존하는 것으로 보임
      코드에서 설정한 각 메시지 유형마다 기대하는 RGB 값이 무엇인지 공유해 줄 수 있는지 궁금함
  • Figma의 Config 컨퍼런스에서 Eugene을 만났는데, 디자이너들에게 비슷한 실전 팁을 많이 알려줬고 정말 친절하며 디자인과 접근성에 진심인 사람이었음
    이 글에서 특히 칭찬하고 싶은 건 APCA인데, WCAG 2의 색 대비 알고리즘을 계승할 가능성이 큼
    Figma 내부 접근성 개편에서도 APCA를 사용했고, 그 덕분에 최종 결과가 훨씬 좋아졌음
    Eugene이 WCAG 2가 실패하는 사례를 잘 보여주는데, 실제로 우리도 그런 경우를 계속 마주쳤음
    핵심 조언은 색을 제대로 맞추는 일이 정말 어렵다는 것임
    도구는 도움이 되지만 어느 순간에는 눈을 믿어야 함
    결국 이런 도구들은 눈이 색을 보는 방식을 수학적으로 근사할 뿐이고, 최종 기준은 알고리즘이 아니라 사람의 눈임
    도구나 알고리즘이 맞지 않는 결과를 내는 지점에서는 조정하거나 기본으로 돌아가는 편이 좋음

    • Figma 내부 접근성 개편에 APCA를 썼다는 부분을 더 자세히 설명해 줄 수 있는지 궁금함
      APCA만 사용하고 WCAG 2 색 대비 알고리즘이 대비 부족으로 표시하는 내용은 무시했다는 뜻인지 알고 싶음
    • 적록색약인데, Figma의 기본 접근성이 충분히 좋아서 따로 접근성 조정을 생각해 본 적이 없음
      잘 만들었음
  • HCT도 소개하고 싶음
    Material You를 가능하게 하려고 만든 색공간으로, 여기서 말한 밝기 측정값과 최신 색채 과학 색공간을 결합함
    LAB/LCH는 1976년에 나온 것임
    디자인을 더 직관적으로 만들어 주는데, T 차이가 40이면 버튼에 대한 WCAG 기준을 만족하고 50이면 텍스트 기준을 만족한다는 것만 알면 됨

    • 흥미로움
      HCT가 https://www.hsluv.org/comparison/와 어떻게 비교되는지 궁금함
      HCT와 비슷하게 여기서는 L 차이로 대비 색을 고르기 쉬워짐
      같은 맥락에서 https://www.myndex.com/APCA/와, 이것이 표준이 되었을 때의 접근 방식에 대해서도 생각이 궁금함
      두 색 사이의 대비값은 어느 색이 전경이고 어느 색이 배경인지에 따라 달라지므로, 이제는 T 차이만 비교하는 것으로 충분하지 않을 것 같음
    • HCT를 배우기에 좋은 자료가 있는지 궁금함
      예를 들어 애플리케이션에 빨강, 노랑, 파랑, 주황, 초록, 보라, 즉 3원색과 3보색에 해당하는 6가지 색이 필요하다고 하자
      정확히 어떤 색이 되는지는 크게 상관없지만, 그 6가지로 어느 정도 식별 가능하면서 밝기, 어쩌면 채도까지 비슷하게 맞추고 싶다면 어떻게 해야 할까
      노랑은 매우 밝고 파랑은 매우 어두우니 정확한 답은 없고 근사치에 도달해야 할 것 같음
      이런 것을 배울 도구나 튜토리얼이 있는지 궁금함
    • 공개 명세가 어딘가에 있는지 궁금함
      찾은 것은 GitHub의 material-color-utilities 코드뿐이었음
      코드를 보면 계산이 OkLab보다 훨씬 복잡해 보이고, 특히 HCT에서 RGB로 가는 방향이 더 그래 보임
  • 글에서 oklab/oklch를 빠뜨린 것뿐 아니라, 웹/CSS가 sRGB만 지원한다고 한 주장도 틀림
    CSS color() 함수는 여러 색공간을 지원함

    • 작성자임
      이 글은 2년 전에 발행됐고, 도구 작업을 시작했을 때는 OkLCH 명세도 아직 나오기 전이었음
      지금이라면 LCH 대신 OkLCH를 고를 텐데, LCH의 몇 가지 문제를 해결하기 때문임
    • CSS Color Module Level 4는 아직 권고안 초안 단계임
      여기서 “지원”은 더 정확히 말하면 “Microsoft Edge(chromium)와 Pale Moon(goanna)을 제외하고 지원”에 가까움
      https://test.csswg.org/harness/results/css-color-4_dev/group...
    • oklab과 여러 LAB 계열 색공간을 직접 써봤는데, Oklab은 단순한 계산으로 잘라 쓰기에 훌륭함
    • Oklch 위에 만든 색 모델도 있음
      다만 밝기 대신 APCA의, 즉 WCAG 3의 대비율을 사용함: https://github.com/antiflasher/apcach
  • oklab이 LCh보다 더 나은 대안일 수 있음
    https://bottosson.github.io/posts/oklab/

    • 초기 전제에서 꽤 멀리 벗어난 면이 있음
      밝기 채널이 다른 모든 색공간과 반대로 되어 있고, L은 LCH나 LAB의 L과 아무 관련이 없음
      성공이 오히려 지적 빈곤을 더 가져온 면도 있음
      최초 블로그 글에는 수정해야 할 내용이 아주 많고, CAM16 UCS를 사용한 그라디언트로 정확성을 주장하기 시작하는 지점부터 논리가 크게 어긋남
    • 이 플레이그라운드는 LCh와 OKLAB을 포함한 16개 색공간을 놀라울 정도로 잘 시각화해 줌: https://color-playground.ardov.me/spaces-3d
    • 완벽하지는 않지만, 몇몇 상황에서 색 보간에 oklab과 oklch를 사용해 왔고 RGB나 HSL에서 보간하는 것보다 결과가 시각적으로 훨씬 만족스러웠음
    • 내 사이트에서 OkLab을 만족스럽게 쓰고 있는데, 이전에 CIELAB을 사용하던 색상 팔레트보다 눈이 훨씬 편함
  • CIELAB 수치가 지각 변화를 기반으로 한다면 접근성과는 어떻게 상호작용하는지 궁금함
    이런 지각 공식이 표준 시력을 기준으로 만들어졌을 가능성을 걱정해야 할까
    색각 이상 유형에 따라 달라질 수 있는지, 아니면 그런 문제는 아닌지도 궁금함
    차트를 가능한 한 접근성 있게 만들려고 하지만 색에 대해서는 전혀 배운 적이 없어서 조언을 따라 할 뿐이고, 직접 도출할 수는 없음
    그래서 멍청한 질문일 가능성도 충분히 있음

    • 이쪽 작업을 해봤음
      대비는 비선형적으로 변함
      시뮬레이션은 꽤 쉽게 적용할 수 있고, Machado 등 저자의 시뮬레이션은 행렬 변환일 뿐임
  • 이 글은 설명을 아래쪽에 두고 있지만, WCAG 3 초안 표준의 읽기 쉬운 대비 테스트인 APCA Contrast는 WCAG 2.1의 대비율보다 일부 색에 훨씬 공정함
    지각 대비 뒤의 색 이론을 읽기 좋은 글: https://www.smashingmagazine.com/2022/09/realities-myths-con...
    APCA를 간결하게 설명한 글: https://typefully.com/u/DanHollick/t/sle13GMW2Brp

    • APCA는 잘 동작하지만, 라이선스가 매우 이상하고 제한적임
      무엇에 쓰기 전에 그 부분을 자세히 살펴보고 정말 사용할 수 있는지 판단하는 편이 좋음
  • 코드는 어디 있나
    웹 폼이 아니라 어떤 소프트웨어에서도 쓸 수 있는 알고리즘이 필요함