색 있는 표(colortbl)

LaTeX 표에 색을 입히는 colortbl 패키지는 셀의 배경을 칠하는 것이 아닙니다. 셀 뒤에 색 패널을 깔아 둡니다. 작성자인 David Carlisle이 자신의 문서에 그렇게 써 놓았습니다. 표의 색과 관련해 이해가 안 가는 현상은 거의 전부 이 한 문장에서 나옵니다. \cline을 분명히 썼는데 선이 보이지 않는 이유도, booktabs와 함께 쓰면 색과 선 사이에 흰 띠가 남는 이유도 여기에 있습니다. 이 페이지는 \usepackage[table]{xcolor} 한 줄에서 출발해 \rowcolor(행), \columncolor(열), \cellcolor(셀), 줄무늬를 만드는 \rowcolors, 선에 색을 입히는 \arrayrulecolor 를 차례로 살펴보고, 마지막에는 booktabs 쪽의 반론, 곧 애초에 색을 쓰지 말라는 주장까지 따라갑니다.

표에 색을 넣으려면 어떤 패키지가 필요한가

필요한 것은 \usepackage[table]{xcolor} 한 줄뿐입니다. colortbl을 따로 불러올 이유는 없습니다. xcolortable 옵션colortbl을 자동으로 끌고 오기 때문입니다. 반대로 \usepackage{colortbl}만 쓸 수도 있지만, 그러면 색 이름 이 모자랍니다. colortbl이 내부적으로 요구하는 것은 arraycolor 두 가지인데, color는 이름을 거의 정의하지 않아서 \rowcolors{2}{gray}{white}라고 쓰는 순간 ! LaTeX Error: Undefined color 'gray'. 로 멈춥니다. 색 이름과 색 혼합을 가져다주는 것이 바로 xcolor의 역할이므로, 실무에서는 결국 [table]이 붙은 한 줄로 정착합니다.

preamble
% one line brings in both xcolor and colortbl
\usepackage[table]{xcolor}

beamer만 쓰는 방식이 달라서, 클래스 옵션으로 \documentclass[xcolor=table]{beamer}처럼 넘깁니다. 색 자체는 xcolor 표기가 그대로 통하므로 gray, red 같은 이름뿐 아니라 gray!20(농도 20%)이나 red!30!yellow(빨강 30%에 노랑 70% 혼합)도 쓸 수 있습니다. 글자 뒤에 원색을 깔면 글자가 읽히지 않으므로, 표의 바탕색은 name!15에서 name!25 정도의 옅은 지정이 실용적인 범위입니다.

Option clash for package xcolor 가 날 때와, 이제 나지 않게 된 이유

! LaTeX Error: Option clash for package xcolor. 는 표에 색을 넣을 때 가장 자주 밟는 지뢰였습니다. 원인은 간단합니다. tikz, pgfplots, beamer 등이 먼저 옵션 없는 xcolor 를 불러온 탓에, 나중에 쓴 \usepackage[table]{xcolor}가 “같은 패키지를 다른 옵션으로 다시 불러왔다”고 판정되기 때문입니다. 그런데 xcolor 3.00(2023년 11월 11일) 에서 사정이 달라졌습니다. 이 버전부터 table은 불러오기 옵션이 아니라 LaTeX의 새 키/값 처리기로 선언된 프리앰블 키 이므로, 이미 불러온 xcolor에 나중에 적용할 수 있습니다. TeX Live 2024 환경에서 tikz를 먼저 불러온 뒤 \usepackage[table]{xcolor}를 써도 오류가 나지 않습니다. 같은 실험을 geometry로 하면 여전히 Option clash for package geometry. 에서 멈춥니다.

따라서 웹에 남아 있는 “[table]을 클래스 옵션으로 올려라”라는 정석 조언은 이제 오래된 환경을 위한 대처법입니다. 그래도 낡은 TeX Live나 배포본을 상대할 일은 남아 있으므로 대처 순서만은 기억해 두면 안전합니다. 먼저 클래스 옵션으로 옮깁니다. \documentclass[table]{article}처럼 쓰면 누구보다 먼저 지정할 수 있습니다. 그래도 안 되면 \usepackage{colortbl}을 직접 불러옵니다. 충돌하는 것은 xcolor의 옵션이지 colortbl이 아닙니다. 또한 xcolor 3.00의 새 기능은 LaTeX 2022-06-01 이후 에서만 작동하며, 그보다 오래된 포맷에서는 자동으로 동결 버전이 쓰입니다. 반대로 새 동작 때문에 기존 문서가 망가진다면 \usepackage{xcolor}[=v2]라고 써서 구 버전을 명시적으로 되부를 수 있습니다.

