문서 클래스와 프리앰블

1994년 6월 1일, LaTeX은 명령 하나를 둘로 나누었습니다. 그 뒤로 모든 LaTeX 문서는 똑같은 방식으로 시작합니다. \documentclass 한 줄, 그리고 \usepackage 선언이 이어지는 프리앰블입니다. 그전에는 \documentstyle[12pt,twoside]{article}처럼 쓰면서 옵션과 추가 스타일을 같은 대괄호 안에 몰아넣었습니다. 문서 클래스와 패키지를 갈라놓은 것은 정리 정돈이 아니었습니다. 클래스는 문서가 무엇인지(논문인지 보고서인지 책인지 슬라이드인지)를 정하고, 프리앰블은 문서가 무엇을 할 수 있는지를 정합니다. 이 경계를 제대로 그으면 학술지는 한 줄만 고쳐 원고 전체를 다시 조판할 수 있고, 잘못 그으면 글을 쓰려던 저녁이 Option clash for package geometry를 쫓다가 사라집니다.

\documentclass가 실제로 정하는 것

\documentclass[options]{class}는 문서에서 맨 앞에 와야 하는 유일한 명령이며, 그 앞에 올 수 있는 것은 %로 시작하는 주석뿐입니다. 중괄호 안은 클래스 이름, 대괄호 안은 옵션이고, 중괄호 속 이름은 실제로 존재하는 파일을 가리킵니다. article이라고 쓰면 article.cls가 읽히는데, 수백 줄짜리 정의 모음이며 그 안에는 규칙만 들어 있습니다. 예를 들어 \section 제목은 \Large\bfseries로 조판하고 위에 3.5ex, 아래에 2.3ex를 둡니다. 이 세 값이 article.cls에 그대로 적혀 있습니다. 정작 본문은 한 글자도 그 안에 없습니다.

이 분업은 우연이 아닙니다. 1980년대 초 레슬리 램포트는 책을 쓰기 시작한 참에 당시 쓰이던 매크로 패키지가 부족하다고 느꼈고, 어차피 직접 매크로를 짜야 한다면 조금만 더 손보면 다른 사람도 쓸 수 있겠다고 생각했습니다. 2000년 1월 DMV-Mitteilungen 인터뷰에서 그는 그것이 LaTeX의 출발점이었다고 말합니다. 그러니 클래스란 구조와 외형의 분리를 그대로 파일로 만든 것입니다. 본문에는 \section{Introduction}, 곧 의미만 씁니다. 그것을 크고 굵게 조판하고 번호를 붙이고 위에 공백을 두는 일은 클래스의 몫입니다. 학회와 출판사가 자체 클래스를 배포하는 이유가 바로 이것이며, amsart, IEEEtran, elsarticle, revtex4-2, acmart는 모두 실제로 존재하고 투고 규정으로 지정되기도 합니다. 램포트 자신도 1980년대 후반에 ACM에 전자 투고를 빠르게 돌리기 위해 TeX/LaTeX, troff, Scribe 각각의 표준 문서 스타일을 만들자고 제안했습니다. ACM 편집자에게 거절당하기는 했지만 말입니다.

latex
% Only the first line changes; the body stays as it is.
\documentclass[11pt,a4paper]{article}  % top level heading is \section
% \documentclass[11pt,a4paper]{book}   % \chapter becomes available

\begin{document}
\section{Introduction}
The source carries the structure; the class supplies the appearance.
\end{document}

article, report, book은 무엇이 다른가

실질적인 차이는 두 가지, 장이 있는지양면 인쇄를 전제하는지입니다. article.cls에는 \chapter 정의가 아예 없어 최상위 제목이 \section이고, report.clsbook.cls에는 있습니다. 기본값은 각 클래스 파일의 \ExecuteOptions 줄에 그대로 적혀 있습니다. articleletterpaper,10pt,oneside,onecolumn,final, report는 거기에 openany가 붙고, booktwosideopenright로 바뀝니다. 놓치기 쉬운 것은 용지입니다. 셋 다 기본이 letterpaper이므로 A4를 쓰려면 a4paper를 직접 적어야 합니다. 제목 처리도 갈립니다. article은 첫 페이지 위쪽에 이어서 나오고, reportbook은 제목이 한 페이지를 차지합니다.

