“글꼴을 설치했는데 LaTeX이 찾지 못한다” — 이 페이지는 그 한 문장에 답하기 위해 있습니다. 까다로운 점은 엔진마다 글꼴을 찾는 방식이 완전히 다르다는 것입니다. pdflatex은 시스템 글꼴을 아예 보지 않고, updmap이 만든 글꼴 맵만 믿습니다. XeTeX은 운영체제의 글꼴 기구에 물어봅니다. LuaTeX은 luaotfload가 만든 자체 Lua 데이터베이스를 찾습니다. 그래서 “fc-list에는 나오는데 쓸 수 없다”는 모순이 아니라, 세 가지 기구 가운데 다른 것을 들여다보고 있을 뿐입니다. 아래에서는 fc-list, fc-cache, updmap, kanji-config-updmap, luaotfload-tool, fmtutil을 각각 어느 계층의 고장을 고치는 도구인가에 따라 늘어놓습니다.
엔진은 어떻게 글꼴을 찾는가 — 서로 다른 세 가지 기구
이 세 갈래는 엔진이 태어난 시대의 차이가 그대로 남은 것입니다. pdfTeX의 혈통은 1980년대의 TeX인데, 그 시절 운영체제에는 “글꼴 목록”이라는 개념 자체가 없었습니다. 그래서 TeX 쪽 논리 이름(ptmr8r 같은 문자열)과 실제 파일의 대응을 글꼴 맵이라는 표에 적어 두고, updmap이 그것을 조립합니다. XeTeX(2004년 이후)은 운영체제의 글꼴 기구에 곧바로 매달리도록 설계되었습니다. macOS용으로 빌드된 TeX Live 2024의 xetex을 otool -L로 들여다보면 CoreText가 링크되어 있습니다. LuaTeX은 Lua로 이름을 풀고, luaotfload가 만든 데이터베이스를 찾습니다. 같은 \setmainfont{...}를 써도 그 한 줄이 물으러 가는 곳은 셋 다 다릅니다.
| 엔진 | 글꼴을 찾는 방식 | 고치는 명령 |
|---|---|---|
pdftex | 시스템 글꼴을 보지 않습니다. .tfm 논리 이름을 글꼴 맵으로 실제 파일에 대응시킵니다 | updmap-sys |
xetex | 운영체제에 물어봅니다. macOS 판은 CoreText가 링크되어 있습니다 | 운영체제의 글꼴 관리 |
luatex | Lua로 이름을 풀며, luaotfload가 만드는 이름 데이터베이스를 찾습니다 | luaotfload-tool --update |
dvipdfmx | 조판이 아니라 임베딩 담당. 어떤 글꼴을 PDF에 넣을지는 맵이 정합니다 | updmap-sys / kanji-config-updmap-sys |
fc-list와 fc-cache는 TeX Live의 명령이 아닙니다
여기를 놓치면 이후의 판단이 전부 어긋납니다. fc-list도 fc-cache도 fc-match도 fontconfig라는 별개 프로젝트의 명령이며, TeX Live에는 들어 있지 않습니다. TeX Live 2024의 bin 디렉터리를 끝까지 뒤져도 fc-로 시작하는 실행 파일은 하나도 없고, 이 맥에 있는 것은 Homebrew가 설치한 fontconfig 2.18.2입니다. 그래도 이들이 쓸모 있는 이유는 시스템에 어떤 글꼴이 있고 그 파일이 어디에 있는지 훑어볼 수 있기 때문입니다. fc-list : family는 패밀리 이름만, fc-list -f는 지정한 형식으로 file·family·style을 늘어놓습니다. 이 환경에서는 2,799건이 돌아왔습니다.
fc-list : family | sort -u | wc -l # how many families the system offers
fc-list -f '%{file}\n' :family=Menlo # where the file actually is
fc-cache -fv ~/Library/Fonts # rebuild the fontconfig cache
fc-match "NoSuchFontXYZ"
# Verdana.ttf: "Verdana" "Regular" <- a substitute, not an error여기에 누구나 한 번은 걸리는 함정이 있습니다. fc-match는 “찾지 못했다”고 말하지 않습니다. 존재하지 않는 이름을 건네도 fontconfig는 반드시 무언가를 돌려줍니다. 여기서 fc-match "NoSuchFontXYZ"는 Verdana.ttf: "Verdana" "Regular"를 돌려주었습니다. 이는 대체이지 확인이 아닙니다. “설치되어 있는가”를 알아보려고 fc-match를 쓰면 언제나 “있다”는 답을 듣게 됩니다. 판정하려면 돌아온 패밀리 이름이 물어본 이름과 같은지 보거나, fc-list로 이름을 지정해 좁힙니다. macOS에서는 주의가 하나 더 필요합니다. 앞 절에서 본 대로 xetex은 CoreText를 보므로, fc-list에 나온다고 해서 XeTeX이 쓸 수 있다는 보장은 되지 않습니다. 반대로 XeTeX이 실제로 fontconfig를 거쳐 찾는 빌드(대개 리눅스의 TeX Live)에서는 글꼴을 사용자 글꼴 디렉터리에 둔 뒤 fc-cache를 돌리는 것이 정확히 옳은 조치입니다.
updmap — 글꼴 맵의 한 줄은 무엇을 말하는가
글꼴 맵은 TeX의 논리 이름과 실제 파일을 잇는 한 줄짜리 텍스트의 모음입니다. updmap은 그 줄들을 직접 쓰지 않고, updmap.cfg에 나열된 .map 파일들을 하나로 이어 붙여 dvips용 psfonts.map과 pdftex 및 dvipdfmx용 pdftex.map을 써 냅니다. 이 환경에서 updmap-sys --listmaps를 세어 보면 선언이 389줄이고, 내역은 Map 332개, MixedMap 46개, KanjiMap 11개입니다. 이어 붙인 psfonts.map은 45,672줄, 5.5 MB에 가까운 한 장의 텍스트입니다. 그 안의 한 줄은 이렇게 읽습니다. TeX 쪽 이름, PostScript 글꼴 이름, 인코딩 재지정, 그리고 실제 파일.
# one real line out of psfonts.map on this machine
ptmr8r NimbusRomNo9L-Regu " TeXBase1Encoding ReEncodeFont " <8r.enc <utmr8a.pfb
updmap-sys --listmaps # every declared map, and which cfg declared it
sudo updmap-sys --enable Map myfont.map
sudo updmap-sys # rebuild psfonts.map and pdftex.map실무에서 발이 걸리는 곳은 대개 명령이 아니라 어느 설정을 건드리고 있는가입니다. TeX Live 2024의 updmap은 맨 updmap 실행을 거부합니다. updmap [ERROR]: Either -sys or -user mode is required.와 updmap [ERROR]: In nearly all cases you should use updmap -sys.만 돌아옵니다. 이 거부는 친절한 설계인데, 진짜 함정이 그 너머에 있기 때문입니다. updmap --help가 직접 이렇게 적어 두었습니다. updmap-user를 단 한 번이라도 실행하면, 이후에는 updmap-sys를 돌려도 아무 효과가 없습니다. 개인 설정 파일이 생겨 그때부터 그쪽이 우선하기 때문입니다. 공유 머신과 CI에서는 updmap-sys로 통일하고, updmap-user는 시스템 설정을 일부러 덮어쓰겠다고 자각할 때만 씁니다. sudo가 필요한 것은 /usr/local/texlive/2024 아래를 root가 소유하기 때문입니다.
kanji-config-updmap — PDF에 임베드할 일본어 글꼴 고르기
일본어 글꼴 선택이 별도의 명령으로 되어 있는 데에는 이유가 있습니다. pLaTeX・upLaTeX 경로에서는 어떤 일본어 글꼴을 PDF에 임베드할지가 조판 시점이 아니라 dvipdfmx 단계에서 정해지기 때문입니다. 원고를 고치지 않고도 임베드 글꼴만 나중에 바꿔 끼울 수 있는데, 그 전환 스위치가 texjporg의 kanji-config-updmap이고, 내부적으로는 updmap의 jaEmbed 옵션(예전 이름은 kanjiEmbed)을 설정합니다. 먼저 status로 현황을 확인하십시오. 이 환경에서는 CURRENT family for ja: haranoaji (variant: -04)가 돌아왔고, 이어서 ipa와 ipaex 등이 대기 중인 패밀리로 나열되었습니다. 바꾸고 싶으면 패밀리 이름을 그대로 넘깁니다. updmap과 마찬가지로 -sys와 -user 구분이 있으며, 공유 환경에서는 kanji-config-updmap-sys로 통일하는 편이 안전합니다.
kanji-config-updmap-sys status
# CURRENT family for ja: haranoaji (variant: -04)
# Standby family : ipa
# Standby family : ipaex
sudo kanji-config-updmap-sys ipaex # embed the IPAex family instead
sudo kanji-config-updmap-sys auto # let it pick from what is installedluaotfload-tool — LuaTeX의 첫 실행이 느린 이유
LuaLaTeX을 처음 돌린 사람이 가장 먼저 놀라는 것은 대기 시간입니다. 원인은 luaotfload의 이름 데이터베이스로, 시스템의 글꼴 파일을 훑어 이름과 파일의 대응표를 만듭니다. 이 환경에서는 TEXMFVAR/luatex-cache/generic/names/luaotfload-names.luc.gz에 약 390 KB로 저장되어 있었습니다. 흥미로운 점은 글꼴을 찾지 못하면 스스로 재작성이 시작된다는 것입니다. 존재하지 않는 이름을 \setmainfont에 넘기면 로그에 luaotfload | db : Reload initiated (formats: otf,ttf,ttc); reason: Font "NoSuchFontXYZ" not found.가 나오고, 그런 뒤에야 ! Package fontspec Error: The font "NoSuchFontXYZ" cannot be found.에서 멈춥니다. 그러니 “방금 설치한 글꼴이 보이지 않는다”는 대개 한 번 더 돌리면 낫습니다. 명시적으로 하려면 luaotfload-tool --update를 쓰며, 데이터베이스가 없으면 Font names database not found, generating new one.과 This can take several minutes; please be patient.를 표시하고 다시 만듭니다.
luaotfload-tool --update # rebuild the LuaTeX names database
luaotfload-tool --diagnose=environment # what luaotfload thinks its world looks like
ls "$(kpsewhich --var-value=TEXMFVAR)/luatex-cache/generic/names/"fmtutil — 엔진이 시작할 때 읽는 .fmt 다시 만들기
pdflatex을 실행하면 엔진은 latex.fmt 같은 포맷 파일을 읽어 들인 뒤에야 일을 시작합니다. 이는 LaTeX을 전부 읽어 마친 순간의 엔진 내부 상태를 통째로 저장한 스냅숏으로, 매번 수천 줄의 매크로를 다시 읽지 않고 시작하기 위한 장치입니다. fmtutil은 이 .fmt를 다시 만듭니다. 나설 일은 많지 않습니다. 포맷에 관계된 갱신을 했을 때, 또는 .fmt가 망가져 엔진이 시작 전에 멈췄을 때뿐입니다. 패키지 하나 설치할 때마다 돌리는 것이 아닙니다. 하나만이라면 fmtutil-sys --byfmt pdflatex, 전부라면 fmtutil-sys --all이지만 후자는 몇 분이 걸립니다. -sys와 -user의 구분은 updmap과 같고, 공유 환경에서는 -sys로 통일합니다.
sudo fmtutil-sys --byfmt pdflatex # rebuild one format
sudo fmtutil-sys --all # rebuild every format (several minutes)
kpsewhich --var-value=TEXMFVAR # where the .fmt files end up증상으로 명령 찾기
| 명령 | 이럴 때 씁니다 |
|---|---|
fc-list : family | 시스템에 그 글꼴이 정말 있는지, 이름이 무엇인지 먼저 확인하고 싶을 때 |
luaotfload-tool --update | LuaLaTeX만 글꼴을 찾지 못하고, 한 번 더 돌려도 낫지 않을 때 |
updmap-sys --enable Map | 서양 글꼴 패키지를 손으로 설치했는데도 PDF의 글자가 바뀌지 않을 때 |
kanji-config-updmap-sys status | PDF의 일본어만 의도와 다를 때. 먼저 현재 jaEmbed를 확인합니다 |
fmtutil-sys --byfmt | 엔진이 조판에 들어가기 전에 포맷을 읽지 못해 멈출 때 |
mktexlsr | TEXMFLOCAL에 파일을 두었는데도 찾지 못할 때. 자세한 내용은 빌드 도구 페이지로 |
마지막으로 이 지도의 여백에 있는 작은 도구를 하나. TeX Live에는 albatross라는 명령이 들어 있는데, man 페이지에 따르면 주어진 유니코드 글자를 담고 있는 글꼴을 찾는 도구입니다. 게다가 내부에서 fontconfig를 씁니다. TeX 세계의 도구가 fontconfig를 부르는 관계가 여기서도 나타나는 셈입니다. 다만 이 기기에서 실행하니 Unable to locate a Java Runtime.에서 멈췄습니다. 자바 실행 환경이 필요하므로 쓰려면 따로 준비해야 합니다. mktexlsr・texhash와 kpsewhich는 빌드 도구 페이지에 자세히 정리되어 있습니다.