\rowcolor, \columncolor, \cellcolor 의 차이와 놓는 위치

세 명령은 칠하는 범위만 다른 것이 아니라 쓰는 자리도 셋 다 다릅니다. \rowcolor{color}행의 맨 앞, 곧 그 행 첫 셀의 내용보다 앞, 바로 앞 \\ 직후에 놓습니다. \columncolor{color} 는 표 본문이 아니라 열 지정 안>{\columncolor{gray!20}} 형태로 씁니다. >{…}array 패키지가 제공하는 훅으로 그 열의 각 셀 바로 앞에 내용을 끼워 넣으며, colortbl 은 여기에 얹혀 갑니다. \cellcolor{color} 만 자유로워서 대상 셀 안이라면 어디에 써도 적용됩니다. 이 비대칭은 외우기 까다롭지만 이유는 분명합니다. 행은 시작하는 순간에만 붙잡을 수 있고, 열은 표가 시작되기 전에만 선언할 수 있기 때문입니다.

세 명령의 인수 형태는 같아서 \columncolor[model]{color}[left overhang][right overhang] 처럼 색 이름 앞에 색 모델 선택 인수를, 뒤에 좌우 돌출(overhang) 선택 인수를 둘 수 있습니다. 돌출은 색 패널을 열의 좌우로 어디까지 넓힐지 정합니다. 오른쪽을 생략하면 왼쪽 값을 그대로 쓰고, 둘 다 생략하면 tabular에서는 \tabcolsep, array에서는 \arraycolsep가 쓰입니다. 둘 다 0pt로 하면 패널이 열 내용의 너비에서 정확히 잘립니다. 셀 사이에 흰 줄이 생기는 원인은 대개 이것이므로, 이웃한 색을 이어 붙이고 싶다면 오히려 돌출을 늘려야 합니다.

latex
\begin{tabular}{>{\columncolor{gray!20}}l c r}
  \rowcolor{blue!30}
  Item & Qty & Price \\
  Apple  & 3 & 380 \\
  Orange & \cellcolor{yellow!40}5 & 120 \\
\end{tabular}

이 세 명령은 한 번에 설계된 것이 아니라 이십 년에 걸쳐 덧붙여졌습니다. colortbl의 첫 초고는 1996년 9월 20일 자이고, 그때 있던 것은 \columncolor 하나뿐이었습니다. \rowcolor는 보름 뒤인 1996년 10월 5일에 추가되었는데, 변경 기록에는 “S. Rahtz를 기쁘게 하려고”라고 적혀 있습니다. TeX 세계의 거물 Sebastian Rahtz를 가리킵니다. \cellcolor는 그로부터 다시 오 년이 지난 2001년 2월 13일에 Donald Arseneau 의 기여로 들어왔습니다. 그전까지 셀 하나를 칠하려면 \multicolumn{1}{>{\columncolor{…}}c}{…}라고 쓸 수밖에 없었고, Carlisle은 이 방식의 결점을 셋 꼽습니다. 셀의 내용이 색칠 발동을 방해할 수 있다는 점, 열 정렬 지정을 손으로 옮겨 적어야 해서 특히 p{} 열에서 틀리기 쉽다는 점, 그리고 셋째로 \multicolumn{1} 자체가 우스꽝스럽다는 점입니다. 셀 하나를 칠할 때는 망설임 없이 \cellcolor를 씁니다.

색이 겹치면 무엇이 이기는가: 셀>행>열

\cellcolor\rowcolor를 덮어쓰고, \rowcolor\columncolor를 덮어씁니다.셀>행>열 입니다. 범위가 좁은 지정일수록 강하다는, 직관 그대로의 순서라서 새로 외울 것이 없습니다. 이 순서 덕분에 열 전체에 옅은 회색을 깔고, 머리글 행만 파랗게 하고, 눈에 띄게 하고 싶은 셀 하나만 노랗게 하는 세 겹 쌓기를 충돌 걱정 없이 쓸 수 있습니다. 설계상으로는 넓은 범위의 지정을 “기본값”, 좁은 지정을 그에 대한 “예외”로 다루는 구조라고 읽으면 이해가 쉽습니다.

명령칠하는 대상놓는 위치
\columncolor{c}열 전체열 지정의 >{…}
\rowcolor{c}행 전체행의 시작, 첫 셀 앞
\cellcolor{c}단일 셀그 셀 안 어디든
\rowcolors{n}{a}{b}행 교대(줄무늬)표 앞에 한 번
\arrayrulecolor{c}이후의 모든 선표 밖, 행 시작, 또는 >{}
\doublerulesepcolor{c}이중선 사이의 틈\arrayrulecolor와 같은 자리

