자동으로 삽입되는 공백

LaTeX 원본에 입력한 공백은 문자가 아니라 치수입니다. 10포인트 Computer Modern에서 낱말 사이의 공백은 정확히 3.33252 pt이고, 재어 보면 ~\ (백슬래시 + 공백)도 똑같이 3.33252 pt입니다. 반대로 공백을 몇 개를 치든 하나도 남지 않는 자리가 있습니다. \LaTeX is가 “LaTeXis”로 나오는 것이 그렇습니다. 이 페이지에서는 LaTeX이 자동으로 넣는 공백의 실측값, 사라진 공백을 되찾는 명령, 그리고 직접 공백을 놓을 때 ~\hspace\quad을 가려 쓰는 법을 다룹니다.

LaTeX의 공백은 몇 포인트인가

10포인트 article에 T1 Computer Modern을 불러 재어 보면 낱말 사이 공백은 3.33252 pt, 늘어날 여유가 1.66626 pt, 줄어들 여유가 1.11084 pt입니다. 이 셋은 글꼴 자체가 가진 값으로, TeX에서는 각각 \fontdimen2, \fontdimen3, \fontdimen4라고 부릅니다. 즉 LaTeX의 공백은 “어떤 너비”가 아니라 “늘고 줄 수 있는 너비”——TeX 용어로 글루(glue)입니다. 양끝 맞춤 줄이 딱 맞아떨어지는 것은 이 여유분을 줄마다 배분하기 때문이며, 공백이 문자였다면 애초에 성립하지 않습니다.

반대로 직접 놓는 공백 중에는 전혀 늘거나 줄지 않는 것들이 있습니다. \,(가는 공백)은 1.6663 pt, \enspace은 4.99878 pt, \quad은 9.99756 pt, \qquad은 19.99512 pt입니다. 넷 다 em 단위로 정의되어 있어서 \quad은 정확히 1 em, \qquad은 2 em, \,은 1/6 em, \enspace은 1/2 em입니다. em은 글꼴 크기를 따라가므로 같은 \quad\large 안에서는 11.74713 pt로 늘어나지만, \hspace{10pt}은 어디에 쓰든 10 pt 그대로입니다. 본문의 리듬에 맞추려면 em 계열, 그림이나 표의 치수에 맞추려면 절대 길이 ——선택의 핵심은 이것뿐입니다.

명령10pt 본문 실측정의와 성질
(ordinary blank)3.33252 pt\fontdimen2. 늘림 1.66626 pt・줄임 1.11084 pt를 가진 글루
\ 3.33252 pt제어 공백. 낱말 사이와 같은 너비지만 문장 끝 판정의 영향을 받지 않음
~3.33252 pt\nobreak을 앞세운 \ . 같은 너비이지만 그 자리에서 줄바꿈하지 않음
\,1.6663 pt1/6 em의 가는 공백. \thinspace과 동일. 늘거나 줄지 않음
\negthinspace−1.66631 pt\,의 반대. 좁히고 싶을 때 사용
\enspace4.99878 pt1/2 em. 목록 라벨 주위 등에
\quad9.99756 pt정확히 1 em. \large 안에서는 11.74713 pt로 늘어남
\qquad19.99512 pt2 em. 수식이나 예시를 나눌 때
\hspace지정한 대로\hspace{10pt}은 언제나 10 pt. 다만 줄머리에 오면 버려짐
\hspace*지정한 대로줄머리에서도 사라지지 않는 판. 그 자리에서 줄바꿈도 하지 않음

\LaTeX\ is\LaTeX{} is은 같은 너비가 아닙니다

영문자만으로 된 명령 바로 뒤에 친 공백은 명령 이름이 끝났다는 신호로 소진되어 1포인트도 지면에 나오지 않습니다. 실측하면 \LaTeX is의 너비는 32.37791 pt, \LaTeX\ is는 35.71043 pt——차이는 정확히 3.33252 pt, 곧 낱말 사이 공백 하나입니다. “latex 공백이 사라진다”로 검색하는 사람이 가장 먼저 만나는 증상이 이것이고, pdftotext로 PDF에서 글자를 뽑으면 실제로 LaTeXis가 붙어서 나옵니다. 공백을 몇 개를 치든, 줄을 바꾸든 결과는 같습니다.