클래스알맞은 문서장과 기본값
article논문, 노트, 짧고 중간 길이의 일반 문서\chapter 없음. oneside, onecolumn, notitlepage
report기술 보고서, 학위논문, 여러 장으로 나뉜 긴 문서\chapter 있음. oneside, openany, 별도 제목 페이지
book본격적인 책\chapter 있음. twoside, openright, 장은 오른쪽 페이지에서 시작
letter편지절 구분 없음. \address, \signature, \opening, \closing

book에는 알아 둘 장치가 하나 더 있습니다. \frontmatter / \mainmatter / \backmatter 로, 종이책의 관습을 각각 한 줄 남짓으로 구현합니다. \frontmatter\pagenumbering{roman}을 불러 서문과 목차를 소문자 로마 숫자(i, ii, iii…)로 만들고 장 번호를 끕니다. \mainmatter\pagenumbering{arabic}으로 쪽 번호를 1부터 다시 매기고 장 번호를 되살립니다. \backmatter는 아라비아 숫자 쪽 번호는 그대로 두고 장 번호만 다시 없애므로, 색인이 “제12장 색인”이 되지 않습니다. 서문은 i, ii, iii이고 본문은 다시 1부터 시작하는 책은 모두 이 세 줄의 결과입니다.

표준 네 가지로 부족하다면 CTAN에 목적별 클래스가 거의 다 있습니다. 발표 자료라면 beamer가 정석입니다. frame 환경 하나가 슬라이드 한 장이 되고, 단계적 표시(오버레이)와 테마가 함께 딸려 옵니다. 표준 클래스의 기본 타이포그래피가 낡아 보인다면 KOMA-Scriptscrartcl / scrreprt / scrbook이 각각 article / report / book에 대응하며, 세부 조정을 위한 인터페이스가 훨씬 풍부합니다. 일본어 조판에서는 pLaTeX / upLaTeX용으로 오쿠무라 하루히코와 texjporg 팀이 관리하는 jsarticle / jsbook(jsclasses), LuaLaTeX용으로 그 LuaTeX-ja 판인 ltjsarticle / ltjsbook, 그리고 “일본어 조판 처리 요건(JLReq)”에 바탕을 둔 jlreq가 있습니다. jlreq는 엔진을 자동으로 판별하고, reportbook 옵션으로 report·book에 해당하는 동작으로 바뀝니다. 어느 경우든 첫 질문은 같습니다. 클래스가 실제로 쓰는 엔진과 맞는가?

\documentclass 옵션은 무엇을 뜻하는가

옵션은 대괄호 안에 쉼표로 나열하는, 문서 전체에 적용되는 스위치입니다. \documentclass[11pt,a4paper,twoside]{article}처럼 씁니다. 순서는 상관없고, 같은 계열의 옵션(onesidetwoside 등)을 둘 다 쓰면 나중 것이 이깁니다. 아래 표는 실제로 손이 가는 옵션들이지만, 정작 외워 둘 것은 기본값입니다. 본문 10pt, 용지 letterpaper, 판면 onecolumn입니다. A4로 인쇄할 생각이라면 a4paper는 매번 직접 적어야 합니다.

옵션효과기본값
10pt / 11pt / 12pt본문 기준 글자 크기. 제목과 각주도 함께 비례해 변합니다10pt
a4paper / letterpaper용지 크기. a5paper, b5paper, legalpaper, executivepaper도 있습니다letterpaper
twocolumn / onecolumn본문을 2단으로 조판. 플로트 배치도 figure* 계열로 바뀝니다onecolumn
twoside / oneside제본을 고려해 좌우 여백과 쪽머리를 비대칭으로 만듭니다oneside. booktwoside
openright / openany장을 반드시 홀수(오른쪽) 페이지에서 시작할지 여부bookopenright, reportopenany
titlepage / notitlepage\maketitle이 한 페이지를 통째로 차지할지 여부report/booktitlepage, articlenotitlepage
fleqn / leqno별행 수식을 왼쪽 정렬 / 수식 번호를 왼쪽에 배치가운데 정렬, 번호는 오른쪽
draft / final넘친 줄(overfull box)을 여백의 검은 막대로 표시final

