패키지 및 글꼴 관리

LaTeX 환경을 오래 잘 굴리는 데 정말로 효과가 있는 것은 tlmgr의 옵션 목록을 외우는 일이 아니라 파일을 어디에 둘지 판단하는 일입니다. TeX이 쓰는 탐색 경로 TEXMF를 찍어 보면 어떤 트리 앞에만 !!라는 표시가 붙어 있습니다. 이는 “디스크를 훑지 말고 ls-R 데이터베이스만 보라”는 지시이며, 이 두 글자의 유무가 손으로 넣은 파일이 곧바로 발견되는지, 아니면 mktexlsr를 칠 때까지 보이지 않는지를 가릅니다. 이 페이지에서는 tlmgr로 패키지를 더하고 갱신하는 법, 사용자 트리 TEXMFHOME과 시스템 트리 TEXMFLOCAL의 분담, CTAN에서 손으로 설치하는 절차, 그리고 글꼴 맵(updmap) 관리까지를 실제 TeX Live 2024에서 잰 값과 함께 다룹니다.

패키지 추가하기: tlmgr install 사용법

LaTeX 패키지를 추가하는 표준 절차는 tlmgr install <이름> 한 줄이고, 의존 패키지도 기본으로 따라옵니다. 이름을 하나씩 대도 되고 collection-fontsrecommended처럼 컬렉션 단위로 통째로 넣어도 됩니다. 시스템 전체 트리에 넣는 구성이라면 관리자 권한이 필요합니다(Unix 계열은 sudo tlmgr install …, Windows는 관리자 셸). 의존을 끌어오고 싶지 않을 때는 --no-depends를, 망가진 파일을 갈아 끼우고 싶을 때는 --reinstall을 붙입니다.

terminal
# Install a package; dependencies come along by default
tlmgr install siunitx
tlmgr install collection-fontsrecommended

# Skip dependencies, or overwrite a broken install
tlmgr install --no-depends siunitx
tlmgr install --reinstall siunitx

# A system-wide tree needs admin rights
sudo tlmgr install siunitx

실무에서 더 중요한 것은 오류 메시지에서 패키지 이름으로 건너가는 길입니다. LaTeX Error: File siunitx.sty not found 같은 오류가 났을 때 검색으로 주운 .sty를 원고 폴더에 넣는 것은 최악의 수입니다. 먼저 파일 이름패키지 이름을 나누어 생각하십시오. 파일은 siunitx.sty, 패키지는 siunitx입니다. 대개는 같지만 자주 어긋납니다. tikz.stypgf 패키지에 들어 있으니까요. tlmgr search --global --file은 “그 파일을 담고 있는 패키지”를 알려 주므로 여기가 다리 역할을 합니다. 이름이 어렴풋하면 tlmgr search --global <낱말>을, 정체를 알고 싶으면 tlmgr info <이름>을 쓰면 설명・라이선스・크기・수록 파일까지 나옵니다.

terminal
# From "File siunitx.sty not found" to an installed package
kpsewhich siunitx.sty                      # is it already here?
tlmgr search --global --file siunitx.sty   # which package ships it?
tlmgr install siunitx                      # install it properly

# Half-remembered name, or curious about a package
tlmgr search --global siunit
tlmgr info siunitx

놓치기 쉬운 동작이 하나 있습니다. tlmgr installtlmgr remove/usr/local/bin 같은 시스템 디렉터리의 심볼릭 링크를 다시 걸어 주지는 않습니다. PATH를 TeX Live의 bin 디렉터리 자체로 잡아 두었다면 상관없지만, tlmgr path add로 실행 파일・man・info 링크를 만들어 두는 운용이라면 새 실행 파일을 담은 패키지를 넣은 뒤 직접 tlmgr path add를(지운 뒤에는 tlmgr path remove를) 실행해야 합니다. 명령줄이 부담스럽다면 TeX Live에는 Tcl/Tk로 만든 GUI tlshell이 함께 들어 있어 검색·설치·삭제·일괄 갱신·저장소 전환을 창에서 할 수 있습니다. 뒤에서 실행된 명령 로그도 보여 주므로 tlmgr를 익히는 입구로도 알맞습니다.

갱신은 --self와 --all을 한 쌍으로

정석은 tlmgr update --self --all 한 줄로, --selftlmgr 자신(기반)을, --all이 나머지 전부를 최신으로 만듭니다. 이 순서는 취향의 문제가 아닙니다. tlmgr 설명서는 --all에 대해 “tlmgr 자신을 제외한 모든 설치 패키지를 갱신하며, tlmgr 자신에 갱신이 있으면 --force--self를 함께 주지 않는 한 오류가 난다”고 못 박아 두었습니다. 즉 낡은 tlmgr는 “먼저 나부터 갈아 끼우게 하라”며 멈춥니다. 둘 다 건네면 tlmgr는 먼저 자기를 갈아 끼우고, 성공하면 새 판으로 나머지 갱신을 이어 갑니다.