고치는 방법은 셋이고, \LaTeX\ is\LaTeX{} is{\LaTeX} is 모두 35.71043 pt로 측정됩니다. 다만 “셋 다 같다”에는 조건이 붙습니다. 앞이 마침표면 결과가 갈립니다. 실측으로 etc.\ Next은 39.99023 pt, etc.{} Next은 41.10107 pt이고 차이는 1.11084 pt——문장 끝에 더해지는 여분(\fontdimen7) 그대로입니다. \ 은 이 여분을 결코 받지 않는 공백인 반면, {} 뒤에 친 보통 공백은 문장 끝 공백으로 넓혀지기 때문입니다. 즉 \ 은 “사라진 공백을 되돌리는” 데 그치지 않고 문장 끝 취급을 끄는 일까지 겸하며, Fig.\ 5 같은 약어를 고칠 때 쓰이는 이유도 여기 있습니다. 문장 끝 판정 자체의 구조——\sfcode, \@, \frenchspacing——는 “구두점・괄호” 페이지에서 다룹니다.

latex
% widths measured with \sbox0{...}\typeout{\the\wd0}
% pdfLaTeX, TeX Live 2024, 10pt article, T1 Computer Modern
\LaTeX is       % 32.37791pt -> "LaTeXis"  (the blank is eaten)
\LaTeX\ is      % 35.71043pt
\LaTeX{} is     % 35.71043pt
{\LaTeX} is     % 35.71043pt

% ...but after a period the two fixes are NOT the same:
etc.\ Next      % 39.99023pt  (control space: no sentence space)
etc.{} Next     % 41.10107pt  (+1.11084pt = \fontdimen7)

xspace이 해결책만큼이나 자주 함정이 되는 이유

xspace 패키지는 직접 만든 명령 끝에 \xspace을 놓으면 “다음 문자가 구두점이 아니면 공백을 더한다”는 방식으로 작동하여, 매번 \LaTeX{}을 쓰는 수고를 덜어 줍니다. 다만 그 판정은 예외 목록과의 대조에 지나지 않습니다. TeX Live 2024에 들어 있는 xspace.sty(LaTeX Project 관리, tools 번들)의 예외는 쉼표・마침표・아포스트로피・슬래시・물음표・쌍반점・쌍점・느낌표・물결표・붙임표・닫는 둥근 괄호, 그리고 \ \/・중괄호・\space\footnote\footnotemark입니다. 여기에 없는 것 앞에서는 \xspace이 공백을 넣습니다.

닫는 대괄호 ]는 목록에 없습니다. 그래서 \newcommand{\eg}{e.g.\xspace}을 정의하고 [\eg]이라고 쓰면 출력은 [e.g. ]——닫는 괄호 바로 앞에 공백이 들어갑니다. 게다가 바로 앞이 마침표이므로 들어가는 것은 낱말 사이가 아니라 문장 끝 너비로, 실측 22.2168 pt(\xspace 없으면 17.77344 pt), 차이가 4.44336 pt나 됩니다. \eg\%(→ e.g. %), \eg\@., 곧은 큰따옴표 앞에서도 같은 일이 일어납니다. 반대 방향도 성가십니다. 안전하게 쓴다고 \eg{}이라고 적으면 중괄호가 예외에 걸려 공백이 전혀 들어가지 않아, \eg{}xe.g.x이 됩니다.

latex
\usepackage{xspace}
\newcommand{\eg}{e.g.\xspace}

\eg foo    % "e.g. foo"   correct
\eg, foo   % "e.g., foo"  correct (comma is an exception)
[\eg]      % "[e.g. ]"    WRONG -- ] is not an exception
\eg\%      % "e.g. %"     WRONG
\eg{}x     % "e.g.x"      WRONG -- the brace matches an exception

% You can patch the list, but every new case needs another patch:
\xspaceaddexceptions{]}

