300쪽짜리 학위논문을 .tex 파일 하나로 쓰는 사람은 없습니다. 큰 문서에 대한 LaTeX의 답은 \input, \include, \includeonly 세 명령이며, 프로젝트를 장마다 한 파일로 쪼갠 뒤 지금 쓰고 있는 장만 다시 조판할 수 있게 해 줍니다. 흥미로운 것은 그 아래의 구조입니다. LaTeX은 \include로 들여온 장을 하나 끝낼 때마다 그 장의 .aux 파일에 체크포인트를 적어 두는데, 페이지 번호를 포함한 모든 카운터 값이 거기에 담깁니다. 건너뛴 장이 뒤따르는 장의 번호를 흔들지 않는 이유가 이것입니다. 이 페이지는 디렉터리 구성에서 시작해 거의 누구나 한 번은 걸리는 상대 경로의 함정을 지나, 전체 빌드에서만 드러나는 고장으로 끝맺습니다.
큰 LaTeX 프로젝트의 폴더 구성
출발점은 하나입니다. 본 파일에는 본문을 한 줄도 쓰지 않습니다. main.tex에는 문서 클래스, 프리앰블, 그리고 \include 목록만 두고 그 밖의 것은 넣지 않습니다. 장은 chapters/, 그림은 figures/, 문헌 데이터베이스는 bib/에 둡니다. 그러면 main.tex 자체가 목차처럼 읽히고, 장 순서를 바꾸는 일은 줄 순서를 바꾸는 일이 됩니다. 공동 집필이 견딜 만해지는 이유도 같습니다. 각자 다른 파일을 건드리므로 충돌이 드물고, Git 차이도 손댄 장 하나에 머뭅니다. 프리앰블이 길어지면 preamble.tex로 떼어 내 \input{preamble}로 불러옵니다. 프리앰블은 결코 \include로 넣지 않는데, 그 이유는 다음 절에서 분명해집니다.
thesis/
main.tex
preamble.tex % packages and settings
chapters/01-intro.tex 02-method.tex 03-results.tex
figures/ % all images, next to main.tex
bib/refs.bib% main.tex -- no prose here, just structure
\documentclass[11pt,a4paper]{report}
\input{preamble}
\begin{document}
\tableofcontents
\include{chapters/01-intro}
\include{chapters/02-method}
\include{chapters/03-results}
\bibliographystyle{plain}
\bibliography{bib/refs}
\end{document}파일 이름에 01-, 02- 같은 번호를 붙이면 편집기의 파일 목록이 읽는 순서대로 늘어섭니다. 한 줄 더 값어치를 하는 것은 각 장 파일 맨 위에 두는 % !TEX root = ../main.tex입니다. TeXShop, TeXstudio, VS Code를 비롯한 대부분의 편집기가 이 줄을 읽고, 장 파일을 열어 둔 채 빌드해도 main.tex 쪽을 조판합니다. 이 줄이 없으면 언젠가 장 파일 하나만 컴파일하다가 ! LaTeX Error: Missing \begin{document}.를 만나게 됩니다. \documentclass가 없는 파일이니 당연한 결과지만, 알아차리기까지 몇 분은 날아갑니다.
\input과 \include의 차이
\input{f}는 f.tex의 내용을 그 자리에 붙여 넣을 뿐 그 밖의 일은 하지 않습니다. \include{f}는 장 단위의 동작이라 앞뒤로 \clearpage를 넣고, 무엇보다 그 장 전용의 f.aux를 열어 보조 정보를 그쪽으로 내보냅니다. 이 “장마다 하나씩의 .aux”가 \include가 존재하는 이유 전부입니다. 페이지 번호, 상호 참조 라벨, 목차 줄이 장별로 나뉘어 저장되므로, 나중에 어떤 장을 건너뛰더라도 바로 그 장의 정보를 지난번 실행 결과에서 되읽어 올 수 있습니다. 반면 \input은 파일 경계의 흔적을 전혀 남기지 않습니다. 그래서 프리앰블 불러오기, 공용 매크로, 표의 내용, 되풀이되는 상용구처럼 장보다 작은 부품은 모두 \input의 몫입니다.
| 명령 | 하는 일 | 페이지 나눔 | 중첩 |
|---|---|---|---|
\input | 그 자리에 .tex 파일의 내용을 펼칩니다 | 없음 | 가능 |
\include | 장 단위로 들여오며 전용 .aux를 가집니다 | 앞뒤로 \clearpage | 불가 |
\includeonly | 프리앰블 전용. 처리할 \include를 제한합니다 | — | — |
\subfile | subfiles의 명령. 그 부분만 따로도 조판됩니다 | 없음 | 가능 |
\subimport | import의 명령. 안의 상대 경로가 그 폴더 기준이 됩니다 | 없음 | 가능 |
표의 맨 오른쪽 칸이 이 절에서 가장 손해가 큰 차이입니다. \include로 들여온 파일 안에서 다시 \include를 쓰면 ! LaTeX Error: \include cannot be nested.로 멈춥니다. 억지스러운 제한처럼 보이지만 구현을 보면 필연입니다. 커널에는 장의 .aux에 쓰기 위한 출력 스트림이 딱 하나뿐이라, 안쪽 \include에는 자기 .aux를 쓸 자리가 남아 있지 않습니다. 그러니 한 장을 절 단위로 더 쪼개고 싶다면 장 파일에서 \input{chapters/02-method/setup}처럼 \input으로 부릅니다. 결과가 하나 더 있습니다. \include는 프리앰블에도 쓸 수 없어 \include should only be used after \begin{document} 경고가 나옵니다. 프리앰블을 \input으로 읽는 이유가 바로 이것입니다.
모르면 조용히 손해를 보는 비대칭이 하나 더 있습니다. 존재하지 않는 파일에 \input{chapters/ch9}를 쓰면 ! LaTeX Error: File ... not found.로 멈추지만, 같은 상황에서 \include{chapters/ch9}는 로그에 No file chapters/ch9.tex.만 적고 아무 일 없다는 듯 끝까지 조판합니다. 즉 \include의 파일 이름을 잘못 치면 오류가 아니라 장 하나가 통째로 빠진 PDF가 나옵니다. 장 이름을 바꾼 뒤에는 로그에서 No file을 검색하는 습관을 들이십시오.
\includeonly로 한 장만 조판하기 — 페이지 번호가 어긋나지 않는 이유
프리앰블에 \includeonly{chapters/02-method}를 쓰면 그 \include 하나만 처리되고 나머지는 건너뜁니다. 몇 분 걸리던 전체 빌드가 몇 초 만에 끝나고, 게다가 건너뛴 장의 페이지 번호와 상호 참조도 그대로 올바릅니다. 장치는 두 겹입니다. 첫째, 장을 건너뛸 때에도 LaTeX은 main.aux에 \@input{chapters/01-intro.aux} 줄을 반드시 씁니다. 즉 지난번 .aux를 언제나 되읽어 오므로 거기 기록된 \newlabel이 살아 있어 \ref가 풀립니다. 둘째, 장을 하나 끝낼 때마다 LaTeX은 그 장의 .aux 끝에 모든 카운터의 현재 값을 덧붙입니다. 커널 소스는 이 기록을 말 그대로 체크포인트라고 부르며, 장을 건너뛸 때는 이것을 그대로 재생하기만 하면 페이지・장・그림 번호가 “그 장이 끝난 지점”까지 단숨에 옮겨 갑니다.
% in the preamble of main.tex
\includeonly{chapters/02-method}
% several at once, comma separated, no spaces needed around the commas
% \includeonly{chapters/02-method,chapters/03-results}% chapters/01-intro.aux, written by the last full build (trimmed)
\newlabel{ch:intro}{{1}{2}{}{}{}}
\@setckpt{chapters/01-intro}{
\setcounter{page}{5}
\setcounter{chapter}{1}
\setcounter{figure}{0}
}이 두 겹 덕분에 부분 빌드로 나온 PDF는 생각보다 완성본에 가깝습니다. 목차조차 망가지지 않습니다. .toc는 실행이 끝날 때 .aux 파일들로부터 쓰이므로, 건너뛴 장도 지난번 페이지 번호를 단 채 목차에 남습니다. 다만 지켜야 할 전제가 하나 있습니다. 처음에 한 번은 전체를 빌드할 것. .aux가 아직 없는 장을 건너뛰면 참조는 ??로 남고 로그에는 LaTeX Warning: There were undefined references.가 찍힙니다. 알아 둘 만한 세부가 둘 더 있습니다. \include와 \includeonly는 이름을 비교하기 전에 끝의 .tex를 떼므로 \includeonly{chapters/02-method.tex}라고 써도 일치합니다. 그리고 \includeonly는 프리앰블 전용이라 \begin{document} 뒤에 두면 ! LaTeX Error: Can be used only in preamble.가 납니다. 제출 전에는 이 줄을 반드시 지우고 모든 장을 다시 빌드하십시오. 부분 빌드의 PDF는 작업용 근사값이지 완성된 문서가 아닙니다.
상대 경로가 장 파일이 아니라 본 파일 기준인 이유
\input도 \include도 현재 디렉터리를 바꾸지 않습니다. TeX은 모든 상대 경로를 실행 시의 작업 디렉터리, 보통은 main.tex이 놓인 자리에서 풉니다. 그러니 chapters/02-method.tex 안에 쓰는 그림 경로도 main.tex에서 본 모양으로 적어야 합니다. \includegraphics{figures/plot}는 통하고, 장 파일의 위치에서 보면 맞아 보이는 \includegraphics{../figures/plot}는 ! LaTeX Error: File ... not found.로 실패합니다. 여기서 흔히 “장을 옮겼더니 그림이 사라졌다”는 결론에 이릅니다. 옮겨진 것은 파일뿐이고 기준점은 처음부터 끝까지 main.tex입니다.
해결책은 두 갈래입니다. 보통은 graphicx의 \graphicspath를 프리앰블에 두어 찾아갈 폴더를 등록합니다. 서식이 독특하니 외워 둘 만합니다. 폴더마다 중괄호로 따로 감싸고, 각각 끝에 슬래시를 붙입니다(\graphicspath{{figures/}{chapters/figures/}}). 그러면 어느 장에서든 폴더도 확장자도 없이 \includegraphics{plot}라고 쓸 수 있습니다. 구분자는 윈도에서도 슬래시를 씁니다. 두 번째는 장마다 자기 그림 폴더를 두고 싶은 프로젝트에 어울립니다. import 패키지의 \subimport{chapters/}{02-method}를 쓰면 그 장 안의 상대 경로가 chapters/ 기준으로 풀립니다. 장 하나를 나중에 다른 프로젝트로 옮길 생각이라면 이쪽이 더 옮기기 좋습니다.
% option A -- one shared figure folder, registered once in the preamble
\usepackage{graphicx}
\graphicspath{{figures/}{chapters/figures/}} % braces per folder, trailing slash
% then, anywhere in any chapter:
% \includegraphics[width=0.8\linewidth]{plot}
% option B -- each chapter carries its own figures
\usepackage{import}
% in main.tex, instead of \include{chapters/02-method}:
\subimport{chapters/}{02-method} % paths inside resolve from chapters/장 하나만 따로 조판하기: subfiles와 standalone
\includeonly는 “전체 속의 한 장”을 빨리 조판하는 도구이지, 장을 독립된 PDF로 만들어 주지는 않습니다. 장 자체를 하나의 문서로 다루고 싶다면 subfiles 패키지를 씁니다. 장 파일 맨 위에 \documentclass[../main]{subfiles}를 두면 본 파일의 프리앰블을 빌려 단독으로 컴파일되고, 동시에 본 파일에서는 \subfile{chapters/02-method}로 여느 때처럼 본문에 흘려 넣을 수 있습니다. 그림 쪽에도 같은 발상이 있습니다. standalone 클래스로 쓴 TikZ 그림은 그 자체로 한 쪽짜리 PDF가 되고, 본 문서에서는 \usepackage{standalone}을 넣고 평범하게 \input하면 붙습니다.
% main.tex
\documentclass{report}
\usepackage{graphicx}
\usepackage{subfiles}
\begin{document}
\subfile{chapters/02-method}
\end{document}
% chapters/02-method.tex -- also compiles on its own
\documentclass[../main]{subfiles}
\begin{document}
\chapter{Method}
This chapter builds alone and inside the book.
\end{document}대가도 분명합니다. 단독으로 조판한 장은 1쪽부터 시작하고 다른 장에서 정의한 \label을 볼 수 없으므로 \ref는 ??가 되고 로그에 LaTeX Warning: There were undefined references.가 남습니다. 용도로 고르면 됩니다. 전체 번호를 유지하면서 빠르게 돌리고 싶다면 \includeonly, 지도교수에게 “3장만” 건네야 한다면 subfiles입니다. 최종적으로 하나의 PDF로 제출하는 학위논문이라면 \include와 \includeonly 조합이 자연스럽고, 각 장이 논문・강의 노트・배포 자료로도 홀로 서는 프로젝트라면 subfiles가 어울립니다. 한 프로젝트에서 둘을 섞으면 프리앰블 관리가 두 겹이 되어 대개 수지가 맞지 않습니다.
draft 옵션으로 시험 조판을 빠르게
\documentclass[draft]{report}는 큰 문서를 시험 조판할 때 두 가지 일을 합니다. 첫째, 판면을 벗어난 행——overfull hbox——을 여백의 검은 선으로 표시해 깨진 곳을 눈으로 잡아냅니다. 둘째, 이미지를 실제로 그리지 않고 파일 이름이 적힌 테두리로 바꿉니다. 이미지 처리가 통째로 빠지므로 컴파일이 눈에 띄게 가벼워지고, 그림이 많은 장일수록 효과가 큽니다. 이미지에만 적용하려면 \usepackage[draft]{graphicx}로 범위를 좁히고, 반대로 이미지는 그대로 보면서 넘친 행만 알고 싶다면 \overfullrule=5pt를 두어 선만 나오게 합니다. 마무리 빌드에서는 draft를 final로 되돌리는 것을 잊지 마십시오.
\documentclass[draft]{report} % skip images, show overfull rules
% scope it to images only:
% \usepackage[draft]{graphicx}
% keep images, still flag overfull lines:
% \overfullrule=5pt장 하나는 통과하는데 전체는 실패할 때
이 증상의 원인은 거의 넷 중 하나입니다. (1) 그 장의 프리앰블에만 있는 패키지나 매크로를 쓰고 있습니다. 단독 빌드는 통과하지만 본문에서는 ! Undefined control sequence.가 납니다. (2) 두 장이 같은 \label을 정의해 LaTeX Warning: Label ... multiply defined.가 뜨고, 참조가 조용히 엉뚱한 곳을 가리킵니다. (3) 장 폴더에서 본 상대 경로를 적었습니다. 앞 절의 함정입니다. (4) .aux가 낡았습니다. 이 가운데 (2)가 가장 위험합니다. 오류를 내는 대신 틀린 번호를 찍기 때문입니다. \label{fig:method-setup}처럼 라벨에 장 이름을 접두사로 붙이면 구조적으로 막을 수 있습니다.
.aux가 상하는 방식도 알아 둘 값어치가 있습니다. 빌드를 도중에 멈추거나 장 이름을 바꾸면 쓰다 만 .aux가 남을 수 있습니다. 다음 실행은 그것을 읽고, 방금 고친 곳과는 아무 상관 없는 줄에서 넘어집니다. 손대지 않은 자리에서 오류가 난다면 다른 무엇보다 먼저 생성물을 지우고 다시 하십시오. 손으로 지운다면 .aux, .toc, .lof, .lot, .out이고, 장별 .aux는 chapters/ 안에도 있다는 점을 잊지 마십시오. latexmk를 쓴다면 latexmk -c로 중간 파일만, latexmk -C로 출력까지 정리됩니다. 지운 뒤에는 참조와 목차가 자리를 잡도록 두 번 돌립니다.
\includeonly작업을 시작하기 전에 한 번은 전체를 빌드해 모든 장이 새.aux를 갖게 합니다.- 무거운 TikZ 그림은 외부화하거나 미리 PDF로 구워 두고
\includegraphics로 불러옵니다. - 장 파일 맨 위에
% !TEX root = ../main.tex를 두어 어떤 파일을 열어 두어도 본 문서가 빌드되게 합니다. import를 쓰지 않는다면figures/와bib/는 장 옆이 아니라main.tex옆에 둡니다.- 라벨에
fig:method-setup처럼 장 접두사를 붙여multiply defined를 구조적으로 막습니다. - 제출 전에는
\includeonly와draft를 빼고, 생성물을 지운 뒤 클린 빌드하고, 로그를 끝까지 읽어Warning과No file을 확인합니다.
마지막으로 리듬 이야기입니다. 긴 문서가 잘 굴러가는 쪽은 매번 전체를 빌드하는 사람도, 언제나 부분만 빌드하는 사람도 아니라 둘을 번갈아 쓰는 사람입니다. 평소에는 \includeonly로 지금 장만 돌리고, 저장할 때마다의 재빌드는 latexmk에 맡깁니다. 고비마다 \includeonly와 draft를 빼고 전체를 조판해 번호・목차・색인・문헌이 자리를 잡는지 확인합니다. 그리고 제출 전에는 생성물을 지우고 클린 빌드한 뒤 로그를 끝까지 읽습니다. 분할은 속도를 위한 요령처럼 보이지만, 실은 “언제든 전체를 올바르게 다시 조판할 수 있다”는 안심을 위한 요령이기도 합니다.