디자이너와 프런트엔드 개발자는 본인이 인정하는 것보다 훨씬 자주 “이미지를 팔레트로 변환하는” 작업을 한다. 새 클라이언트가 슬라이드 덱을 건네고 “이 분위기 그대로 웹사이트로 만들어 달라”고 한다. 사진작가는 포트폴리오 크롬이 히어로 이미지와 호응하길 원한다. 마케팅 팀은 상단의 제품 컷이 색감을 주도하는 랜딩 페이지를 원한다. 이 모든 시나리오는 같은 질문에서 출발한다: 이 이미지에 실제로 어떤 색이 있고, 어떤 색이 시각적 무게를 짊어지고 있는가?
수동 방법은 이렇다: 파일을 Figma에 던져 넣고, 스포이트를 길게 누르고, 대표적으로 보이는 5–6 곳을 샘플링해서, HEX 값을 스타일시트에 적고, 맞기를 빈다. 알고리즘 방법은 이렇다: 모든 가시 픽셀을 k 그룹으로 클러스터링하고, 각 그룹의 평균 색과 이미지 내 점유율을 보고하고, 점유율 메타데이터를 포함한 팔레트를 다운스트림 결정에 그대로 넘긴다.
브라우저는 이 작업에 가장 적합한 런타임이다. 이미지는 로딩이 끝나는 순간 메모리에 있다. Canvas는 픽셀 데이터를 직접 노출한다. 수백 줄의 JavaScript로 k-means를 “즉각적”이라 느낄 만큼 빠르게 돌릴 수 있다. 업로드도, 라운드트립도, 작업 중인 자료를 들여다보는 제3자도 없다.
이미지 기반 팔레트가 필요한 순간
이미지 기반 팔레트가 빛을 발하는 건 몇 가지 반복되는 시나리오다. 패턴은 늘 같다: 시각 자료가 고정이고, 팔레트는 그것을 따라야 한다.
| 시나리오 | 왜 이미지 추출이 수동보다 나은가 |
|---|---|
| 신규 클라이언트 온보딩 | 클라이언트가 가진 브랜드 자산이 곧 팔레트. 로고에 맞을 만한 HEX를 추측하는 것보다 리버스 엔지니어링이 훨씬 빠르다. |
| 사진작가 포트폴리오 | 사이트 크롬은 히어로 사진과 호응해야 둘이 충돌하지 않는다. 사진에서 색을 뽑으면 조화는 보장된다. |
| 이커머스 상품 상세 | 상품 컷의 주요 톤이 액센트, 배지, CTA 보더를 주도해 페이지 전체에 시각적 연속성이 생긴다. |
| 스톡 이미지 기반 랜딩 | 스톡 이미지는 까다롭다 — 액센트를 잘못 잡으면 레이아웃이 “붙여 넣은 느낌”이 된다. 액센트를 이미지 자체에서 가져오면 그런 일이 없다. |
| 경쟁사 분석 | 자사 히어로 이미지와 경쟁사 히어로 이미지의 색상 가중치를 나란히 두면, 색상 전략이 주관에서 정량으로 바뀐다. |
| 에디토리얼 커버 | 커버에서 5색 팔레트를 추출해, 점유율 1위는 제목 색, 2위는 바이라인, 3위는 구분선에 사용한다. |
출발점이 “HEX 하나가 있고 스킴이 필요해”라면 적합한 도구는 컬러 팔레트 생성기 (보색, 유사색, 트라이아드, 테트라드 등을 베이스 HEX에서 생성). 출발점이 “이미지가 있어”라면 리버스 추출이 원자료를 존중하는 워크플로우다.
k-means가 팔레트를 만드는 방식
k-means는 디자이너 친화적인 결과를 낼 수 있는 가장 단순한 클러스터링 알고리즘이다. 4단계 루프:
1. 이미지에서 k개의 픽셀을 무작위로 초기 중심으로 선택.
2. 각 픽셀을 RGB 거리가 가장 짧은 중심에 할당.
3. 각 중심을 할당된 픽셀들의 평균 위치로 이동.
4. 중심이 더 이상 움직이지 않을 때(또는 24회 반복, 먼저 오는 쪽)까지 2, 3을 반복.
흥미로운 설계 결정은 루프 자체가 아니라 그 주변에 있다.
다운샘플링. 4K 사진에서 k-means를 돌리면 반복마다 800만 번의 픽셀 비교가 필요해 “즉각”으로 느껴야 할 브라우저 도구에는 너무 느리다. 최장 변을 200픽셀로 리사이즈하면 약 4만 샘플 픽셀로 압축된다. 8 중심점 + 24 반복은 총 약 800만 번의 거리 계산. 최신 노트북에서 100밀리초 이내에 끝난다. 다운샘플링은 중요한 색상 정보를 잃지 않는다 — 어차피 쓰지 않을 공간 정보만 잃을 뿐.
초기화. 순수 무작위 선택은 가끔 두 중심점을 거의 동일한 픽셀에 떨어뜨린다. 도구는 첫 반복 이전에 샘플링한 중심점을 중복 제거해 최악의 경우를 피하지만, k-means 자체는 여전히 확률적이다. 같은 이미지, 같은 k로 두 번 돌려도 약간 다른 클러스터로 수렴할 수 있다. 해법은 다시 돌려 새 시드를 시도하거나, k를 키워 중심점이 색 공간을 더 결정론적으로 덮도록 하는 것.
거리 척도. RGB 공간의 유클리드 거리는 교과서적 선택이며 시각 추출에는 충분하다. 디자이너들은 가끔 “Oklab 같은 지각 균등 공간이 더 ‘자연스러운’ 클러스터를 만든다”고 주장하지만 실용적 이득은 미미하다 — 결과는 사람 눈으로 보고, 사용자는 결과를 받은 뒤 색상이나 명도로 다시 정렬할 수 있다. RGB를 유지하면 수학이 빠르고 구현이 감사 가능하다.
클러스터 병합. 중복 제거된 초기화로도 k-means는 가끔 육안으로 구분 불가능한 두 중심점으로 수렴한다. 도구는 RGB 거리 합이 6 미만인 두 중심을 병합하고(지각하기 어려운 거리), 픽셀 가중치를 합산한다. 결과: k가 무엇이든 출력 스와치 두 개가 같아 보이지 않는다.
프리필터. 두 가지 필터가 알고리즘에서 주도권을 되찾는다. 투명 픽셀 제외(alpha < 128)는 기본 ON — PNG의 알파 채널은 가시 콘텐츠를 묘사하는 팔레트에 포함되어선 안 된다. 거의 흰색 픽셀 제외(휘도 > 0.95)는 옵션. 스튜디오 흰 배경이 있는 제품 컷에선 ON으로 두면 중심점이 진짜 피사체를 찾고, 흰색이 디자인의 일부인 에디토리얼 레이아웃에선 OFF로 둔다.
네 가지 색 공간 — 각각 언제 쓸까
팔레트는 다음 도구에 그대로 붙여넣을 수 있어야 유용하다. 본 도구는 스와치마다 네 가지 색 공간을 출력해 파이프라인에서 수동 변환이 필요 없게 한다.
| 공간 | 강점 | 용도 |
|---|---|---|
| HEX | 범용 호환, 가장 짧은 토큰 | 채팅, GitHub, Figma 파일 메타데이터에서 공유 |
| RGB | 모던 공백 구분 문법 rgb(160 90 44) | 직접 작성한 스타일시트, CSS 변수 |
| HSL | 색상 + 채도 + 명도를 단일 축으로 | 빠른 변형, 호버 상태 (명도 +10%) |
| OKLCH | 지각적으로 균일한 L, C, H | 디자인 토큰, 자동 팔레트 생성, 명암비 인식 시프트 |
OKLCH는 프로덕션 코드에서 여전히 과소평가되어 있어 더 자세히 짚어둘 가치가 있다. HSL의 L 축은 수학적으로 단순하지만 지각적으로 불균일하다 — L=50에서 L=70으로의 변화가 노란색에서 파란색보다 더 큰 도약으로 보인다. OKLCH는 그 축을 Oklab에서 도출한 지각 균일 L로 대체한다. 결과로, 자동 변환(10% 밝게, 색상 30° 회전)의 출력이 사람 눈에 등간격 단계로 보인다. 예측 가능한 명도 램프가 필요한 디자인 토큰 시스템을 구축한다면 OKLCH가 올바른 출력 포맷이다.
흔히 빠지는 함정
자동 팔레트 추출을 처음 쓰는 사용자가 걸리는 패턴이 몇 가지 있다.
이미지에 거대한 거의 흰색 배경이 있다. 8 중심점 중 3개가 오프화이트 영역에 떨어지고, 사진의 실제 피사체는 1–2 스와치만 기여한다. “거의 흰색 제외”를 ON으로 — 알고리즘이 휘도 > 0.95 픽셀을 무시하고 풀려난 중심점이 진짜 콘텐츠를 찾아간다.
이미지가 대부분 투명하다. 알파 프리필터가 일반적인 경우(투명 배경 위 PNG 아이콘)를 처리한다. 완전 투명일 경우 도구는 “필터 적용 후 표시 가능한 픽셀이 없습니다”를 보고하며 빈 팔레트를 렌더링하지 않는다.
실행할 때마다 결과가 달라진다. k-means의 무작위 초기화 때문이다. 수정은 k를 키우거나(중심이 많을수록 무작위 시드가 더 넓게 퍼진다), “주요 3–4색은 안정, 후순위 4–5색은 약간 흔들린다”를 받아들이는 것. 신경 쓰는 색이 고정될 때까지 재추출 버튼을 누른다.
추출된 색이 스포이트로 찍은 색과 다르다. k-means가 보고하는 건 각 클러스터의 평균이지 샘플링한 픽셀이 아니다. 사진이 왼쪽 진홍에서 오른쪽 주황으로 그러데이션된다면 k-means는 클러스터 중심이 안착한 중간색을 반환할 가능성이 크다. 스포이트는 그 지점의 색을 반환한다. 둘 다 맞지만 다른 질문에 답한다. 사진의 특정 특징과 일치하는 액센트 색이 필요하면 수동 샘플링, 사진의 톤을 요약하는 톤 팔레트라면 k-means가 적합하다.
단순한 이미지에 너무 많은 색을 요구한다. 검은 배경의 로고는 많아야 3–5개 구분되는 색을 가진다. 16개를 요구하면 k-means가 거의 동일한 그룹을 분할해 마이크로 클러스터를 만든다. 출력은 정상이지만 실질적 중복이 포함된다. 클러스터 병합 단계가 극소 거리를 정리하지만, 이미지의 실제 색상 수에 맞춰 k를 줄이는 게 더 낫다.
실전 워크플로우
가장 빨리 결과를 내는 흐름:
1. 원본 이미지를 드롭. 기본은 k=8, 빈도순 정렬.
2. 이미지에 스튜디오 흰 배경이 있으면 "거의 흰색 제외"를 ON.
3. "다시 추출"을 한두 번 눌러 주요 색이 안정됨을 확인.
4. 임의 스와치의 색 블록 부분을 클릭해 HEX 복사.
5. "CSS 변수 복사"로 :root 블록 전체를 가져옴.
6. 디자인 토큰에 붙여넣기.
7. 가장 중요한 쌍을 컬러 명도 대비 검사기
(https://zerotool.dev/ko/tools/color-contrast-checker/) 로 돌려
텍스트와 배경 조합이 WCAG AA를 만족하는지 검증.
Tailwind config을 유지한다면 “Tailwind 복사” 버튼이 theme.extend.colors.palette 아래에 곧장 떨어뜨릴 수 있는 스니펫을 c1부터 cN까지의 명명으로 출력한다. 이후 도메인에 맞춰(primary, accent, surface 등) 이름을 바꾸면 끝.
프라이버시와 성능
브라우저는 이런 작업에 대해 프라이버시 친화적인 런타임이다. 이미지는 FileReader.readAsDataURL로 읽히고, HTMLImageElement로 디코딩되고, 샘플링 해상도로 숨겨진 Canvas에 그려지고, JavaScript에서 CPU 위에 클러스터링된다. 이미지 바이트와 픽셀 데이터는 기기에 머문다 — 페이지의 유일한 네트워크 요청은 도구가 로드될 때의 정적 자산뿐이다.
Apple Silicon Mac에서 측정한 실제 성능 데이터:
| 이미지 | 디코딩 + 그리기 | k-means (k=8) | 합계 |
|---|---|---|---|
| 800×600 PNG | ~12 ms | ~35 ms | ~47 ms |
| 1920×1080 JPEG | ~25 ms | ~40 ms | ~65 ms |
| 3840×2160 JPEG | ~70 ms | ~45 ms | ~115 ms |
| 8000×6000 사진 | ~180 ms | ~50 ms | ~230 ms |
k-means 실행 시간은 다운샘플링된 버퍼 크기에 의해 제한되며 원본 이미지와 무관하다. 따라서 매우 큰 사진은 주로 디코딩 및 그리기 단계에서 느려진다.
Adobe Color, Coolors와의 차이
Adobe Color의 “이미지에서 추출” 탭은 이 분야의 확립된 벤치마크이며 멋진 5색 팔레트를 만든다. 서버 사이드에서 동작하고, 팔레트를 Creative Cloud 라이브러리에 저장하려면 로그인을 요구하며, 이미 Adobe 생태계 안에 살고 있는 디자이너 중심으로 설계되어 있다. Coolors의 이미지 피커도 비슷한 범위다. 둘 다 영감을 찾기엔 좋지만, 결과를 코드로 출고할 때엔 약간 어긋난 느낌이 든다.
ZeroTool 추출기는 다른 niche에 있다: 이미 다른 탭에 스타일시트를 열어둔 개발자를 위한 “탭만 열면 바로 쓰는” 도구. 트레이드오프:
- 스와치마다 네 가지 색 공간(HEX, RGB, HSL, OKLCH)을 나란히 표시 — 코드 복사 시 변환 단계가 사라진다.
- 팔레트 이미지가 아닌 CSS 변수, JSON, Tailwind config로의 일괄 익스포트.
k가 3에서 16까지 조정 가능, 고정 5가 아니다.- 스와치마다 점유율 백분율 — 어떤 추출 색을 브랜드 액센트로 삼을지 결정할 때 중요.
- 페이지 로드 후 100% 오프라인.
- 저장 팔레트, 클라우드 라이브러리, 팀 공유 없음 — 의도적. “저장”은 계정을 필요로 하고, 계정은 데이터가 브라우저를 떠난다는 뜻이니까.
팔레트가 팀 공유 라이브러리에 저장되어야 한다면 Adobe Color가 여전히 정답. :root 블록에 30초 안에 팔레트를 떨어뜨려야 한다면 이 도구가 그 용도로 만들어졌다.
한국 디자인 현장에서의 보강
브런치, 미디엄 한국판, 자체 사이트 헤더에서 자주 쓰이는 흐름이 있다: 표지 일러스트나 사진에서 5색을 추출해 본문 구분선·인용 블록 색·강조 색에 매핑한다. 도구가 4 색 공간을 동시에 보여주므로, 디자인 토큰에 OKLCH로 저장하면서 즉시 코드에 HEX로 붙여넣는 두 가지 흐름을 한 화면에서 처리할 수 있다.
또 다른 패턴: 제품 스크린샷에서 추출한 색을, 그 UI의 스크린샷을 인용하는 블로그 글의 장식 색으로 사용한다. 콘텐츠와 비주얼의 색온도가 맞아 독자에게 인지 부하가 덜 생긴다.
더 읽을 거리
- 컬러 팔레트 생성기 — 하나의 베이스 HEX에서 보색, 유사색, 트라이아드, 테트라드 스킴 생성.
- 컬러 셰이드 생성기 — 임의의 베이스 색에서 9단계 명도 램프 추출. 추출한 한 색을 완전한 램프로 확장할 때.
- 색상 변환기 — HEX, RGB, HSL 자유 상호 변환과 라이브 미리보기.
- 색상 명도 대비 검사기 — 추출 팔레트의 각 쌍이 적용 배경에 대해 WCAG AA / AAA를 만족하는지 검증.
- MDN: oklch() 색 함수 — OKLCH 문법과 브라우저 지원 레퍼런스.
- Björn Ottosson의 Oklab 원문 — 도구의 OKLCH 변환이 사용하는 지각 색 공간의 원논문.
- k-means 클러스터링 (위키백과) — 알고리즘 배경, k-means++ 같은 개선과
k를 선택하는 엘보 방법.
이미지 컬러 팔레트 추출은 ZeroTool 컬러 도구 패밀리의 한 조각. 출고 전 명도 대비 검사기로 검증하고, 추출한 한 색을 완전한 명도 램프로 확장해야 할 때 셰이드 생성기와 짝지어 쓴다.