예외는 \xspaceaddexceptions{]}처럼 나중에 더할 수 있지만, 더할 때마다 “다음엔 무엇을 빠뜨렸나”를 세게 됩니다. 그래서 익숙한 필자들은 아예 \xspace을 쓰지 않고 \newcommand{\eg}{e.g.}로 담백하게 정의한 뒤 호출부에서 \eg{} foo라고 쓰거나, 약어 명령을 만들지 않고 그냥 e.g.을 칩니다. \xspace이 정말 값을 하는 것은 호출이 잦고 뒤에 본문의 낱말만 온다고 단언할 수 있는 경우——제품명이나 프로젝트명 매크로 정도에 그칩니다.

~이 필수인 자리——줄바꿈하지 않는 공백

~은 “너비는 낱말 사이와 같지만 그 자리에서 줄을 꺾지 않는” 공백입니다. 특별한 공백이 따로 있는 것이 아니라, latex.ltx의 정의는 \DeclareRobustCommand{\nobreakspace}{\leavevmode\nobreak\ } ——\nobreak을 앞에 둔 \ 그 자체입니다. 그래서 실측에서도 x~yx\ y와 같은 3.33252 pt의 틈이 되고, \ 과 마찬가지로 문장 끝 여분도 받지 않습니다(x.~y는 16.6626 pt, 맨 x. y는 17.77344 pt). “latex 물결표 줄바꿈”으로 찾는 동작의 정체는 이 \nobreak 한 낱말입니다.

효과는 좁은 단에서 시험하면 뚜렷합니다. 너비 3 cm의 parbox에 “We show in Figure 5 that it holds.”를 조판하면 줄 끝이 Figure에서 끊기고 다음 줄이 5로 시작합니다. 같은 문장을 Figure~5로 바꾸면 TeX은 대신 Fig-ure를 붙임표로 나누고 Figure 5를 떼어 놓지 않습니다. 즉 ~은 “그 틈을 금지”할 뿐 아니라 다른 분할안을 찾게 만드는 지시이기도 합니다. 필수라 할 만한 곳은 숫자・기호・약호가 홀로 줄머리에 서면 읽히지 않는 자리입니다——Figure~5, Section~2, Eq.~(3), Chapter~12, Dr.~Smith, Knuth~(1984), 머리글자 D.~E. Knuth, 그리고 10~kg 같은 수치와 단위. 상호 참조와 인용에서는 \ref\cite 앞에 두는 것이 정석이라 Figure~\ref{fig:main}, see~\cite{knuth1984}처럼 씁니다.

latex
% in a 3cm column, the plain space breaks the reference in half:
We show in Figure 5 that it holds.   % -> "...in Figure / 5 that..."
We show in Figure~5 that it holds.   % -> "...in Fig-/ure 5 that..."

See Section~\ref{sec:method} and Figure~\ref{fig:main}.
As shown by Knuth~\cite{texbook}, a mass of 10~kg suffices.
D.~E. Knuth, Dr.~Smith, Eq.~(3), Chapter~12.

주의할 점이 둘입니다. 첫째, ~은 줄을 꺾지 않을 뿐 하이픈 넣기를 막지는 않습니다. 위 예에서 Fig-ure가 나뉜 것이 바로 그것이며, 낱말 자체를 지키고 싶다면 \mbox{...}을 씁니다. 둘째, ~은 LaTeX이 활성 문자로 삼은 기호라서 verbatim 밖에서는 URL이나 파일 경로의 물결표를 그냥 칠 수 없습니다. 본문에서 물결표 글자를 내려면 \textasciitilde을 씁니다.

\hspace\hspace*의 차이——줄머리에서 사라지는가

줄 가운데에서는 둘의 차이가 없습니다. 차이는 바로 그 틈에서 줄이 꺾일 때 드러납니다. TeX에는 줄바꿈 바로 뒤에 온 글루를 버리는 규칙이 있어서, \hspace{1.5cm}은 거기서 줄이 꺾이면 통째로 사라집니다. 실측하면 너비 3 cm 단에 alpha beta gamma\hspace{1.5cm}epsilon zeta를 조판했을 때 TeX은 그 틈에서 줄을 꺾고 1.5 cm는 어디에도 나타나지 않습니다. \hspace*{1.5cm}으로 바꾸면 그 자리에서 줄바꿈이 일어나지 않고 epsilon 쪽이 붙임표로 나뉘며 1.5 cm 틈은 지면에 남습니다.

