카운터와 길이

LaTeX에는 값을 기억할 수 있는 두 종류의 “레지스터”(저장 위치)가 있습니다. 카운터는 정수를, 길이는 치수를 저장합니다. 장, 그림, 수식 번호는 카운터로 세고, 여백이나 박스 너비는 길이로 잽니다. 이 페이지는 직접 만든 카운터와 길이를 정의하고 조작하는 프로그래밍 기초를 다룹니다. 단위 자체와 \hspace/\vspace 같은 공백 명령은 별도 페이지(아래 링크)에 맡기고, 여기서는 세고, 재고, 기억하는 장치에 집중합니다.

카운터 — 정수 레지스터

카운터는 정수 하나를 기억하는 그릇입니다. LaTeX가 문서를 읽어 가면서 장이 시작되면 chapter를, 그림을 놓으면 figure를 하나씩 증가시키고 그 번호를 제목이나 캡션에 인쇄합니다. 이것들이 미리 정의된 표준 카운터이며, 직접 새 카운터를 만들 수도 있습니다.

새 카운터는 \newcounter{foo} 로 만듭니다. 만든 직후의 값은 0입니다. 이름은 문자만 사용하며(백슬래시 없음) 이미 존재하는 이름과 겹칠 수 없습니다. 핵심 추가 기능은 선택적 부모 지정인 \newcounter{foo}[⟨parent⟩] 입니다. 이렇게 하면 fooparent에 종속되어 parent가 한 번 증가할 때마다 foo가 자동으로 0으로 재설정됩니다. 절이 바뀔 때마다 하위 절 번호가 다시 시작되는 이유가 바로 이 구조입니다.

값을 바꾸는 명령은 세 가지입니다. \setcounter{foo}{3}foo에 3을 대입하고, \addtocounter{foo}{2} 는 현재 값에 2를 더하며(음수를 넘기면 뺄 수 있음), \stepcounter{foo} 는 1만 증가시킵니다. \stepcounter에는 중요한 부수 효과가 있습니다. 그 카운터의 자식으로 등록된 모든 카운터를 0으로 재설정합니다. 또한 \setcounter\addtocounter의 대입은 전역적이므로 그룹({ } 또는 환경)을 벗어나도 되돌아가지 않습니다.

가까운 친척인 \refstepcounter{foo} 도 증가와 자식 재설정까지는 같지만, 추가로 그 시점의 foo를 현재 참조 대상으로 설정합니다. 그래서 바로 뒤에 놓은 \label{…}foo의 인쇄 값(아래의 \thefoo)을 가리키고, \ref가 그 번호를 불러옵니다. LaTeX가 section, equation, figure를 증가시킬 때 내부적으로 쓰는 명령이 바로 \refstepcounter이므로, 제목이나 수식에 붙인 \label이 올바른 번호를 참조할 수 있습니다. 숫자만 내부적으로 진행시키려면 \stepcounter를, 참조 가능한 “번호 붙은 대상”을 만들려면 \refstepcounter를 사용합니다.

latex
\newcounter{trial}            % trial を作成(初期値 0)
\setcounter{trial}{5}         % trial = 5
\addtocounter{trial}{-2}      % trial = 3
\stepcounter{trial}           % trial = 4(子カウンタがあれば 0 に)

카운터의 “숫자” 꺼내기 — \value

\value{foo} 는 카운터의 내용을 TeX가 계산에 사용할 수 있는 숫자로 꺼냅니다. \setcounter/\addtocounter의 값 위치, \ifnum 조건 판정, 나아가 \value{foo}\parindent 같은 치수 계산처럼 LaTeX가 정수를 기대하는 곳 어디서든 사용할 수 있습니다. 예를 들어 barfoo와 같은 값으로 맞추려면 이렇게 씁니다.

latex
\setcounter{bar}{\value{foo}}        % bar に foo の現在値を代入
\addtocounter{bar}{\value{foo}}      % bar に foo の値をさらに加える

초보자가 자주 막히는 지점입니다. \value는 표시용이 아닙니다. 본문에 번호를 실제로 *인쇄*하려면 다음 절의 \arabic 같은 표시 명령이나 \thefoo를 사용합니다. 이렇게 구분하면 됩니다. \value는 계산을 위한 원시 숫자를 주고, 표시 명령은 사람이 읽을 문자열을 줍니다. 둘을 분리해 두면 혼란이 사라집니다.

카운터 표시하기 — \the와 형식 명령

모든 카운터에는 값을 인쇄할 문자열로 바꾸는 표시 명령 묶음이 있습니다. 어떤 표기법으로 찍을지 선택할 수 있습니다.

