TeX에는 색이라는 개념이 없습니다. 커누스가 설계한 조판 엔진은 상자와 글루로 지면을 쌓아 올릴 뿐이고, 그 모형 안에 색이 들어갈 자리는 없습니다. 색을 나타내는 원시 명령 자체가 없습니다. 그렇다면 LaTeX의 xcolor 패키지는 무엇을 하는 걸까요. 출력 드라이버에게 쪽지를 남깁니다. \textcolor{red}{…}라고 쓰면 TeX은 “여기부터 빨강”이라는 \special을 출력 파일에 끼워 넣고, 실제로 색을 칠하는 일은 나중에 PDF를 만드는 쪽이 맡습니다. 이 사실 하나만 알면 LaTeX에서 색과 관련해 이해가 안 가던 일이 거의 다 설명됩니다. 이 페이지는 그 길을 차례로 따라갑니다. \usepackage{xcolor} 불러오기에서 시작해 \textcolor, \colorbox, \pagecolor, \definecolor와 색 모델, red!30!white 같은 혼색 표기, 그리고 마지막 함정——화면의 색은 인쇄기에서 나오는 색이 아니라는 사실——까지입니다.

\usepackage{xcolor}color 패키지의 차이: 무엇을 불러올까

답은 언제나 \usepackage{xcolor}입니다. xcolor는 David Carlisle의 color 패키지를 완전히 포함하는 상위 패키지로, color의 명령을 그대로 물려받은 위에 혼색, 추가 색 이름 집합, 모델 변환을 얹었습니다. 만든 사람은 Uwe Kern(2003–2021)이며 2021년부터는 LaTeX Project가 관리합니다. TeX Live 2024에 들어 있는 것은 v3.01(2023년 11월 15일) 입니다. 설계의 중심은 드라이버 비의존성 이어서, pdfTeX으로 조판하든 dvips를 거치든 같은 색 지정이 같은 방식으로 해석됩니다.

드라이버 비의존성에 대한 이 고집은 옵션 설계에 그대로 남아 있습니다. 옛 color 패키지는 dvips 계열 드라이버가 선택되면 dvipsnames의 68색을 말없이 켰습니다. 그 결과 내 컴퓨터에서는 잘 되다가 pdfTeX으로 바꾸는 순간 정의되지 않은 색으로 멈추는 문서가 만들어졌습니다. xcolor는 이 동작을 없앴습니다. dvipsnames라고 직접 쓴 사람에게만 색 이름을 내주는 대신, 그 이름들이 모든 드라이버에서 통하도록 했습니다. 아무 옵션 없이 쓸 수 있는 것은 19개의 기본 색이고, 필요에 따라 dvipsnames(68색), svgnames(151개 이름), x11names(317개 이름)를 얹습니다. 표에 색을 넣고 싶다면 table 옵션이 colortbl을 함께 데려옵니다.

preamble
\usepackage{xcolor}                   % 19 base colours, always available
\usepackage[dvipsnames]{xcolor}       % + 68 cmyk names from the dvips driver
\usepackage[svgnames]{xcolor}         % + 151 names from the SVG 1.1 spec
\usepackage[x11names]{xcolor}         % + 317 names from the X11 rgb.txt
\usepackage[dvipsnames,svgnames]{xcolor} % sets can be combined
\usepackage[table]{xcolor}            % also loads colortbl for coloured tables

\textcolor\color 의 차이, 그리고 \colorbox\fcolorbox

\textcolor{red}{문자} 는 인수로 넘긴 범위만 색칠하고, \color{red}감싸고 있는 TeX 그룹이 닫힐 때까지 색을 바꿔 두는 스위치입니다. 둘은 별개의 장치가 아닙니다. \textcolor는 중괄호를 대신 채워 준 \color일 뿐이며, xcolor 문서가 그렇게 설명하고 있습니다. 그래서 {\color{blue} …} 바깥의 { } 를 빠뜨리면 그 뒤 문서 전체가 파랗게 됩니다. 거꾸로 보면, 절이나 환경 안에서 쓴 \color는 그 환경이 끝날 때 저절로 원래대로 돌아온다는 뜻이기도 합니다. \textcolor는 여기에 더해 \leavevmode를 호출하므로 문단 맨 앞에 두어도 들여쓰기가 망가지지 않습니다.