\rowcolors 로 한 줄 걸러 줄무늬 자동 생성

한 줄 걸러 색이 바뀌는 줄무늬는 표 \rowcolors{start}{odd-row color}{even-row color} 를 한 번 쓰기만 하면 됩니다. 끝의 s 가 중요합니다. s 없는 \rowcolor는 행 하나를 칠하는 별개의 명령입니다. 첫 인수는 색칠을 시작할 행 번호이므로, 머리글 행을 그대로 통과시키려면 2를 넘깁니다. 두 색 인수는 모두 비울 수 있고, 비우면 “색 없음”입니다. 여기서 검색으로 나오는 옛 글들과 어긋나는 점이 하나 있습니다. \rowcolors는 더 이상 xcolor의 명령이 아닙니다. 2022년 6월 20일 자 colortbl 1.0f에서 코드가 xcolor에서 colortbl로 옮겨졌고, xcolor 3.00의 변경 기록에도 이관이 명시되어 있습니다. 쓰는 방식은 그대로지만, 지금은 \usepackage{colortbl}만으로도 \rowcolors가 정의된다는 사실은 알아 두면 쓸모가 있습니다.

latex
% start striping at row 2, so the header stays plain
\rowcolors{2}{gray!15}{white}
\begin{tabular}{l r r}
  Item & Qty & Price \\
  Apple  & 3 & 380 \\
  Orange & 5 & 120 \\
  Grape  & 2 & 600 \\
  Peach  & 4 & 450 \\
\end{tabular}

줄무늬는 전부 아니면 전무가 아닙니다. 먼저 \rowcolors에는 앞쪽 선택 인수가 있어서 \rowcolors[\hline]{2}{…}{…}처럼 쓰면 각 행 앞에 \hline 같은 명령을 실행시킬 수 있습니다. 다음으로, 자동 줄무늬보다 명시적인 \rowcolor\multicolumn 지정이 우선 하므로 줄무늬 도중 한 행만 다른 색으로 바꾸는 것도 자연스럽게 쓸 수 있습니다. 그리고 줄무늬를 일시적으로 멈추기 위한 \hiderowcolors\showrowcolors 가 있어서, 표 중간에 두면 그 지점부터 무늬를 지우거나 다시 시작할 수 있습니다. “합계 행만 줄무늬에서 빼고 싶다” 같은 요구는 이것으로 해결됩니다.

선에 색 입히기: \arrayrulecolor\doublerulesepcolor

\hline, \cline, 세로줄 | 의 색은 \arrayrulecolor{color} 로 바꿉니다. \color와 같은 인수를 받는 전역 선언 이라서 표 밖, 행의 시작, 열 지정의 >{} 어디에나 놓을 수 있습니다. 여기에 함정이 하나 있습니다. 표 중간에 지정하면 그 뒤에 지정된 선에만 미치고, 열 지정 단계에서 이미 선언된 세로줄은 원래 색을 그대로 유지합니다. 전역 선언이므로 표를 빠져나온 뒤에도 계속 작동한다는 점도 주의해야 하며, 이후의 표까지 끌려들게 하고 싶지 않다면 \arrayrulecolor{black}을 다시 선언해 되돌립니다.

||\hline\hline 이 만드는 이중선 사이의 틈 은 기본적으로 흰색 그대로입니다. 이곳도 칠하려면 틈의 폭을 정하는 길이 \doublerulesep 와 함께 \doublerulesepcolor{color} 를 씁니다. 다만 이 명령을 쓰면 longtable 이 페이지 경계에서 \hline\hline 사이의 공간을 더 이상 버리지 못합니다. TeX에는 공간(glue)을 버리는 장치가 있지만, 색을 입힌 “공간”은 실제로는 세 번째 선이고 선은 공간만큼 쉽게 버릴 수 없기 때문입니다. 긴 표를 여러 쪽에 걸쳐 나눌 예정이라면 이 점은 미리 알아 두는 편이 안전합니다.

latex
\setlength\arrayrulewidth{1pt}\arrayrulecolor{blue}
\setlength\doublerulesep{2pt}\doublerulesepcolor{yellow}
\begin{tabular}{||l|c||}
  \hline\hline
  one & two \\
  three & four \\
  \hline\hline
\end{tabular}
\arrayrulecolor{black} % global: reset, or later tables inherit it