실무에서는 그 틈이 판면의 일부로서 의미를 가진다면 별표 붙은 쪽을 고릅니다. 표지의 서명란, 제목 앞뒤의 고정된 간격, \hfill과 함께 요소를 좌우로 밀어내는 배치 등이 그렇습니다. 반대로 “읽기 좋으라고 조금 띄우고 싶을” 뿐이라면 별표 없는 쪽으로 충분하고, 줄 끝에서 알아서 사라지는 편이 오히려 편합니다. 음수도 쓸 수 있어 \hspace{-1em}은 실측으로 정확히 1 em만큼 당깁니다.

\ignorespaces\unskip——환경 앞뒤에 새어 나오는 공백 없애기

\ignorespaces그 뒤에 이어지는 공백을 모두 건너뛰는 명령이고, \unskip바로 앞에 놓인 글루 하나를 취소하는 명령입니다. 앞의 것은 입력을 먹고 뒤의 것은 출력을 깎는다고 외우면 헷갈리지 않습니다. 실측하면 a b는 13.8855 pt, a \unskip b는 10.55298 pt——딱 낱말 사이 하나만큼 줄어듭니다. a\ignorespaces b(공백 두 개)도 10.55298 pt입니다.

쓰임새는 거의 직접 만든 환경의 앞뒤입니다. \newenvironment{note}{\textbf{Note:}}{\textbf{.}}으로 정의하고 \begin{note} yes \end{note} tail이라고 쓰면 \begin{note} 뒤와 \end{note} 앞에 친 공백이 그대로 지면에 나와 너비가 70.92018 pt가 됩니다. 시작부 끝에 \ignorespaces, 종료부 앞에 \unskip을 더하면 63.1443 pt——손으로 \textbf{Note:}yes\textbf{.} tail이라고 쓴 값과 1 scaled point도 다르지 않은 값으로 내려앉습니다. PDF에서 뽑은 문자열도 Note: yes . tail에서 Note:yes. tail로 바뀝니다. 이 두 낱말을 환경 정의에 넣어 두면 공동 집필 원고에서 특히 효과가 큽니다. 필자마다 \begin 뒤에서 줄을 바꾸든 말든 출력이 흔들리지 않기 때문입니다.

latex
% leaks a space on both sides -- measured 70.92018pt
\newenvironment{naive}{\textbf{Note:}}{\textbf{.}}

% tight on both sides -- measured 63.1443pt, identical to hand-set text
\newenvironment{tidy}{\textbf{Note:}\ignorespaces}{\unskip\textbf{.}}

\begin{tidy} yes \end{tidy} tail

% \ignorespacesafterend also swallows the blank AFTER \end{...};
% use it only when the environment must butt against what follows.
  • 먼저 ~부터 넣습니다. Figure~\ref{...}, Section~2, 10~kg, Dr.~Smith는 쓰는 순간에 넣습니다. 나중에 찾아 고치는 비용이 큽니다.
  • \ 은 “공백을 되돌린다”와 “문장 끝 취급을 끈다”의 두 몫을 한다고 외웁니다. Fig.\ 5이 통하는 것은 뒤쪽 몫 덕분입니다.
  • \xspace은 원칙적으로 쓰지 않습니다. 쓴다면 닫는 대괄호・\%・따옴표 앞을 반드시 한 번 검사합니다.
  • 판면에 관여하는 틈은 \hspace*, 읽기를 돕는 틈은 \hspace. 별표 붙은 쪽만 줄머리에서 살아남습니다.
  • 직접 만든 환경에는 처음부터 \ignorespaces\unskip을 넣습니다. 정의하는 날 넣어 두면 원고가 자라도 공백이 새어 나오지 않습니다.