document.tex
This word is \textcolor{red}{red}, the rest is not.

{\color{blue} Everything from here to the closing brace is blue.} Back to black.

% the whole box gets a background; the frame colour comes first
\colorbox{yellow}{highlighted}
\fcolorbox{red}{yellow}{red frame, yellow fill}

배경을 칠하는 것은 \colorbox{색}{문자} 이고, 테두리와 채우기를 따로 지정하는 것은 \fcolorbox{테두리색}{채움색}{문자} 입니다. 인수 순서는 “테두리가 먼저, 채우기가 나중”입니다. 여기에 빠지기 쉬운 함정이 하나 있습니다. \colorbox는 이름 그대로 상자 여서 내용이 행을 넘어가지 못합니다. 긴 문장에 강조를 넣으면 줄바꿈되지 않고 판면 밖으로 튀어나가며 Overfull \hbox 경고가 남습니다. 단어 몇 개를 도드라지게 하기에는 충분하지만, 문장 단위로 칠하고 싶다면 줄바꿈을 다룰 수 있는 soul\hl이나 tcolorbox 쪽으로 옮겨 가세요. 또한 다른 패키지의 색 인수——설명서가 직접 드는 예가 soul\sethlcolor 입니다——는 red!30!white 같은 색 표현식을 그대로 받지 못할 수 있습니다. 그럴 때는 \colorlet으로 이름을 붙인 뒤 그 이름을 넘깁니다.

명령하는 일적용 범위
\textcolor{c}{text}인수의 글자만 색 c로인수 안에서만
\color{c}이 지점부터 글자색을 c로 바꿈현재 TeX 그룹이 끝날 때까지
\colorbox{c}{text}글자 뒤에 c로 채운 상자를 둠상자 하나. 행을 넘지 못함
\fcolorbox{f}{b}{text}테두리는 f, 배경은 b로 감쌈위와 같음. 선 굵기는 \fboxrule
\pagecolor{c}페이지 전체 바탕색을 c로전역 선언. 이후의 모든 페이지
\nopagecolor바탕색을 지워 투명으로 되돌림모든 드라이버가 지원하지는 않으며 로그에 기록이 남음

\pagecolor 가 그룹을 무시하는 이유: 색은 \special 이기 때문

\pagecolor{black} 은 현재 페이지와 그 뒤의 모든 페이지 바탕색을 바꿉니다. 게다가 \color와 달리 이것은 TeX 그룹을 존중하지 않는 전역 선언 입니다. {\pagecolor{black} …} 라고 써도 닫는 중괄호에서 되돌아오지 않습니다. 되돌리려면 \nopagecolor(투명으로 복귀)나 \pagecolor{white} 를 명시적으로 놓아야 합니다. 표지만 검게 하려 할 때 가장 먼저 발목을 잡는 성질이라, \maketitle 바로 뒤에 취소를 넣어 두는 것이 정석입니다. 바탕색이 아니라 특정 페이지에만 테두리나 워터마크를 겹치고 싶다면 eso-pic 계열 도구가 더 적합합니다.

document.tex
\pagecolor{black}\color{white}
\maketitle
% \pagecolor is global: it must be cancelled by hand
\nopagecolor\color{black}