여기에는 모르면 반드시 한 번은 걸려 넘어지는 구조가 있습니다. \documentclass에 적은 옵션은 클래스만의 것이 아니라, 그 뒤에 불러오는 모든 패키지에 전역 옵션으로 전달됩니다. clsguide의 용어로 \usepackage[...]에 직접 준 것은 지역 옵션, \documentclass[...]에 준 것은 전역 옵션이며, 패키지는 자기가 아는 옵션 이름을 양쪽에서 골라 씁니다. 그래서 \documentclass[twocolumn]{article}이라고 쓰면 2단을 이해하는 패키지들은 말없이 2단 모드로 동작합니다. 이 구조는 동시에 ! LaTeX Error: Option clash for package geometry. 의 해법이기도 합니다. 이 오류는 같은 패키지가 서로 다른 옵션으로 두 번 읽힐 때, 대개 클래스나 템플릿이 이미 불러왔을 때 나타납니다. LaTeX이 로그에 직접 주는 조언은 그 옵션을 \documentclass 선언으로 끌어올리라는 것입니다. 전역 옵션은 두 번째 로드와 충돌하지 않기 때문입니다.

프리앰블에 쓰는 것과 본문에 쓰는 것

프리앰블은 \documentclass 다음 줄부터 \begin{document} 바로 앞까지이며, 여기에는 선언만 놓을 수 있습니다. 본문 글자는 한 자도 안 됩니다. 여기에 평범한 문장을 한 줄 쓰면 ! LaTeX Error: Missing \begin{document}. 로 멈춥니다. 이름은 헷갈리지만 뜻은 “본문이 시작되지 않았는데 조판할 문자가 왔다”입니다. 프리앰블의 % 주석을 끝맺지 않았거나 전각 공백 같은 문자가 끼어들어도 같은 줄이 나옵니다. 반대로 본문 안에서 \usepackage를 부르면 ! LaTeX Error: Can be used only in preamble. 이 됩니다. 모든 패키지는 첫 페이지를 조판하기 전에 다 갖춰져 있어야 하기 때문입니다.

  • 패키지 불러오기\usepackage[options]{package}. \usepackage{amsmath,amssymb}처럼 묶어 쓸 수 있지만, 그 형태로는 옵션을 붙일 수 없습니다.
  • 제목 정보\title{...}, \author{...}, \date{...}. 실제로 조판하는 것은 본문의 \maketitle이며, 관습적으로 이 세 선언은 프리앰블에 둡니다.
  • 직접 만든 명령과 환경\newcommand, \renewcommand, \newenvironment. 문서 전체에서 쓰는 구조만 넣습니다.
  • 길이와 카운터\setlength{\parindent}{0pt}, \setcounter{tocdepth}{2} 등 문서 전체에 적용되는 값.
  • 페이지 서식과 패키지 설정\pagestyle{headings}, \hypersetup{...}, \graphicspath{{figures/}} 처럼 불러온 뒤에 하는 조정.
  • 넣으면 안 되는 것 — 제목, 문단, 그림, 표. 출력에 나타나는 것은 모두 \begin{document} 뒤에 옵니다.

패키지는 어떤 순서로 불러와야 하는가

대부분의 패키지는 순서를 따지지 않지만, 예외는 반드시 외워 둘 값어치가 있습니다. 가장 유명한 것이 hyperref로, 매뉴얼은 불러오는 패키지들 가운데 맨 마지막에 두라고 못 박습니다. 이유는 단순합니다. hyperref가 하는 일이 LaTeX의 수많은 명령을 재정의하는 것이기 때문입니다. 먼저 불러오면 뒤에 오는 패키지가 그 재정의를 덮어써서 링크와 PDF 북마크가 조용히 망가집니다. 매뉴얼은 이 조언에 각주를 달아, 재정의 수를 줄여 로드 순서 의존성을 낮추는 작업이 시작되었다고 밝힙니다. 즉 이것은 영구적인 법칙이 아니라 현재 시점의 우회책입니다.