terminal
# The standard move: infrastructure first, then everything else
tlmgr update --self --all

# See what would change before committing to it
tlmgr update --list

# Update one package only
tlmgr update siunitx

이 갱신이 함께 벌이는 일도 알아 두면 좋습니다. 서버에서 컬렉션에서 빠진 패키지는 자동으로 제거되고, 내가 가진 컬렉션에 새로 들어온 패키지는 자동으로 설치됩니다. --list를 붙이면 둘 다 미리 확인할 수 있습니다. 어디서 받아 오는지는 저장소 설정이 정하며, 기본값은 CTAN의 미러 자동 분배입니다. 회선이 느리거나 특정 미러에 고정하고 싶다면 tlmgr option repository로 영구히 바꾸고, 그 한 번만 다른 미러를 쓰고 싶다면 --repository <url>을 붙입니다. 용지 크기 같은 기본값도 tlmgr가 쥐고 있어, A4로 맞추려면 tlmgr paper a4(프로그램별이면 tlmgr dvips paper a4)를 씁니다. 현재 설정은 tlmgr option show로 한꺼번에 볼 수 있습니다.

terminal
# Where tlmgr fetches from, and other stored defaults
tlmgr option repository ctan          # automatic CTAN mirror redirection
tlmgr option repository https://example.org/CTAN/systems/texlive/tlnet
tlmgr option show

# Use a different mirror for one run only
tlmgr install --repository https://example.org/CTAN/systems/texlive/tlnet siunitx

# Paper size defaults are stored here too
tlmgr paper a4
tlmgr dvips paper a4

TEXMFHOME과 TEXMFLOCAL의 차이

tlmgr가 관리하지 않는 파일, 이를테면 학회 템플릿의 클래스 파일, 직접 쓴 스타일, CTAN에서 손으로 내려받은 패키지를 둘 곳은 둘입니다. TEXMFHOME은 나만의 것, TEXMFLOCAL은 기계 전체의 것입니다. 둘 다 배포판 자신의 트리(TEXMFDIST)보다 먼저 탐색되므로 같은 이름의 파일이 있으면 이쪽이 이깁니다. 실제 위치는 환경마다 다르니 넘겨짚지 말고 찍어 보십시오. 이 Mac에서 kpsewhich -var-value=TEXMFHOME을 치면 /Users/wedd/Library/texmf 가 나옵니다. ~/texmf가 아닙니다. Linux에서는 ~/texmf가 기본값이라, Linux용 안내를 그대로 Mac에서 따라 하면 넣어 둔 파일이 영원히 발견되지 않는 사고가 납니다. 이 기계의 TEXMFLOCAL/usr/local/texlive/texmf-local이고, 눈여겨볼 점은 연도 디렉터리 바깥에 있다는 것입니다. 그래서 내년 판으로 갈아타도 여기에 둔 것은 살아남습니다.

terminal
# Never guess these paths - print them
kpsewhich -var-value=TEXMFHOME    # your own tree (differs on macOS and Linux)
kpsewhich -var-value=TEXMFLOCAL   # machine-wide tree, outside the year directory
kpsewhich -var-value=TEXMFDIST    # the distribution itself - do not edit by hand

# The whole search order, including the !! markers
kpsewhich -expand-path='$TEXMF'

둘 사이의 판단은 단순합니다. 내 원고를 위한 파일은 TEXMFHOME, 공용 기계에서 모두가 쓰게 할 것은 TEXMFLOCAL 입니다. TEXMFHOME은 관리자 권한이 필요 없고 운영체제를 다시 깔아도 홈과 함께 옮겨 갑니다. 내부는 배포판과 같은 구성(TDS)을 따라, LaTeX 스타일이라면 tex/latex/ 아래에 둡니다. 이 구성의 전모는 “디렉터리 구조와 경로”에 넘기되, 실무에서는 아래 예시의 계층만 기억해도 대개 충분합니다. 한 가지 주의. 원고 폴더에 .sty의 낡은 사본을 두지 마십시오. TeX은 현재 디렉터리를 가장 먼저 뒤지므로, tlmgr로 갱신해도 낡은 쪽이 계속 이겨서 원인을 잡기 어려운 고장이 됩니다.

terminal
# A personal class file, in the tree that belongs to you
HOME_TREE="$(kpsewhich -var-value=TEXMFHOME)"
mkdir -p "$HOME_TREE/tex/latex/local"
cp mythesis.cls "$HOME_TREE/tex/latex/local/"
kpsewhich mythesis.cls    # should print the path immediately

# Let tlmgr manage that tree too, with no root required
tlmgr init-usertree
tlmgr --usermode install siunitx