명령출력범위 / 비고
\arabic아라비아 숫자(1, 2, 3 …)가장 일반적이며 음수도 허용
\roman소문자 로마 숫자(i, ii, iii …)1보다 작으면 아무것도 출력하지 않음
\Roman대문자 로마 숫자(I, II, III …)1보다 작으면 아무것도 출력하지 않음
\alph소문자(a, b, c …)1–26, 범위를 벗어나면 오류
\Alph대문자(A, B, C …)1–26, 범위를 벗어나면 오류
\fnsymbol각주 기호(∗ † ‡ § ¶ ‖ …)1–9, 수식 모드용

\alph/\Alph 는 26개 알파벳에 대응하므로 값이 1보다 작거나 26보다 크면 “Counter too large” 오류가 납니다. \fnsymbol 은 별표, 단검표, 이중 단검표, 절 기호, 단락 기호, 평행 기호, 이중 별표, 이중 단검표, 이중 이중 단검표의 9개 각주 기호를 순서대로 내며, 유효 범위는 1–9입니다. 수식 모드에서 동작하므로 본문에서는 $\fnsymbol{footnote}$처럼 감싸거나 \thefootnote를 통해 사용합니다.

이 명령들은 인수로 카운터 이름을 받습니다(\arabic{page}처럼). 하지만 실제 조판에서 번호를 찍는 것은 각 카운터에 자동으로 마련되는 전용 매크로 \thefoo 입니다. section에는 \thesection, figure에는 \thefigure가 있는 식입니다. \the…\renewcommand로 재정의하면 번호 형식 전체를 바꿀 수 있습니다. 예를 들어 절 번호를 로마 숫자로 만들려면 한 줄이면 됩니다.

latex
\renewcommand{\thesection}{\Roman{section}}   % 1, 2, 3 → I, II, III
% 図番号を「節.通し番号」に:図 2.3 のように
\renewcommand{\thefigure}{\thesection.\arabic{figure}}

두 번째 예처럼 \the… 정의에 다른 카운터의 표시를 섞으면 “2.3” 같은 복합 번호를 만들 수 있습니다. 이것이 동작하는 이유는 그림 카운터가 절 카운터를 부모(재설정 트리거)로 갖도록 설정되어 있기 때문입니다. 즉 번호의 모양과 언제 0으로 돌아갈지에 대한 연동은 서로 따로 정해진다는 설계를 볼 수 있습니다.

표준 카운터와 번호 깊이

LaTeX는 몇 가지 카운터를 미리 정의하고 문서 안에서 자동으로 움직입니다. 이들도 \setcounter 등으로 자유롭게 조작할 수 있습니다. 예를 들어 중간에서 장 번호를 다시 매기거나, 부록의 그림 번호를 A.1처럼 만들 수 있습니다.

  • 제목 계층: part, chapter, section, subsection, subsubsection, paragraph, subparagraph(사용 가능 여부는 클래스에 따라 다름)
  • 플로트와 수식: figure, table, equation
  • 각주: footnote, mpfootnote(minipage 안의 각주)
  • 목록: enumi, enumii, enumiii, enumiv(enumerate의 네 단계 중첩)
  • 페이지: page
  • 제어: secnumdepth(어느 깊이까지 제목에 번호를 붙일지)와 tocdepth(어느 깊이까지 목차에 실을지)

마지막 두 가지는 성격이 조금 다릅니다. 번호와 목록의 “깊이”를 정수로 제어하는 스위치입니다. 각 제목 명령에는 레벨 번호가 있으며(section은 1, subsection은 2, …), 그 레벨이 secnumdepth이하일 때 번호가 붙습니다. 기본값은 대략 2라서 \setcounter{secnumdepth}{1}이면 절 아래의 번호가 빠지고, \setcounter{tocdepth}{1}이면 목차가 절까지만 좁혀집니다. 카운터가 단순한 세기뿐 아니라 조판 동작을 이끄는 설정값이 되기도 한다는 좋은 예입니다.

길이 — 치수 레지스터

다른 한쪽인 길이(length)12pt2cm처럼 치수 하나를 기억하는 레지스터입니다. 카운터가 정수인 것과 달리 길이는 단위가 있는 치수를 보관하며, 늘어남과 줄어듦(plus/minus)도 가질 수 있습니다. 같은 치수를 문서 여러 곳에서 쓴다면 숫자를 직접 박아 넣는 것보다 길이에 이름을 붙여 두는 편이 훨씬 유지보수하기 쉽습니다.