세로줄 하나만 색을 입히고 싶다면 전용 명령을 꺼내지 않고 | 대신 !{\color{green}\vline} 을 열 지정에 끼워 넣는 방법이 있습니다. 사소하지만 실용적인 점 하나. \arrayrulewidth 는 선의 두께를 정하는 길이인데, 기본 굵기 그대로 색을 입히면 선이 무척 약해 보입니다. 검정일 때는 충분했던 두께가 밝은 색으로 바꾸는 순간 지면에서 사라지기도 합니다. 색을 입혔다면 선을 조금 두껍게 한다고 기억해 두면 겉모습이 안정됩니다.

\cline 이 보이지 않는 이유: 선이 색 패널 뒤에 가릴 때

\rowcolor 를 깐 표에서 \cline 을 그으면 선이 전혀 보이지 않습니다. 버그가 아니라 첫머리에서 말한 구조의 필연입니다. colortbl 은 색을 패널로 셀 뒤에 까는데, \cline 은 그 패널보다 더 뒤에 그려지므로 색에 덮여 버립니다. Carlisle은 소스의 주석에서 \cline 이 색을 입힌 표에서는 사실상 작동하지 않음을 인정하면서, 적어도 보이는 부분만이라도 색은 맞춰 두겠다고 적었습니다. 회피책은 분명합니다. \cline 대신 hhline 패키지 를 불러와 \hhline{-~} 처럼 씁니다. - 는 선을 그을 열, ~ 는 건너뛸 열을 뜻합니다. 이렇게 하면 선이 패널 위에 그려져 제대로 보입니다.

latex
% \cline{1-1} would vanish behind the panel; \hhline draws on top
\usepackage{hhline}
...
\begin{tabular}{ll}
  \rowcolor{blue!40} one & two \\
  \hhline{-~}
  \rowcolor{blue!40} three & four \\
\end{tabular}

booktabs 와 함께 쓸 때 선과 배경색 사이에 생기는 흰 틈

colortblbooktabs 는 문제없이 함께 쓸 수 있지만, \toprule, \midrule, \bottomrule 과 배경색 사이에 흰 띠 가 남습니다. 원인은 booktabs 가 선의 위아래에 넣는 공간으로, 기본값은 \aboverulesep.4ex, \belowrulesep.65ex 입니다. 이 공간은 행 상자의 바깥에 있어서 \rowcolor 의 패널이 닿지 않습니다. 채움이 선까지 닿게 하려는 정석은 두 공간을 0pt 로 만들고 잃어버린 높이를 \extrarowheight 로 옮기는 것입니다. 행 높이는 그대로 유지되고 색만 바뀌어 이제 선에 맞닿습니다.

latex
% let the row color reach the booktabs rules
\setlength\aboverulesep{0pt}
\setlength\belowrulesep{0pt}
\setlength\extrarowheight{.75ex}

또 하나의 전형적인 증상은 큰 글자나 높이가 큰 내용이 바로 위의 \hline 또는 색 패널의 윗변에 닿는 것입니다. colortbl 은 애초에 선의 너비를 정하려고 셀을 하나하나 상자에 담아 재고 있으므로, 그 김에 마련된 것이 길이 \minrowclearance 입니다. \setlength\minrowclearance{2pt} 처럼 설정하면 높은 행 위에만 약간의 여백이 들어갑니다. 다만 Carlisle 본인은 행간을 고르게 유지한 채 해결할 수 있는 \extrarowheight\arraystretch 를 먼저 늘리는 편이 낫다고 적었습니다. 대문자 높이에 이 값을 더한 것이 보통 행 높이를 넘으면 줄 사이가 눈에 띄게 들쭉날쭉해지기 때문입니다.

마지막으로 애초에 색을 써야 하는가라는 물음을 남겨 둡니다. booktabs 를 쓴 Simon Fear 의 입장은 분명했습니다. 좋은 표는 여백과 몇 개의 가로선 으로 읽히며, 세로선은 절대 쓰지 않는다, 이중선도 쓰지 않는다는 두 지침만 지키면 크게 어긋나지 않는다는 것입니다. 그는 이름표가 붙은 열에 값을 늘어놓은 “formal table(정식 표)” 과, 아이콘이 흩어져 있고 색도 쓸 법한 “tableau” 를 구분하면서, 앞의 것의 판면은 수 세기의 경험으로 확립된 것이니 어지간해서는 바꿀 일이 아니라고 말합니다. 참고로 booktabs 의 버전 번호는 1.61803398 입니다. 황금비 φ 로 수렴해 간다는 작성자의 장난입니다. 표에 색을 깔기 전에, 행 높이와 선 두어 개만으로 풀리지는 않았을지 한 번쯤 의심해 볼 가치가 있습니다.