LaTeX으로 일본어 조판을 시작할 때 가장 먼저 정해야 하는 것은 어떤 패키지를 부를지가 아니라 어느 경로로 갈지입니다. 지금 살아 있는 길은 셋입니다. upLaTeX + dvipdfmx, LuaLaTeX + LuaTeX-ja, XeLaTeX + zxjatype. 같은 .tex 파일이 세 경로를 모두 통과하고, 셋 다 같은 본문 글꼴을 PDF에 묻습니다. 다른 것은 속도, 아직 쓸 수 있는 패키지, 그리고 사고가 나는 지점입니다. 일본어야말로 TeX이 두 번째 조판 모형——글자 사이 글루, 세로쓰기, 줄바꿈 금지——을 갖게 된 이유이고, 이 세 경로는 그 모형의 세 가지 구현입니다. 이 페이지는 TeX Live 2024에서 실제로 측정한 숫자로 선택을 매듭짓습니다.
일본어 LaTeX의 세 경로 — 지식이 어디에 놓여 있는가
세 경로의 진짜 차이는 일본어 조판 지식이 시스템의 어느 층에 놓여 있는가입니다. upLaTeX에서는 지식이 엔진 안에 있습니다. 세로쓰기도 금칙도 글자 사이 글루도 C로 쓰인 조판기의 일부라 빠릅니다. LuaLaTeX에서는 지식이 Lua 콜백에 있습니다. LuaTeX-ja가 LuaTeX이 방금 만든 노드 목록을 훑으며 일본어 규칙을 적용하므로 느리지만 고치기가 훨씬 쉽습니다. XeLaTeX에서는 지식이 zxjatype이라는 매크로 패키지(안에서 xeCJK를 부릅니다)에 있는데, 이는 일본어 전용 엔진이라기보다 CJK 전반의 구조를 일본어에 맞춘 것입니다. 출력 경로도 다릅니다. upLaTeX만 DVI를 거쳐 dvipdfmx에 넘기고, 나머지 둘은 PDF를 곧바로 씁니다.
| 경로 | 엔진 | 출력 | 일본어 글꼴 |
|---|---|---|---|
uplatex + dvipdfmx | e-upTeX(pTeX 계열) | DVI 다음 PDF | TFM/VF 경유. 묻는 일은 dvipdfmx가 담당 |
lualatex + luatexja | LuaTeX | PDF 직접 | OpenType 직접. \setmainjfont으로 지정 |
xelatex + zxjatype | XeTeX | XDV 다음 PDF(xdvipdfmx) | OS 글꼴도 가능. zxjafont이 정석 |
이 표의 오른쪽 아래에 일본어 TeX의 역사가 하나 숨어 있습니다. dvipdfmx는 Mark A. Wicks의 dvipdfm을 다바이트・CID 지원으로 확장한 것——곧 일본어를 위해 태어난 도구입니다. 그런데 XeTeX이 이를 자기 출력 단계로 채택해 xdvipdfmx가 되었습니다. 실제 TeX Live 2024 설치를 보면 dvipdfmx는 xdvipdfmx를 가리키는 심볼릭 링크입니다. 일본어 사정으로 만들어진 변환기가 지금은 일본어와 무관한 XeTeX 문서 전부의 마지막 공정을 맡고 있는 셈입니다.
속도는 얼마나 차이 나는가 — 같은 원고를 세 경로로 재다
같은 10쪽 분량 일본어 원고를 TeX Live 2024에서 컴파일하면 uplatex + dvipdfmx가 0.31초, lualatex(ltjsarticle)가 0.59초, xelatex(bxjsarticle + zxjatype)가 0.74초였습니다. 대략 1 : 1.9 : 2.4이고, 이 비율은 한 쪽짜리 파일에서도 거의 같습니다. 차이의 대부분은 기동과 조판 자체이지 원고 길이가 아닙니다. 한 번이라면 0.3초와 0.6초의 차이를 누구도 신경 쓰지 않지만, latexmk -pvc로 저장할 때마다 다시 돌리는 방식으로 쓰면 체감으로 다가옵니다. pLaTeX 경로가 20년이 지나도 사라지지 않는 이유는 향수가 아니라 이것입니다. 세 PDF 모두 같은 Harano Aji Mincho를 서브셋으로 묻고 있고, pdftotext로 본문을 뽑으면 셋 다 올바른 일본어가 나옵니다. 빠른 경로가 품질이 낮은 경로인 것은 아닙니다.
# route 1 -- fastest; DVI in between
uplatex main.tex && dvipdfmx main.dvi
ptex2pdf -l -u main # the same two steps in one command
# route 2 -- LuaTeX-ja, PDF straight out
lualatex main.tex
# route 3 -- XeTeX via zxjatype
xelatex main.tex문서 클래스 고르기 — jsclasses, jlreq, ltjsclasses, bxjscls
경로가 정해지면 문서 클래스는 거의 저절로 정해집니다. upLaTeX이면 jsarticle(jsclasses)이나 jlreq, LuaLaTeX이면 ltjsarticle(ltjsclasses)이나 jlreq, XeLaTeX이면 bxjsarticle(bxjscls)입니다. 다만 예외가 하나 있습니다. jlreq는 pLaTeX・upLaTeX・LuaLaTeX 세 가지를 지원하지만 XeLaTeX은 지원하지 않습니다. xelatex에 \documentclass{jlreq}를 넣으면 ! Undefined control sequence.가 뜨고 이어서 ! LaTeX Error: Missing \begin{document}.까지 굴러떨어집니다. 클래스를 고정해 두면 엔진을 갈아탈 수 있다는 말은 맞지만, 갈아탈 곳에 XeLaTeX은 들어 있지 않습니다.
| 클래스 | 동작하는 엔진 | 성격 |
|---|---|---|
jsarticle | pLaTeX / upLaTeX | 오쿠무라 하루히코의 jsclasses(책은 jsbook). 사실상의 표준이며 기존 자산이 가장 많습니다 |
jlreq | pLaTeX / upLaTeX / LuaLaTeX | W3C의 JLReq에 맞춘 설계. 세로쓰기는 tate 옵션 하나면 됩니다 |
ltjsarticle | LuaLaTeX 전용 | jsclasses를 LuaTeX-ja로 이식한 것. 이행 호환성이 높습니다 |
bxjsarticle | pdfLaTeX / XeLaTeX / LuaLaTeX / (u)pLaTeX | bxjscls. 엔진을 가로지르는 얇은 공통층이자 XeLaTeX 경로의 입구 |
클래스를 고를 때 한 번은 놀라게 되는 대목은 같은 10pt가 같은 크기를 뜻하지 않는다는 점입니다. jsarticle을 10pt로 조판하고 한자 한 글자의 너비를 재면 9.24683pt밖에 안 됩니다. 클래스 파일에 \def\Cjascale{0.924690}이 있어 일본어 글꼴을 서양어 크기의 0.924690배로 읽어 들이기 때문입니다. 같은 일을 jlreq에서 하면 한자는 정확히 10pt입니다. 즉 jsarticle을 jlreq로 바꾸면 행 길이도, 한 행의 글자 수도, 판면도 달라집니다. 이행할 때는 같은 조건 비교가 아니라 판면을 다시 짠다는 마음으로 임하세요.
% route 1: uplatex main.tex && dvipdfmx main.dvi
\documentclass[uplatex,dvipdfmx]{jsarticle}
\begin{document}
日本語と English を混ぜた段落です。約物(かっこ)も混じります。
\end{document}% route 2: lualatex main.tex
\documentclass{ltjsarticle}
\usepackage{luatexja-fontspec}
\setmainjfont{Harano Aji Mincho}
\setsansjfont{Harano Aji Gothic}
\begin{document}
日本語と English を混ぜた段落です。約物(かっこ)も混じります。
\end{document}pLaTeX 경로에서 못 쓰게 되는 패키지 — fontspec, unicode-math, microtype
빠른 대신 pLaTeX 경로에서는 OpenType을 전제로 하는 현대적인 패키지들이 통째로 막힙니다. \usepackage{fontspec}은 ! Fatal Package fontspec Error: The fontspec package requires either XeTeX or(다음 줄에 LuaTeX)에서 멈추고, unicode-math는 ! Package unicode-math Error: Cannot be run with uptex!를 냅니다. 성가신 쪽은 microtype입니다. 이것은 오류를 내지 않습니다. 로그에 Package microtype Warning: You don't seem to be using pdftex, luatex or xetex.만 남기고 조용히 아무 일도 하지 않습니다. 불러왔는데 듣지 않는, 가장 알아채기 어려운 고장입니다. 반면 graphicx, hyperref, tikz는 드라이버만 맞으면 정상 동작하므로 "옛 패키지만 쓸 수 있다"는 이야기는 아닙니다. 경계선은 정확히 OpenType과 마이크로 타이포그래피 위에 그어져 있습니다.
북마크가 깨진다 — hyperref와 pxjahyper
(u)pLaTeX에 hyperref로 일본어 제목을 쓰면 PDF 북마크(책갈피)만 깨집니다. 본문은 멀쩡한데 목차 패널의 글자가 무너집니다. 원인은 hyperref가 제목의 UTF-8 바이트열을 그대로 UTF-16BE에 부어 넣기 때문입니다. 생성된 .out 파일을 들여다보면 \376\377\000\346\000\227\000\245…처럼 바이트마다 널이 끼어 있습니다. \usepackage{pxjahyper}를 더하면 같은 제목이 \376\377\145\345\147\054\212\236…, 곧 0x65E5 0x672C 0x8A9E——「日本語」 세 글자——가 됩니다. (u)pLaTeX에서 hyperref를 쓴다면 pxjahyper는 사실상 필수라고 기억해 두세요. LuaLaTeX + LuaTeX-ja에서는 맨 hyperref만으로 올바른 UTF-16BE가 나오므로 이 손질이 필요 없습니다.
% (u)pLaTeX: load pxjahyper AFTER hyperref, or the outline panel is garbage
\documentclass[uplatex,dvipdfmx]{jsarticle}
\usepackage{hyperref}
\usepackage{pxjahyper}
\begin{document}
\section{日本語の見出し}
本文。
\end{document}결국 어느 것을 고를까
새로 시작한다면 LuaLaTeX + LuaTeX-ja(ltjsarticle 또는 jlreq)를 고르세요. 0.3초의 느림과 맞바꿔 Unicode가 그대로 통하고, OS 글꼴을 쓸 수 있고, fontspec도 unicode-math도 microtype도 동작하며, 북마크도 알아서 올바르게 나옵니다. 학과의 학위논문 템플릿이나 학회 스타일 파일이 jsclasses를 전제로 배포된다면, 혹은 빌드 시간이 정말 중요한 반복 작업이라면 upLaTeX + dvipdfmx 그대로도 괜찮습니다. 낡은 길이 아니라 지금도 가장 빠른 길입니다. XeLaTeX + zxjatype은 이미 XeLaTeX 자산이 있고 거기에 일본어를 더하고 싶을 때 고르는 것이며, 일본어만을 위해 새로 고를 이유는 많지 않습니다. 이제 새 문서를 맨 platex로 시작할 이유는 없고, uplatex으로 해 두면 다룰 수 있는 문자의 범위가 넓어집니다(이 차이는 「문자 인코딩과 줄바꿈」에서 다룹니다).
- 새 문서이고 기관의 제약이 없다면 →
lualatex+ltjsarticle(또는jlreq). Unicode, OS 글꼴,microtype을 모두 쓸 수 있습니다. - 기존 템플릿이
jsclasses전제이거나 빌드 속도가 중요하다면 →uplatex+dvipdfmx.ptex2pdf -l -u로 한 명령에 담을 수 있습니다. - 이미 XeLaTeX 문서가 있다면 →
bxjsarticle+zxjatype+zxjafont.jlreq는 XeLaTeX에서 동작하지 않습니다. - (u)pLaTeX에서
hyperref를 쓴다면pxjahyper를 반드시 부르세요. "북마크만 깨진다"는 증상은 거의 이것입니다. microtype은 (u)pLaTeX에서 경고만 내고 무효입니다. 효과를 보고 싶다면 Lua나 Xe 경로로 가세요.