mktexlsr / texhash는 언제 필요한가

답은 분명합니다. TEXMFLOCAL이나 시스템 트리에 손으로 파일을 놓았을 때는 필요하고, TEXMFHOME에 놓았을 때는 필요 없습니다. 이유는 첫머리에 적은 !!에 있습니다. 이 기계에서 TEXMF를 펼쳐 보면 /usr/local/texlive/texmf-localtexmf-dist 앞에는 !!가 붙어 있고 ~/Library/texmf 앞에는 붙어 있지 않습니다. !!는 kpathsea에게 “이 트리는 디스크를 보지 말고 ls-R 데이터베이스만 믿으라”는 지시이므로, ls-R을 새로 만들기 전에는 새 파일이 없는 것과 같습니다. 뒷받침으로, ls-R을 지닌 트리의 목록인 TEXMFDBS에도 TEXMFHOME은 들어 있지 않습니다. 이 색인은 값을 톡톡히 합니다. 이 기계의 texmf-dist/ls-R은 276,953줄이나 되고, 덕분에 TeX은 22만 개가 넘는 파일을 매번 훑지 않아도 됩니다.

색인을 다시 만드는 명령은 mktexlsr로, TEXMFDBS에 오른 모든 트리의 ls-R을 재생성합니다. texhash는 다른 명령이 아닙니다. 이 기계에서 확인해 보면 texhashmktexlsr로 가는 심볼릭 링크, 곧 이름만 둘인 같은 프로그램입니다. 어느 쪽으로 불러도 됩니다. 시스템 트리에 쓰기 때문에 sudo가 필요합니다. 덧붙여 tlmgrgetnonfreefonts는 필요한 갱신을 스스로 해 주므로, 실무에서 직접 칠 일은 “내가 파일을 손으로 복사했을 때”뿐이라고 보아도 좋습니다.

terminal
# The same file in the system tree DOES need the index rebuilt
LOCAL_TREE="$(kpsewhich -var-value=TEXMFLOCAL)"
sudo mkdir -p "$LOCAL_TREE/tex/latex/local"
sudo cp mythesis.cls "$LOCAL_TREE/tex/latex/local/"
sudo mktexlsr          # texhash is a symlink to this same program

kpsewhich mythesis.cls # now it resolves
kpsewhich -all mythesis.cls  # and shows every copy, if several collide

CTAN에서 손으로 설치하기: .dtx와 .ins

손으로 하는 일은 tlmgr에 없는 것들에 한합니다. 투고처가 직접 배포하는 전용 클래스, 지난주에 막 공개된 패키지, 저자의 사이트에만 있는 판 같은 것들이지요. CTAN에서 배포되는 패키지 중에는 .sty가 그대로 놓인 것도 있지만, 상당수는 소스와 문서를 한데 담은 .dtx와 그것을 꺼내는 지시서 .ins 의 짝으로 옵니다. 이때 tex foo.ins를 돌리면 .dtx에서 foo.sty가 생성되므로, 그것을 TEXMFHOME 아래 알맞은 자리로 옮깁니다. .dtx 형식은 문학적 프로그래밍의 가장 순수한 모습입니다. pdflatex foo.dtx를 돌리면 주석 달린 소스가 들어간 PDF 설명서가 나옵니다.

terminal
# A package that ships as .dtx + .ins: extract, then place
tex foo.ins                     # writes foo.sty (and foo.cls, if any)
pdflatex foo.dtx                # optional: build the annotated manual

HOME_TREE="$(kpsewhich -var-value=TEXMFHOME)"
mkdir -p "$HOME_TREE/tex/latex/foo"
cp foo.sty "$HOME_TREE/tex/latex/foo/"
kpsewhich foo.sty

MiKTeX이라면: mpm과 자동 설치

MiKTeX에는 tlmgr가 없습니다. 명령줄은 mpm(MiKTeX Package Manager), GUI는 MiKTeX Console이 맡고, 갱신도 패키지 추가도 그쪽으로 모읍니다. 가장 큰 차이는 즉석 설치입니다. 문서가 요구했지만 없는 패키지를 조판 도중에 내려받아 컴파일을 이어 갑니다(Console 설정에서 “항상 설치・매번 확인・설치하지 않음”을 고를 수 있습니다). 다만 이 자동화에는 조건이 있습니다. 모든 사용자용으로 설치한 MiKTeX이라도, 즉석에서 받아 온 패키지는 실행한 사용자의 AppData\Roaming 쪽에 떨어집니다. 공용 기계에서는 필요한 패키지를 관리자 모드로 미리 넣어 두는 편이 확실합니다.

글꼴 맵 관리: updmap과 getnonfreefonts