그리고 이 “맨 마지막”에는 유명한 예외가 있습니다. cleverefhyperref보다 뒤에 불러와야 합니다. cleverefhyperref가 정의한 것을 감지한 뒤 자기 참조 명령을 만들기 때문에, 순서가 반대이면 아예 동작하지 않습니다. varioref까지 쓴다면 그 매뉴얼이 지정하는 순서는 varioref → hyperref → cleveref 입니다. 이 함정이 고약한 이유는 조용히 실패하기 때문입니다. cleveref 매뉴얼이 경고하듯, 순서가 틀리면 상호 참조가 전혀 엉뚱한 대상을 가리키는데 출력에도 로그에도 아무 경고가 나오지 않습니다. 참조 번호가 알 수 없이 하나씩 어긋난 적이 있다면, 프리앰블의 이 세 줄 순서부터 확인해 보십시오.

latex
\documentclass[11pt,a4paper]{article}

% 1. encoding and fonts
\usepackage[T1]{fontenc}
% 2. language
\usepackage[english]{babel}
% 3. page geometry
\usepackage[margin=25mm]{geometry}
% 4. mathematics
\usepackage{amsmath,amssymb}
% 5. graphics and colour
\usepackage{graphicx}
\usepackage{xcolor}
% 6. hyperref near the end: it redefines many commands
\usepackage{hyperref}
% 7. cleveref is the exception, it must come after hyperref
\usepackage{cleveref}

% document-wide settings and definitions
\newcommand{\R}{\mathbb{R}}
\setlength{\parindent}{0pt}
\title{A Short Note}
\author{Ada Lovelace}
\date{\today}

\begin{document}
\maketitle

\section{Setup}\label{sec:setup}
For all $x \in \R$ we have $x^2 \ge 0$.

\section{Result}
The argument of \cref{sec:setup} applies unchanged.
\end{document}

프리앰블을 본문보다 키우지 않기

앞서 언급한 그 인터뷰에서 램포트는 “사람들이 그만두어야 할 LaTeX 실수 세 가지”를 말해 달라는 질문을 받았습니다. 그의 세 답은 모두 같은 하나였습니다. 형식에 너무 신경 쓰고 내용에는 너무 신경 쓰지 않는 것. 세 번 반복한 형식 자체가 답이었습니다. 프리앰블이야말로 그 덫이 놓인 자리입니다. 한 번 쓰고 마는 외형 조정, 시험 삼아 넣고 지우지 않은 패키지, 두 번 쓴 축약 명령이 차곡차곡 쌓입니다. 대가는 보기 흉함이 아니라, 언젠가 오류가 났을 때 범인이 그 수십 줄 어딘가에 숨어 있다는 점입니다. 문서 전체에 적용되는 것만 남기십시오. 클래스, 언어와 글꼴, 수식, 그림과 표, 링크입니다. \newcommand는 글을 쓰면서 실제로 반복된 구조에만 부여합니다. 투고 템플릿을 쓴다면 그 프리앰블을 먼저 존중하십시오. 클래스가 전제하는 패키지를 임의로 바꾸면 대개 Option clash로, 아니면 훨씬 읽기 어려운 형태로 되돌아옵니다.

  • 새 보고서article로 시작합니다. 판면 설계에 손대는 일은 본문이 대충 다 쓰인 뒤로 미뤄도 늦지 않습니다.
  • 학위논문 — 대학이 배포하는 클래스를 그대로 쓰고, 여백이나 제목 조정은 마지막에 몰아서 합니다. 템플릿 프리앰블을 건드리지 않는 것이 가장 빠른 길입니다.
  • 학술지 투고 — 출판사의 클래스(elsarticle, IEEEtran, revtex4-2 등)를 먼저 넣고, 그 위에 자신의 프리앰블을 최소한만 더합니다.
  • A4로 인쇄하려면 — 표준 클래스의 기본은 letterpaper이므로 \documentclass[a4paper]{...}라고 명시합니다. geometry를 쓴다면 거기서 지정해도 됩니다.
  • 오류가 났을 때 — 마지막에 추가한 \usepackage\newcommand를 먼저 의심하고, 그래도 모르겠으면 프리앰블을 절반씩 잘라 이분 탐색합니다.