이 “전역” 성질은 예의 없음이 아니라, 첫머리에서 말한 \special의 본성 그 자체입니다. 색은 TeX의 상자 안에 담기지 않고, 출력 파일에 남겨진 쪽지일 뿐입니다. 그래서 페이지가 바뀌면 쪽지가 닿지 않습니다. 초기 pdfTeX에는 이 때문에 유명한 문제가 있었습니다. 색을 켠 채로 페이지를 넘기면 다음 페이지에서 색이 사라졌습니다. 대책으로 pdfcolmk라는 패키지가 LaTeX의 마크 기구를 이용해 “이 페이지는 이 색으로 시작한다”를 매 페이지 다시 적어 넣었을 정도입니다. 2007년에 나온 pdfTeX 1.40이 색 스택을 내장하면서 이 기교는 필요 없어졌습니다. 지금 pdfcolmk는 아무 일도 하지 않는 호환용 빈 패키지이고, xcolorfixpdftex 옵션도 Package option 'fixpdftex' is obsolete and ignored 라고 경고만 내는 유물입니다. 오늘날의 pdfLaTeX에서는 색이 페이지를 넘어 유지됩니다.

\definecolor\colorlet 을 나누어 쓰는 법

숫자에서 색을 만드는 것이 \definecolor{이름}{모델}{값}, 이미 있는 색에서 만드는 것이 \colorlet{이름}{색} 입니다. 브랜드 규정이 “#1B3A6B” 형태로 내려왔다면 앞쪽, “본문의 파랑을 조금 더 어둡게”라면 뒤쪽이라고 생각하면 헷갈리지 않습니다. 둘 다 프리앰블에 한 번만 써 두면 그 뒤로는 redblue와 같은 평범한 색 이름으로 행동합니다. \colorlet의 인수에는 다음 절에서 다룰 색 표현식을 그대로 넘길 수 있어서, 실무에서 가장 쓸모 있는 용도는 혼색에 이름을 붙이는 일 입니다. \colorlet{accent}{blue!30!black} 처럼 씁니다. 문서의 모든 색을 이런 이름을 거쳐 쓰도록 해 두면, 전체 색조 조정은 프리앰블 한 줄을 고치는 일로 끝납니다.

preamble
\definecolor{myblue}{rgb}{0.2,0.4,0.8}   % from numbers
\definecolor{brand}{HTML}{1B3A6B}        % from a web hex code
\colorlet{accent}{blue!30!black}         % from an existing colour
\colorlet{ruleline}{brand!25}            % a 25 % tint of the brand colour

rgb・RGB・HTML・cmyk・gray: 색 모델은 무엇을 고를까

\definecolor의 두 번째 인수가 색 모델, 곧 색을 숫자로 적는 방식입니다. 실무에서 고르는 기준은 단순합니다. 손에 있는 숫자의 형태에 맞추면 됩니다. 웹 색상 코드를 받았다면 HTML, 디자인 도구가 0–255로 내준다면 RGB, 인쇄소에서 4색 지정이 왔다면 cmyk입니다. xcolor는 내부에서 서로 변환하므로 같은 색을 다른 모델로 써도 결과는 같습니다.

모델값의 의미와 범위
rgb빨강・초록・파랑, 각각 소수 0–1{0.2,0.4,0.8}
RGB같은 세 값을 정수 0–255로{51,102,204}
HTML16진수 여섯 자리 RRGGBB. 앞의 # 는 붙이지 않음{FF8800}
cmyk시안・마젠타・노랑・검정, 각각 0–1. 인쇄용{0,0.5,1,0}
gray밝기 값 하나. 0이 검정, 1이 흰색{0.5}
Gray같은 밝기이나 정수. 기본 상한은 15{8}
hsb색상・채도・명도, 각각 0–1. 색상만 돌리기에 편리{0.6,0.8,0.9}
wave가시광 파장(nm), 363–814. 물리 도판에 적합{589}
named숫자 대신 기존 색 이름을 참조하는 유사 모델{Periwinkle}
preamble
% four spellings of one orange
\definecolor{o1}{rgb}{1,0.5,0}
\definecolor{o2}{RGB}{255,128,0}
\definecolor{o3}{HTML}{FF8000}
\definecolor{o4}{cmyk}{0,0.5,1,0}

% the model can also be given inline, in brackets, at the point of use
\textcolor[HTML]{FF8800}{a one-off orange}
\color[gray]{0.5}