새 길이는 \newlength{\mylen} 로 선언합니다. 카운터와 달리 인수는 백슬래시가 붙은 명령 이름(\mylen)이며, 초기값은 0pt입니다. 기본 조작은 두 가지입니다. \setlength{\mylen}{2em}(대입)과 \addtolength{\mylen}{-3pt}(더하기, 음수면 빼기)입니다. 한 번 만들면 \hspace{\mylen}처럼 치수가 필요한 곳 어디에서나 사용할 수 있습니다.

\textwidth(본문 폭)이나 \baselineskip(기준선 간격) 같은 기존 길이도 그대로 계산에 쓸 수 있습니다. 앞에 계수를 붙이면 0.8\textwidth(본문 폭의 80%)처럼 배율을 지정할 수 있고, 길이끼리 직접 더하거나 뺄 수도 있습니다. 더 풍부한 산술, 특히 나눗셈이 필요하면 calc 패키지를 불러옵니다. 그러면 \setlength{\x}{\textwidth/3}(본문 폭의 1/3)처럼 치수를 정수로 나누는 식을 그대로 쓸 수 있습니다.

calc에는 한 가지 주의점이 있습니다. 치수를 실수 배율로 곱하고 싶을 때는 정수 나눗셈과 쓰는 방식이 달라서 \real{}을 끼워 넣습니다(예: \widthof{word} * \real{0.68}). 또한 식의 타입이 맞아야 합니다. 2cm + 4(치수에 단위 없는 정수를 더함)는 불법이고, 2cm + 4pt처럼 양쪽이 모두 치수이면 괜찮습니다.

document.tex
\usepackage{calc}
\newlength{\thirdcol}
\setlength{\thirdcol}{\textwidth/3}     % 本文幅の 1/3
\addtolength{\thirdcol}{-1em}            % そこから 1em 引く

조판된 내용을 재기 — \settowidth 등

길이 조작에서 특히 강력한 것은 실제로 조판한 결과의 치수를 재서 길이에 대입하는 명령입니다. \settowidth{\mylen}{text} 는 주어진 텍스트를 내부적으로 조판하고 그 너비\mylen에 넣습니다. 마찬가지로 \settoheight 는 기준선 위의 높이를, \settodepth 는 기준선 아래의 깊이를 잽니다(모두 미리 \newlength로 선언한 길이를 대상으로 합니다).

이는 내용에 맞는 치수가 필요할 때 빛을 발합니다. “이 제목 단어와 정확히 같은 너비의 선을 긋고 싶다”거나 “가장 긴 항목명에 맞춰 라벨 너비를 정하고 싶다” 같은 경우입니다. 아래 예시는 단어의 너비를 재고 그 아래에 같은 길이의 선을 놓습니다.

document.tex
\newlength{\wd}
\settowidth{\wd}{重要}        % 「重要」の組版幅を測る
\noindent 重要\par
\rule{\wd}{0.4pt}            % 同じ幅の罫線

같은 “조판해서 재기” 발상은 앞서 언급한 calc 패키지의 \widthof{text}/\heightof/\depthof 에도 이어집니다. 차이는 \settowidth가 결과를 길이에 대입하는 명령인 반면, \widthof는 식 안에 그대로 값으로 쓸 수 있다는 점입니다.

조합 예 — 직접 만든 카운터와 측정한 길이

마지막으로 카운터와 길이를 둘 다 쓰는 작은 예를 보겠습니다. 사용자 카운터 question을 만들고 표시 형식을 “Q1.”, “Q2.”, …로 맞춘 다음, 호출할 때마다 번호를 진행하고 인쇄하는 간단한 명령 \question을 정의합니다. \refstepcounter를 사용하므로 각 질문에 \label을 붙이고 나중에 \ref로 참조할 수 있습니다.

document.tex
\newcounter{question}
\renewcommand{\thequestion}{Q\arabic{question}}
\newcommand{\question}{\refstepcounter{question}\par\noindent\textbf{\thequestion.}\ }
\begin{document}
\question 最初の問い。\label{q:first}
\question 次の問い。
問い~\ref{q:first} を参照。   % → 問い Q1 を参照
\end{document}

\thequestion\renewcommand로 정의했기 때문에 번호 형식(Q + 아라비아 숫자)이 한곳에 모이고, 나중에 바꾸기도 쉽습니다. 길이에서도 같은 감각이 통합니다. 본문 폭(\textwidth)을 기준으로 상대적인 치수를 만들거나, 내용을 \settowidth로 재서 치수를 정하면 종이 크기나 여백이 바뀌어도 비율이 무너지지 않는 문서가 됩니다. 고정값을 직접 적어 넣기보다 이름을 붙이고 한곳에서 관리하는 것. 이것이 카운터와 길이를 프로그래밍 도구로 쓰는 요령입니다.