환경

TeX 자체에는 \begin이라는 명령이 없습니다. Knuth의 plain TeX가 정의하는 것은 \beginsection뿐이고, \begin{...}\end{...}라는 표기는 LaTeX가 덧붙인 것입니다. 그러면 무엇을 위해 덧붙였을까요. 답은 하나의 약속——\end를 지나는 순간, 안에서 건드린 설정이 모두 원래대로 돌아온다——에 있습니다. 환경(environment) 이라 불리는 이 장치는 목록도, 별행 수식도, 그림과 표도, 인용도, 그리고 문서 본체 자체까지 같은 형태로 맞추었습니다. 이 페이지에서는 LaTeX의 환경이 무엇을 보장하는지, 어떻게 중첩하는지, 그리고 양쪽 이름이 어긋났을 때 나오는 \begin{...} ended by \end{...}를 어떻게 읽는지 살펴봅니다.

\begin\end 가 보장하는 것

환경이 보장하는 것은 “그룹”입니다. \begin{name}은 그 환경이 무엇을 하는 물건인지 알아보기도 전에 먼저 TeX 그룹을 열고, \end{name}이 그것을 닫습니다. 그래서 안에서 글꼴을 바꾸든 여백을 바꾸든, \end를 지난 줄에는 아무것도 남지 않습니다. center 환경이 내용을 가운데로 모으고, itemize 환경이 글머리표 목록으로 만들고, quote 환경이 좌우 여백을 넓혀도, 각 효과는 그 범위 안에서 끝납니다. 뒤집어 말하면 환경이 제공하는 것은 장식이 아니라 뒷정리의 보장이며, 그것이 바로 “먼저 환경을 쓴다”는 정석의 이유입니다.

\begin{name}\end{name}이름은 완전히 같아야 합니다. \begin{center}를 열고 \end{flushleft}로 닫을 수는 없습니다. 그 뒤에서 LaTeX는 지금 열려 있는 환경의 이름을 기억해 두는 수수한 일을 합니다. 그래서 오류 메시지가 양쪽 이름과 열린 쪽의 줄 번호까지 알려 줄 수 있는 것입니다. 문서 전체도 예외가 아닙니다. \begin{document}\end{document}는 엄연한 환경이며, 본문을 여기에 쓴다는 최소 규칙은 결국 “가장 바깥 환경 안에 쓴다”는 당연한 이야기일 뿐입니다.

latex
\begin{center}
This paragraph is centred; the line after \end is not.
\end{center}

\begin{quote}
  {\itshape Everything inside is a group,}
  so this italic never escapes the environment.
\end{quote}

중첩하기: 연 순서의 반대로 닫는다

환경은 중첩할 수 있지만, 닫는 순서는 연 순서의 정확히 반대입니다. \begin{a} 안에서 \begin{b}를 열었다면 먼저 \end{b}, 그다음 \end{a}입니다. \begin{a}\begin{b}...\end{a}\end{b}처럼 범위를 교차시킬 수는 없습니다. 이유는 앞 절의 보장 그 자체입니다. 환경이 그룹인 이상 그룹은 상자처럼 서로 들어가는 형태만 가능하고, 절반만 겹치는 모양은 존재하지 않기 때문입니다. 인용 안의 목록, 그림 안의 표, 정리 안의 수식——실무에서 나오는 조합은 모두 이런 중첩으로 자연스럽게 쓸 수 있습니다.

latex
\begin{quote}
  A bulleted list inside a quotation:
  \begin{itemize}
    \item first
    \item second
  \end{itemize}
\end{quote}

여기서 들일 만한 습관은 하나뿐입니다. 환경을 열면 내용을 쓰기 전에 닫는 줄부터 적어 두는 것. 그러고 나서 안쪽을 두 칸이나 네 칸만 들여쓰면 figure 안의 tabular, quote 안의 itemize 같은 대응 관계가 소스의 모양으로 눈에 들어옵니다. 중첩이 깊을수록 나중에 내용을 갈아 끼울 때 \end 하나를 잘못 맞추는 사고가 나기 쉽고, 다음 절에서 보듯 그 사고는 저지른 자리에서 드러나지 않습니다.

가장 먼저 만나는 환경: 용도별 목록