모델은 쓰는 자리에서 대괄호로 직접 지정할 수도 있습니다. 한 번만 쓸 색이라 이름을 붙일 것도 없다면 \textcolor[HTML]{FF8800}{…}\color[gray]{0.5} 로 끝냅니다. 표에서 유별난 것은 wave입니다. 가시광 파장을 나노미터로 건네면 xcolor가 그 파장이 어떻게 보이는지 계산합니다. \definecolor{sodium}{wave}{589} 는 나트륨 D선의 노란 주황색이 됩니다. 광학이나 스펙트럼 도판의 색을 맞출 때 이보다 정직한 지정은 없습니다. 반대로 named는 숫자를 갖지 않는 유사 모델로, dvipsnames 같은 옵션으로 불러온 기존 색 이름을 참조하기 위한 것입니다. 평소에는 색 이름을 그대로 쓰면 충분합니다.

red!30!white! 는 무엇을 하는가: 색 표현식으로 색 섞기

! 는 혼합 비율을 가르는 기호로, 색A!숫자!색B 는 “A를 그 퍼센트만큼, 나머지를 B로” 라는 뜻입니다. red!50!blue 를 실제로 펼치면 rgb0.5,0,0.5 가 나옵니다. 빨강과 파랑이 정확히 반씩인 보라입니다. 색 B를 생략한 red!20 은 나머지가 흰색 으로 간주되어 1,0.8,0.8, 곧 빨강 20 %에 흰색 80 %인 옅은 분홍이 됩니다. 바로 이 지점에서 xcolorcolor와 결정적으로 갈라집니다. 색 이름을 끝없이 늘리지 않고도, 지금 가진 색에서 필요한 농도를 뽑아낼 수 있습니다.

  • red!50!blue — 빨강과 파랑을 반씩. 펼치면 rgb0.5,0,0.5
  • red!20 — 빨강 20 %, 나머지는 흰색. 옅은 색(틴트)을 만드는 정석
  • blue!30!black — 파랑 30 %, 검정 70 %. 어두운 색(셰이드)을 만드는 정석
  • -red — 앞의 마이너스는 보색. -red 는 정확히 시안(rgb0,1,1)
  • green!40!yellow!60 — 표현식은 연결할 수 있고 왼쪽부터 차례로 섞임
  • gray!15~gray!25 — 글자 뒤에 깔 때 적당한 농도. 원색 위에서는 읽기 어려움

색 표현식은 “색이 필요한 모든 자리”에서 통합니다. \textcolor{blue!30!black}{…}, \colorbox{yellow!40}{…}, \definecolor\colorlet 의 인수, 표를 칠하는 \rowcolor{gray!15} 까지 같은 표기입니다. 실무에서 효과가 큰 습관은 혼색을 본문 여기저기에 흩뿌리지 않고 \colorlet 으로 한 번만 이름을 붙여 두는 것입니다. accentaccent!15 두 개로 제목・상자・표 줄무늬까지 감당한다면, 색조 변경은 프리앰블 한 줄로 끝납니다. 반대로 blue!30!black 을 마흔 군데에 흩어 써 두면 나중에 색을 바꾸는 일이 찾아 바꾸기 노동이 됩니다.

preamble
\colorlet{accent}{blue!30!black}
\colorlet{accentbg}{accent!15}

% then, in the body
\textcolor{accent}{a heading}
\colorbox{accentbg}{a quiet highlight}
\fcolorbox{accent}{accentbg}{framed and filled}

쓸 수 있는 색 이름: 기본 19색에서 752색까지

옵션을 하나도 붙이지 않아도 다음 19색 은 언제나 쓸 수 있습니다. xcolor.sty 자체가 정의하므로 어떤 드라이버, 어떤 문서 클래스에서도 같은 이름이 통합니다. 색 표현식의 재료로도 이 19색이면 대체로 충분해서, gray!20 이나 blue!30!black 같은 표기에 익숙해지면 색 이름을 더 늘릴 필요가 크게 줄어듭니다.

  • black, blue, brown, cyan, darkgray, gray, green, lightgray, lime, magenta, olive, orange, pink, purple, red, teal, violet, white, yellow

