\includegraphics{plot}이라고 쓸 때 LaTeX에 넘기는 것은 파일 이름이 아니라 이름의 줄기입니다. graphicx 패키지가 거기에 .pdf, .png, .jpg 순으로 확장자를 붙여 가며 찾고, 가장 먼저 발견한 파일을 씁니다. 같은 원고가 pdfLaTeX에서도 LuaLaTeX에서도 dvipdfmx에서도 그대로 통과하는 것은 이 설계 덕분이며, “PNG를 다시 만들었는데 그림이 바뀌지 않는다”는 흔한 사고도 같은 설계 때문입니다. 이 페이지에서는 이미지 삽입의 중심인 \includegraphics의 옵션, \graphicspath로 지정하는 검색 경로, 엔진별로 실제로 읽을 수 있는 형식, 그리고 “File not found”라는 말을 들었을 때 읽는 법을 다룹니다.
graphicx와 \includegraphics: 확장자를 쓰지 않는 이유
이미지 삽입은 표준 graphicx 패키지가 맡습니다. \usepackage{graphicx}를 선언한 뒤 \includegraphics[옵션]{이름}이라고 씁니다. 확장자를 빼는 것이 관례인데, 내부를 들여다보면 이유가 분명합니다. pdfTeX용 드라이버 파일 pdftex.def에는 시도할 확장자의 순서가 .pdf, .png, .jpg, .mps, .jpeg, .jbig2, .jb2로 적혀 있습니다. 즉 폴더에 plot.pdf와 plot.png가 모두 있으면 언제나 PDF가 이깁니다. 그래프를 PNG로 다시 내보냈는데 그림이 꿈쩍도 하지 않는다면 대개 낡은 plot.pdf가 옆에 남아 있습니다. 뒤집어 말하면, 확장자를 쓰지 않기 때문에 나중에 PNG를 PDF로 바꿔 넣어도 원고를 한 글자도 고칠 필요가 없습니다. graphicx는 더 오래된 graphics 패키지의 확장판이며, 옵션을 key=value 형태로 묶어 넘길 수 있다는 점이 다릅니다. 둘 다 LaTeX 표준 latex-graphics 번들에 들어 있어 따로 설치할 필요가 없습니다.
\documentclass{article}
\usepackage{graphicx}
\begin{document}
% no extension: graphicx tries .pdf, .png, .jpg ... in that order
\includegraphics[width=0.6\textwidth]{plot}
\end{document}확장자를 적으면 자동 선택이 꺼질 뿐 아니라 오류 문구까지 달라집니다. 이름만 넘긴 \includegraphics{plot}이 헛돌면 탐색을 맡은 LaTeX 커널이 ! LaTeX Error: File 'plot' not found.라고 말합니다. 반면 확장자까지 적은 \includegraphics{plot.png}이 헛돌면 이번에는 드라이버가 답합니다. ! Package pdftex.def Error: File 'plot.png' not found: using draft setting. 앞의 것은 “어떤 확장자로도 찾지 못했다”, 뒤의 것은 “바로 그 한 장이 없다”는 뜻이며, 어느 쪽이 나왔는지에 따라 찾아볼 곳이 달라집니다. 덧붙이면 TeX Live의 mwe 패키지는 example-image.pdf를 TeX 트리 자체에 설치하므로 어느 폴더에서든 \includegraphics{example-image}가 통합니다. 질문 사이트의 최소 예제에 늘 이 이름이 나오는 까닭입니다.
크기 지정: width, height, scale, keepaspectratio
실무에서는 크기 지정이 거의 필수이고, width=0.8\textwidth처럼 판면을 기준으로 한 상대값으로 쓰는 것이 정석입니다. 8cm 같은 절대값으로 쓰면 2단 조판으로 바꿀 때도 용지 크기를 바꿀 때도 그림만 제자리에 남습니다. \textwidth는 본문 블록의 폭이고, \linewidth는 “지금 조판 중인 줄의 폭”이라 minipage나 subfigure 안에서는 상자 폭으로 줄어듭니다. 그래서 상자 안에서 width=\linewidth라고 적어 두면 나중에 상자 폭을 바꿔도 그림이 따라옵니다. scale=은 이미지 본래 치수에 대한 배율이라 그 치수 자체가 의미를 가질 때 알맞지만, 판면 폭은 전혀 모르기 때문에 넘치기 쉽습니다. 보통은 width=가 안전합니다.
width=와 height=를 둘 다 쓰면 graphicx는 둘 다 순순히 따르므로 종횡비가 깨져 이미지가 일그러집니다. 이를 막는 것이 keepaspectratio로, 이 옵션을 붙이면 두 값이 만드는 틀 안에 비율을 유지한 채 최대한 크게 들어가는 동작으로 바뀝니다. 사진을 정해진 크기의 자리에 흘려 넣을 때는 거의 항상 함께 씁니다. 확인용으로 알아 두면 좋은 옵션이 하나 더 있는데 draft입니다. 이미지를 아예 읽지 않고 치수만 맞는 빈 틀과 파일 이름만 조판하므로, 그림이 수백 장인 문서의 시험 조판이 훨씬 빨라집니다. \usepackage[draft]{graphicx}라고 쓰면 문서 전체에 적용됩니다.
회전과 잘라내기: angle, trim, clip, viewport
angle=은 반시계 방향 회전각을 도 단위로 받습니다. angle=90은 왼쪽으로 90도, 가로로 긴 그래프를 세로 페이지에 얹을 때의 정석입니다. 눈여겨볼 것은 angle=과 width=를 적는 순서입니다. graphicx는 키를 적힌 순서대로 적용하기 때문입니다. [angle=90,width=6cm]은 “돌린 다음 그 결과를 폭 6cm에 맞춘다”이고, [width=6cm,angle=90]은 “폭 6cm로 만든 다음 돌린다”여서 최종 치수가 달라집니다. 회전 중심은 기본적으로 이미지의 왼쪽 아래이며, origin=c로 가운데, origin=tr로 오른쪽 위로 옮길 수 있습니다.
이미지 가장자리를 잘라내려면 trim=과 clip을 짝지어 씁니다. trim은 왼쪽, 아래, 오른쪽, 위 순서로 네 값을 받는데, 이 순서는 원점이 왼쪽 아래에 있는 PostScript 좌표계에서 물려받은 것이라 직관과 맞지 않습니다. 기본 단위는 bp(빅 포인트, 1인치의 72분의 1)입니다. 그리고 clip을 반드시 붙이세요. 빠뜨리면 잘라 낸다고 여긴 부분이 사라지지 않고 주변 본문 위로 삐져나와 겹칩니다. 음수 값을 주면 반대로 여백이 붙어 그림 둘레에 공간을 만들 수 있습니다. 잘라낼 범위를 “네 변에서 얼마씩 깎을지”가 아니라 절대 좌표의 사각형으로 지정하고 싶다면 viewport=를 쓰며, 이때도 clip과 함께 씁니다.
% half the text width
\includegraphics[width=0.5\textwidth]{photo}
% fit inside 8cm x 5cm without distortion
\includegraphics[width=8cm,height=5cm,keepaspectratio]{photo}
% rotate a quarter turn to the left, then scale the result
\includegraphics[angle=90,width=6cm]{diagram}
% shave 20bp left, 20bp bottom, 30bp right, 10bp top -- clip is mandatory
\includegraphics[trim=20 20 30 10,clip,width=6cm]{scan}
% page 3 of a multi-page PDF
\includegraphics[page=3,width=\linewidth]{report}| 옵션 | 하는 일 |
|---|---|
width= | 출력 폭. 0.8\textwidth 같은 상대값이 정석 |
height= | 출력 높이. width=와 함께 쓸 때는 keepaspectratio를 덧붙임 |
scale= | 이미지 본래 크기에 대한 배율(scale=0.5은 절반) |
angle= | 반시계 방향 회전각(도). width=와의 기술 순서에 따라 결과가 달라짐 |
origin= | 회전 중심. 기본은 왼쪽 아래, c는 가운데, tr은 오른쪽 위 |
keepaspectratio | 폭과 높이가 만드는 틀 안에 비율을 지킨 채 최대로 맞춤 |
trim= ... clip | 왼쪽・아래・오른쪽・위를 깎음. 단위 기본은 bp, clip은 필수 |
viewport= ... clip | 절대 좌표의 사각형으로 잘라낼 범위를 지정. clip과 함께 사용 |
page= | 여러 페이지 PDF에서 몇 쪽을 가져올지 선택(기본은 1쪽) |
draft | 이미지를 읽지 않고 치수만 맞는 빈 틀과 파일 이름만 조판. 시험 조판용 |
\graphicspath로 그림 폴더를 가리키기
이미지를 별도 폴더에 모아 두었다면 \graphicspath로 검색 경로를 더합니다. 디렉터리 이름은 하나씩 중괄호로 감싸고(하나뿐이어도 감쌉니다), 끝에는 반드시 슬래시 /를 붙입니다(Windows에서도 /). 탐색 순서는 실험으로 확인할 수 있습니다. 현재 디렉터리에 같은 이름의 이미지가 있으면 그것이 최우선이고, 없으면 \graphicspath에 적은 순서로 먼저 찾은 것이 쓰입니다. 그래서 \graphicspath{{figures/}{old-figures/}}처럼 늘어놓으면, figures/의 새 판이 자동으로 옛 판을 가리고 아직 다시 그리지 않은 그림만 old-figures/에서 집어 오는 운용이 가능합니다. 공백이 든 경로는 {"my figures/"}처럼 따옴표로 감싸세요. 시도하는 확장자 목록 자체를 바꾸려면 \DeclareGraphicsExtensions를 씁니다.
\usepackage{graphicx}
% braces around each directory, trailing slash on each, searched in this order
\graphicspath{ {figures/} {../shared-figures/} }
% narrow or reorder the list of extensions graphicx will try
\DeclareGraphicsExtensions{.pdf,.png,.jpg}PDF냐 PNG냐: 벡터와 래스터의 선택
판단 기준은 사실 하나입니다. 선과 문자로 이루어진 그림은 벡터, 연속 계조를 가진 이미지는 래스터입니다. 벡터 이미지(PDF, EPS, SVG)는 점과 선과 곡선을 좌표로 기술하므로 아무리 확대해도 윤곽이 다시 계산되고 인쇄 해상도와는 아무 상관이 없습니다. 그래프, 회로도, 수식이 든 도면이 여기에 속합니다. 래스터 이미지(PNG, JPEG)는 색이 있는 픽셀을 격자로 늘어놓은 것이라 확대하면 픽셀이 커질 뿐입니다. 사진과 스크린샷이 여기에 속하며, 인쇄로 내보낸다면 300 dpi 이상의 원본을 준비합니다. 사진을 벡터로 만들어도 얻을 것은 없고 파일만 커집니다. TikZ나 pgfplots처럼 LaTeX 안에서 그림을 생성하면 출력은 처음부터 벡터입니다.
래스터 안에서는 짧은 원칙이면 충분합니다. 사진은 JPEG, 나머지는 PNG. JPEG는 손실 압축이라 사진의 계조에는 강하지만, 선화나 글자 가장자리에 모스키토 노이즈라 부르는 번짐이 생깁니다. 스크린샷을 JPEG로 저장하면 글자 둘레가 지저분해 보이는 까닭이 바로 이것입니다. PNG는 무손실이고 투명도도 다루며, 단색 면이 많은 그림과 스크린샷에 어울립니다. 한편 SVG는 어떤 엔진도 직접 읽지 못합니다. svg 패키지를 쓰면 \includesvg{file}라고 적을 수 있지만, 뒤에서 Inkscape의 명령줄을 불러 PDF(DVI 출력 시에는 EPS)로 변환하고 SVG 안의 글자는 별도 파일로 내보내 LaTeX 쪽에서 다시 조판하는 구조입니다. Inkscape 설치와 --shell-escape 컴파일이 필요합니다. 안정을 원한다면 Inkscape 같은 도구로 미리 PDF로 내보내는 편이 확실합니다. 반대로 TeX의 출력을 SVG로 만들고 싶다면 dvisvgm을 씁니다.
어느 엔진이 어느 형식을 읽는가: EPS는 정말 안 되는가
받아들이는 형식을 정하는 것은 엔진이 아니라 그 뒤의 드라이버 파일입니다. 시작할 때 graphics.cfg가 어떤 엔진이 도는지 가려내어 pdfTeX이면 pdftex.def, XeTeX이면 xetex.def, DVI 출력이면 dvips.def를 불러오고, 그 파일이 선언한 확장자 목록이 곧 지원 형식의 전부입니다. 여기서 흔한 설명에 두 가지 정정이 필요합니다. 첫째, XeLaTeX과 dvipdfmx는 EPS도 PS도 직접 다룹니다. xetex.def와 dvipdfmx.def의 확장자 목록에는 .eps와 .ps가 있고, 나아가 .ai, .bmp, .jp2까지 늘어서 있습니다. 둘째, pdfLaTeX과 LuaLaTeX도 사실상 EPS를 읽습니다.
| 컴파일 경로 | 드라이버 파일 | 시도되는 확장자(이 순서로) |
|---|---|---|
pdflatex | pdftex.def | .pdf .png .jpg .mps .jpeg .jbig2 .jb2. 셸 이스케이프가 켜져 있으면 .eps가 추가됨 |
lualatex | luatex.def | pdftex.def와 같은 목록. .eps 처리도 동일 |
xelatex | xetex.def | .pdf .ai .png .jpg .jpeg .jp2 .jpf .bmp .ps .eps .mps — EPS도 PS도 직접 |
platex + dvipdfmx | dvipdfmx.def | xetex.def와 같은 목록. 치수는 .xbb 보조 파일에서 올 수 있음 |
latex + dvips | dvips.def | .eps .ps .eps.gz .ps.gz .eps.Z .mps뿐. PDF도 PNG도 JPEG도 없음 |
pdfLaTeX이 EPS를 통과시키는 구조는 pdftex.def 안에 적혀 있습니다. \begin{document} 시점에 셸 이스케이프가 켜져 있으면, 이 파일이 스스로 .eps를 확장자 목록에 덧붙이고 epstopdf-base를 불러옵니다. 게다가 TeX Live의 기본값인 제한 셸 이스케이프만으로 충분하며 --shell-escape는 필요 없습니다. 제한 모드에서는 안전한 쌍둥이인 repstopdf가 호출되고, --shell-escape를 붙일 때만 epstopdf 본체로 바뀝니다. 변환 결과는 원본 옆에 myfig-eps-converted-to.pdf라는 이름으로 남습니다. 다만 pdftex.def 자신이 경고를 달아 두었는데, EPS가 아니라 PDF가 진짜 원본일 때는 이 자동 변환이 틀린 결과를 낼 수 있습니다. 끄고 싶다면 \documentclass 줄보다 앞에 \newcommand{\DoNotLoadEpstopdf}{}라고 씁니다.
% EPS under pdflatex already works; this line only makes it explicit
\usepackage{epstopdf}
% ... and this, placed BEFORE \documentclass, switches the conversion off
% \newcommand{\DoNotLoadEpstopdf}{}
% pLaTeX / upLaTeX: the driver cannot be detected, so name it
% \usepackage[dvipdfmx]{graphicx}이 자동 변환에 너무 기대지 말아야 할 이유도 있습니다. pdflatex -no-shell-escape로 돌리면 .eps가 확장자 목록에 아예 추가되지 않아, myfig.eps가 바로 앞에 있어도 ! LaTeX Error: File 'myfig' not found.가 납니다. 더 성가신 것은 확장자까지 적은 경우로, \includegraphics{myfig.eps}는 오류도 경고도 없이 그림 대신 파일 이름을 인쇄한 틀을 조판해 버립니다. 빌드 서버나 공동 저자의 도구 사슬이 -no-shell-escape를 쓰는 현장에서는 EPS를 미리 PDF로 변환해 형상 관리에 넣어 두는 편이 안전합니다. 일본어에서 쓰는 pLaTeX / upLaTeX은 드라이버를 자동 판별할 수 없으므로 \usepackage[dvipdfmx]{graphicx}라고 명시하세요. PNG・JPEG・PDF의 치수 정보가 필요하면 extractbb로 .xbb를 만듭니다.
“File not found”라는 말을 들었을 때
이미지 관련 오류는 문구가 그대로 원인을 가리킵니다. 네 가지만 알아 두면 대부분의 사고는 그 자리에서 정리됩니다. ! LaTeX Error: File 'plot' not found.는 “목록의 어떤 확장자로도 찾지 못했다”는 뜻입니다. 철자, \graphicspath, 또는 EPS밖에 없는데 셸 이스케이프가 꺼진 경우입니다. ! Package pdftex.def Error: File 'plot.png' not found: using draft setting.는 “바로 그 한 장이 없다”입니다. ! LaTeX Error: Unknown graphics extension: .tiff.는 “파일은 있지만 이 경로가 그 형식을 모른다”로, TIFF나 WebP를 그대로 건네면 이렇게 됩니다. PNG나 PDF로 변환하세요.
네 번째는 성격이 조금 다릅니다. ! LaTeX Error: Cannot determine size of graphic in plot.png (no BoundingBox).는 “파일은 읽었지만 치수를 알 수 없다”는 오류입니다. BoundingBox 줄이 빠진 EPS를 건넸을 때도 나지만, 실무에서 이것을 만나는 압도적인 이유는 pdflatex이라고 생각하며 latex을 실행한 것입니다. latex은 DVI를 내는 경로라 dvips.def가 실리고, PNG나 JPEG의 바이트열을 치수로 해석하지 못합니다. 그림이 갑자기 전부 깨졌다면 먼저 컴파일 명령을 의심하세요.
- EPS의 BoundingBox: 줄이 없거나 값이 틀리면 치수가 정해지지 않습니다.
ps2eps나epstool로 다시 씁니다. - 여러 페이지 PDF: 기본은 1쪽뿐입니다.
page=로 쪽을 고르고, 문서를 통째로 끼워 넣으려면pdfpages패키지를 씁니다. - PDF의 여백: 그림 PDF에 여백이 많으면 그림이 작아 보입니다.
pdfcrop으로 잘라낸 뒤 삽입합니다. - 파일 이름의 공백과 마침표:
my plot.tar.gz같은 이름은 확장자를 떼어내기 어렵습니다. 영숫자와 하이픈, 밑줄에 머무릅니다. - 확장자를 적어 두는 것: 확장자를 명시하면 나중에 형식을 바꾸기 어렵습니다. 원칙은 확장자 없이.
끝으로, \includegraphics는 그림을 그 자리에 놓기만 할 뿐 번호도 캡션도 붙이지 않는다는 점을 확인해 둡니다. 논문에서 “그림 3 참조”라고 쓰려면 그림을 figure 환경에 넣고 \caption과 \label을 덧붙입니다. 그 뒤의 이야기——[htbp]가 실제로 그림을 어디에 떨어뜨리는지, 캡션을 어떻게 꾸미는지, (a)(b)로 어떻게 나누는지——는 이 페이지의 자매 페이지들이 맡습니다.