표준 LaTeX가 제공하는 환경은 본문 정렬, 목록, 수식, 플로트, 표 조판의 다섯 갈래로 나누어 보면 전체가 한눈에 들어옵니다. 각각의 자세한 사용법은 전용 페이지에 맡기지만, 이름만 다를 뿐 형태는 모두 같습니다. \begin으로 열고 \end로 닫으며, 안쪽은 그룹입니다. 새로운 환경을 만났을 때도 먼저 “이것은 무엇을 범위로 구분하는가”를 생각하면 대개 감이 잡힙니다.

분류환경하는 일
textcenter, flushleft, flushright, quote, quotation, verbatim가운데・왼쪽・오른쪽 정렬, 인용, 입력 그대로 출력
listsitemize, enumerate, description글머리표, 번호, 표제가 붙은 항목열
mathequation, align, gather별행 수식, 여러 줄 정렬, 번호 매기기
floatsfigure, table캡션과 번호를 가지며, 놓일 자리는 조판에 맡깁니다
tabulartabular, array행과 열의 격자 그 자체. figuretable과는 역할이 다릅니다

이 목록에서 특히 혼동되기 쉬운 짝을 셋만 짚어 둡니다. quotequotation 은 둘 다 인용문을 좌우에서 들여쓰지만, quotation은 각 단락의 첫 줄도 추가로 들여쓰므로 여러 단락에 걸친 긴 인용에 알맞습니다. figuretabletabular 는 전혀 다른 것으로, 앞쪽은 “떠다니며 캡션과 번호를 갖는 그릇”이고 뒤쪽은 “격자 그 자체”입니다. 표에 번호와 상호 참조가 필요하면 tabulartable 안에 넣습니다. 그리고 verbatim 은 내용을 등폭 글꼴로 입력한 그대로 내보내며 \{조차 명령으로 해석하지 않습니다. 프로그램 소스를 보여 줄 때의 정석입니다.

일부 환경은 인수를 받습니다. \begin 바로 뒤에 오는 {...}[...]가 그것입니다. 예를 들어 tabular는 열 지정이 필수입니다. \begin{tabular}{cc}{cc}가 각 열의 정렬(c 가운데, l 왼쪽, r 오른쪽)을 주고, 안에서는 &로 열을 나누며 각 행을 \\로 끝냅니다. 마찬가지로 figure\begin{figure}[htbp]처럼 놓일 자리의 희망을 옵션으로 받습니다. 인수는 언제나 환경 이름 바로 뒤에 오며, \end 쪽에는 아무것도 쓰지 않습니다.

latex
\begin{figure}[htbp]
  \centering
  \begin{tabular}{ll}
    input  & output \\
    source & PDF    \\
  \end{tabular}
  \caption{A tabular grid inside a floating table}
  \label{tab:demo}
\end{figure}

alignalign* 의 차이: 별표는 이름의 일부

이름 끝에 *를 붙인 형태는 “번호를 매기지 않는 판”입니다. align은 모든 줄에 식 번호를 붙이지만 \begin{align*}\end{align*}는 하나도 붙이지 않습니다. equation*도 마찬가지로 번호 없는 별행 수식이 됩니다. 여기서 재미있는 점은 *가 옵션도 인수도 아니라 이름 자체의 일부라는 사실입니다. \begin은 건네받은 문자열을 그대로 명령 이름으로 조립하므로, 별표를 포함한 align*이라는 이름의 명령이 실제로 만들어집니다. 앞 페이지에서 보았듯 제어어의 이름은 영문자가 아닌 문자에서 끝납니다. 즉 이 명령은 원리상 \align*이라고 써서 부를 수 없고, \begin{align*}이라는 경로로만 닿을 수 있습니다.

latex
\begin{align}          % every line gets an equation number
  a &= b + c \\
  d &= e + f
\end{align}

\begin{align*}         % same layout, no numbers at all
  a &= b + c \\
  d &= e + f
\end{align*}

\begin{...} ended by \end{...} 가 나오면

이 메시지는 “닫는 방법이 틀렸다”가 아니라 “열려 있던 것은 이쪽이다”를 알려 줍니다. 이름이 어긋나면 LaTeX는 ! LaTeX Error: \begin{center} on input line 5 ended by \end{flushleft}.처럼 열린 환경의 이름과 그 줄 번호를 덧붙여 멈춥니다. 읽어야 할 것은 뒤쪽의 \end가 아니라 앞쪽입니다. 오류가 보고되는 줄은 대개 \end 쪽이고, 정말 고쳐야 할 자리는 앞쪽이 가리키는 줄이기 때문입니다. \end를 빠뜨렸을 때도 같은 형태로 나오지만 상대가 \end{document}가 됩니다. ! LaTeX Error: \begin{itemize} on input line 2 ended by \end{document}.가 나왔다면 2행에서 연 itemize가 끝까지 닫히지 않았다는 뜻입니다.

이름을 잘못 쳤을 때는 모습이 조금 달라집니다. \begin{itemzie}처럼 정의되지 않은 이름을 쓰면 먼저 ! LaTeX Error: Environment itemzie undefined.가 나오고, 이어서 ! LaTeX Error: \begin{document} ended by \end{itemzie}.가 따라옵니다. 오류가 둘 나오는 것은 \begin이 그 환경이 존재하는지 확인하기 전에 이미 그룹을 열어 버리기 때문입니다. 열린 채 남은 그룹 때문에 대응하는 \end가 이번에는 아무와도 맞지 않게 됩니다. 여기서 실무적인 교훈이 하나 나옵니다. 오류는 위에서부터 하나씩 고치고 다시 컴파일하며, 첫 번째 아래는 무시한다. 환경 주변에서는 첫 오류가 두 번째 오류의 원인인 경우가 특히 많습니다.

둘을 가려내는 단서가 하나 더 있습니다. 중괄호 {를 닫지 않았을 때는 LaTeX가 아니라 TeX 자신의 메시지가 나옵니다. 로그 끝 가까이에 (\end occurred inside a group at level 1)만 적혀 있고 줄 번호가 없습니다. 이름 없는 맨 그룹이 열린 채 남았으므로, TeX에게는 “어디서”를 답할 재료가 없는 것입니다. 뒤집어 보면 이것이 곧 진단이 됩니다. 줄 번호가 붙은 메시지라면 환경의 짝, 줄 번호 없는 이 메시지만이라면 중괄호입니다. 범위를 좁힐 때는 의심스러운 환경을 별도 파일로 떼어 내 단독으로 컴파일하는 것이 결국 가장 빠릅니다.

환경은 겉모습이 아니라 의미로 고른다

환경은 겉모습의 상자가 아니라 원고 부품의 이름입니다. 인용이니까 quote, 항목열이니까 itemize, 격자니까 tabular, 번호와 상호 참조가 필요하니까 figuretable——이렇게 고르면 나중에 캡션, 번호, 참조, 그림·표 목차가 자연스럽게 이어집니다. 반대로 “가운데로 모으고 싶으니 center”, “여백이 필요하니 quote”라는 식으로 계속 고르면, 반년 뒤의 자신이 “이 상자는 무엇이었나”를 판단할 수 없게 되고 체재를 한 번에 바꾸지도 못하게 됩니다. 겉모습만 바꾸고 싶다면 환경보다 선언이나 여백 명령을 쓰는 편이 정직합니다.

  • 내용이 인용quote / quotation을 쓰고, 출처는 본문이나 각주에 밝힙니다.
  • 내용이 논리적인 항목열itemize / enumerate / description을 쓰고, \\로 목록을 흉내 내지 않습니다.
  • 번호와 참조가 필요한 그림이나 표figure / table 안에 \caption\label을 두고, 격자는 tabular에 맡깁니다.
  • 같은 조합이 여러 번 나온다 — 지역 서식 명령을 복사하지 말고 \newenvironment로 이름을 붙여 의미를 고정합니다.

마지막 항목이 가리키듯, 환경은 쓰기만 하는 것이 아니라 직접 정의할 수도 있습니다. \newenvironment는 “시작할 때 실행할 코드”와 “끝날 때 실행할 코드”를 주는 명령이고, 이미 있는 이름을 고쳐 만들려면 \renewenvironment를 씁니다. 인수를 넘기는 방법, \end 쪽에서 인수를 쓸 수 없는 이유, NewDocumentEnvironment를 이용한 현대적인 작성법 같은 세부는 사용자 환경 전용 페이지에 정리되어 있습니다. 여기서 챙길 것은 한 가지뿐입니다. 직접 정의한 환경에도 이 절에서 본 그룹의 보장이 그대로 따라온다는 점입니다.