글꼴 맵은 “TeX이 이 이름으로 부르는 글꼴은 실제로 어느 파일이고, PDF에는 어떻게 묻어 넣는가”를 한 줄씩 적어 둔 대응표입니다. pdftexdvipdfmx가 쓰는 pdftex.map, dvips가 쓰는 psfonts.map, 일본어용 kanjix.map 등이 있습니다. 이것들은 손으로 쓰는 것이 아니라 updmap이 생성합니다. 규모를 실감하려면 줄 수를 보는 편이 빠릅니다. 이 기계의 pdftex.map45,443줄입니다. 글꼴 패키지를 넣고 updmap이 돌고 나서야 이 표가 갱신되고, 그제야 그 글꼴을 PDF에 묻어 넣을 수 있게 됩니다.

updmap에는 시스템 전체를 다루는 updmap-sys나만을 다루는 updmap-user, 두 얼굴이 있는데 여기에 TeX Live 설정에서 가장 아픈 함정이 숨어 있습니다. updmap --help가 스스로 경고합니다. updmap-user를 단 한 번이라도 실행하면, 그 뒤로는 updmap-sys를 실행해도 아무 효과가 없습니다. 개인 설정 파일이 생겨 시스템 쪽을 가려 버리기 때문입니다. updmap-sys가 이 상황에서 경고를 내보내기는 하지만, 원인을 모르면 “관리자 권한으로 돌렸는데 글꼴이 그대로”라며 오래 헤매게 됩니다. 안전한 규칙은 updmap-sys만 쓰고 updmap-user에는 손대지 않는 것입니다.

한국어・일본어・중국어 글꼴 묻어 넣기에는 전용 입구가 있고, kanji-config-updmap-sys가 그 일을 맡습니다. 뒤에서 updmap을 부르며, 어느 CJK 글꼴 계열을 PDF에 묻어 넣을지 바꾸는 도구입니다. status를 건네면 현재 상태를 알려 줍니다. 이 기계에서는 현재 일본어 계열이 haranoaji이고, 바꿔 쓸 수 있는 후보로 haranoaji, ipa, ipaex가 나옵니다. 다시 말해 TeX Live에 함께 들어오는 일본어 글꼴은 Harano Aji와 IPA / IPAex이며, Noto CJK나 Source Han은 들어 있지 않습니다. 그것들을 쓰려면 운영체제에 설치된 글꼴을 가리키게 하거나 따로 설치해야 합니다.

terminal
# Ask, without changing anything: which CJK family is embedded?
kanji-config-updmap-sys status

# Switch the embedded Japanese family, machine-wide
sudo kanji-config-updmap-sys haranoaji

# Rebuild the map files after a manual font install
sudo updmap-sys        # never updmap-user: it permanently shadows updmap-sys

끝으로 배포물에 함께 실을 수 없는 글꼴 이야기를 해 둡니다. “쓰는 것은 자유지만 판매는 불가” 같은 라이선스의 글꼴은, 유상 DVD로도 배포되는 TeX Live에 동봉할 수 없습니다. 바로 이런 것들을 가져오는 것이 TUG의 getnonfreefonts 스크립트로, CTAN에서 글꼴 본체와 TeX용 지원 파일을 받아 TeX이 찾을 수 있는 상태까지 설정해 줍니다. 열쇠는 --user(TEXMFHOME으로)와 --sys(시스템 트리로)의 구분입니다. 오래된 설명에 나오는 getnonfreefonts-sys라는 별도 명령은 지금은 없습니다. 모든 사용자용이라면 getnonfreefonts --sys …를 관리자 권한으로 실행하십시오. 무엇을 넣을 수 있는지는 --lsfonts로 볼 수 있습니다.

terminal
# See what is on offer, then install into your own tree
getnonfreefonts --user --lsfonts
getnonfreefonts --user luximono

# Or system-wide, for everyone on the machine
sudo getnonfreefonts --sys luximono
  • 범용 패키지는 tlmgr로 설치하십시오. 원고 폴더에 남은 낡은 사본은 갱신 뒤에도 계속 이겨서 아무도 설명하지 못하는 고장을 만듭니다.
  • 학회 템플릿에만 속하는 파일은 원고 저장소에 두어도 됩니다. 배포물이 아니라 그 투고 묶음의 일부이기 때문입니다.
  • 공용 기계와 CI에서는 TeX Live 연도판, 추가한 패키지 이름, 고정한 저장소나 Docker 태그를 README나 .latexmkrc에 남기십시오. “내 노트북에 한 번 설치했다”는 재현성이 아닙니다.
  • 제출 직전에 tlmgr update --self --all을 돌리지 마십시오. 어제와 다른 패키지로 PDF를 만들게 됩니다. 갱신은 다른 날에 시험하십시오.
  • updmap-user는 쓰지 마십시오. 한 번만 돌려도 updmap-sys가 듣지 않게 되고, 나중에 원인을 찾기가 대단히 어렵습니다.