그래도 모자라면 옵션으로 이름을 더합니다. dvipsnames 는 dvips 드라이버에서 온 68색(RoyalBlue, Periwinkle, BurntOrange 등, 모두 cmyk 로 정의)을, svgnames 는 SVG 1.1 명세의 이름에 X11에서 가져온 네 개를 더한 151개 이름을, x11names 는 X11의 rgb.txt 에서 가져온 317개 이름을 줍니다. 여기에 xcolor 설명서가 스스로 적어 둔 재미있는 주석이 있습니다. svgnames 의 151개 이름이 가리키는 색은 실제로 141가지뿐입니다. GrayGrey 처럼 철자만 다른 별칭이 같은 값을 가리키기 때문입니다. x11names 도 317개 이름에 315색입니다. 두 집합을 함께 불러오면 rgb.txt 의 752개 이름 전부에 손이 닿는다는 것이 설명서의 안내입니다.

이 색 이름들은 대소문자를 구별합니다. RoyalBlueroyalblue 라고 쓰면 ! Package xcolor Error: Undefined color 'royalblue'. 로 멈춥니다. 색 이름 집합을 아예 불러오지 않았을 때도——\usepackage{xcolor} 만 쓰고 Periwinkle 을 사용한 경우처럼——같은 오류가 납니다. 어느 이름이 어떤 색인지는 기억에 맡기지 말고 texdoc xcolor 로 설명서를 여는 편이 빠릅니다. 이름마다 인쇄된 색 견본이 나란히 실려 있습니다. 경계 하나를 알아 두면 좋습니다. 표의 행과 셀을 칠하는 \rowcolor, \cellcolor, \rowcolorsxcolor 가 아니라 colortbl 소관이며, \usepackage[table]{xcolor} 한 줄이면 둘 다 갖춰집니다. 자세한 내용은 색이 있는 표 페이지를 보세요.

상업 인쇄에 넘길 문서라면 rgb 로 적은 색이 그대로 찍혀 나오리라는 보장이 없습니다. 오프셋 인쇄는 cmyk 네 가지 잉크로만 색을 만들 수 있고, 그 재현 범위는 화면의 RGB보다 좁기 때문입니다. xcolorcmyk 옵션을 주면 문서의 모든 색이 변환되어, 예를 들어 blue{cmyk}{1,1,0,0} 이 됩니다. 화면에서 선명하던 파랑이 종이 위에서는 묵직한 보랏빛 남색으로 보이는 일——이런 차이는 드물지 않습니다. 넘기기 전에 \usepackage[cmyk]{xcolor} 로 한 번 조판해 교정쇄를 확인하거나, 처음부터 cmyk 로 색을 정의해 두는 편이 안전합니다.

한 걸음 더 깊은 함정은 색을 유일한 단서로 삼는 일 입니다. 빨간 행은 경고, 초록 행은 정상——이런 설계는 지면을 흑백으로 복사하는 순간, 색각 특성이 있는 독자 앞에서, 또는 전자잉크 화면에서 정보를 통째로 잃습니다. 웹 접근성 기준 WCAG가 “색의 사용”(성공 기준 1.4.1)에서 요구하는 것이 바로 이 점으로, 색은 반드시 기호・굵은 글씨・명시적 라벨 같은 다른 단서와 함께 써야 합니다. 다행히 확인 수단은 xcolor 자신이 가지고 있습니다. \usepackage[gray]{xcolor} 라고 쓰면 모든 색이 gray 모델로 변환되어(red{gray}{0.3} 이 됩니다) 흑백 프린터의 출력을 그대로 시험할 수 있습니다. 그 상태에서도 뜻이 전달된다면 그 문서는 색에 지나치게 기대고 있지 않습니다.

preamble
% convert every colour in the document to cmyk, for offset printing
\usepackage[cmyk]{xcolor}

% convert every colour to gray: a one-word black-and-white proof
\usepackage[gray]{xcolor}