구문 트리, 분류 체계, 결정 트리, B 트리처럼 가지가 갈라지는 그림을 LaTeX에서 그리는 도구는 크게 세 가지입니다. 가장 강력하고 현대적인 것은 forest, 언어학 구문 트리를 빠르게 그리는 표준은 qtree / tikz-qtree, 추가 패키지 없는 작은 트리라면 순수 TikZ입니다. 셋 모두 좌표를 계산하지 않고도 “부모에서 자식으로 가지가 뻗는” 중첩 구조를 기술할 수 있다는 공통점이 있습니다. 이 페이지에서는 그 선택 기준과 작성법을 봅니다.
세 가지 접근
트리는 본질적으로 중첩(재귀) 구조입니다. 뿌리가 있고, 그 아래에 자식이 달리며, 자식은 다시 손자를 갖습니다. 이 중첩을 괄호의 중첩으로 그대로 표현할 수 있으면 좌표를 하나도 지정하지 않고 트리를 만들 수 있습니다. 세 도구 모두 이 발상에 기반하지만, 쓰는 느낌과 기능 범위가 다릅니다.
forest— TikZ와 pgfkeys 위에 만들어진 가장 유연한 패키지입니다. 라벨이 붙은 괄호 표기[root [child] [child]]에 노드별 옵션과 트리 전체 스타일을 더할 수 있고, 각 노드 내용의 복잡도에 따라 간격을 자동으로 패킹합니다. 언어학 트리와 일반 트리 모두에 적합합니다.qtree/tikz-qtree— 언어학 구문 트리에 초점을 둔 가장 빠른 표준입니다.\Tree [.S [.NP ... ] [.VP ... ] ]처럼 쓰며,.label은 비말단(가지가 갈라지는) 노드를 나타냅니다.tikz-qtree는 같은 표기를 TikZ로 다시 구현해 출력이 더 좋고 조정도 쉽습니다.- 순수 TikZ(
trees라이브러리) —child/node메커니즘, 예\node {root} child {node {a}} child {node {b}};. 추가 패키지가 없으며 작은 트리를 즉석에서 그리기에 좋습니다.
한마디로 forest가 가장 유연해서 복잡한 트리에 맞고, qtree / tikz-qtree는 구성소 트리를 가장 빠르게 그리는 데 맞습니다. 순수 TikZ는 의존성을 늘리지 않고 작은 작업에 기민합니다. 아래에서 차례로 봅니다.
forest: 대괄호로 쓰는 현대적 트리
forest(Sašo Živanović, CTAN)는 TikZ와 pgfkeys 위에 만들어진 트리 그리기 패키지입니다. 프리앰블에서 읽고, forest 환경 안에 라벨이 붙은 괄호 표기로 트리를 씁니다. 각 노드는 대괄호 [ ]로 감싸고, 그 괄호 안에 자식 노드를 나열합니다. 괄호의 중첩이 곧 트리의 중첩입니다. 언어학용으로 linguistics 옵션을 붙이면 가지가 두 자식의 위에서 만나는 모양이 됩니다.
\usepackage[linguistics]{forest}
\begin{forest}
[CP
[C]
[IP
[I]
[VP
[V]
[NP]
]
]
]
\end{forest}이 예는 루트 CP 아래에 C와 IP가 있고, IP 아래에 I와 VP, 다시 VP 아래에 V와 NP가 갈라지는 구문 트리를 그립니다. [CP[C][IP[I][VP[V][NP]]]]처럼 한 줄로 압축해도 같은 트리가 되지만, 복잡해지면 괄호 대응을 놓치기 쉬우므로 위처럼 줄바꿈과 들여쓰기로 계층을 보이는 것이 정석입니다. 한 가지 함정은 소스에 빈 줄을 넣으면 forest가 구문 분석에 실패한다는 점입니다(빈 줄은 문단 구분으로 해석됩니다). 들여쓰기 자체는 자유입니다.
forest의 진가는 자동 레이아웃에 있습니다. 각 노드를 그것이 지배하는 내용의 복잡도에 따라 배치하고, 겹치지 않도록 수평 방향으로 패킹하므로 복잡한 트리도 거의 그대로 볼 만한 형태가 됩니다. 간격을 직접 조정하고 싶을 때는 트리 전체나 부분 트리에 for tree={...}를 적용합니다. 자주 쓰는 것은 수평 간격 s sep, 층(레벨) 사이의 세로 거리 l, 노드 주위 여백 inner sep 세 가지입니다.
\usepackage[linguistics]{forest}
\begin{forest}
for tree={s sep=10mm, inner sep=0, l=0}
[CP
[C]
[IP, for tree={s sep=20mm}
[I, name=src]
[VP
[V]
[DP, roof, name=tgt][the woman]]
]
]
\draw[->] (src) to[out=south west, in=south] (tgt);
\end{forest}이 예에는 여러 관용법이 들어 있습니다. 처음의 for tree={...}가 트리 전체의 간격을 정하고, [IP, for tree={s sep=20mm}처럼 노드 라벨 뒤에 쉼표를 두면 그 부분 트리만 간격을 덮어쓸 수 있습니다. roof는 그 노드의 라벨에 삼각형(지붕)을 씌우는 지정으로, 내부 구조를 생략하고 구를 하나의 단위로 보일 때 사용합니다. name=으로 노드에 이름을 붙여 두면 트리의 닫는 괄호 뒤에 \draw[->] (src) to[...] (tgt);라고 써서 이동 화살표를 그릴 수 있습니다(forest 안에서는 TikZ 명령을 그대로 쓸 수 있습니다). 라벨 자체에 쉼표를 넣고 싶을 때는 {NP, PP}처럼 중괄호로 감싸 레이아웃 지시와 구별합니다.
같은 모양을 매번 쓰고 싶지 않다면 프리앰블에서 \forestset{default preamble={for tree={...}}}로 기본 스타일을 정의해 둘 수 있습니다. forest는 TikZ/pgf에 기반하므로 노드의 모양, 색, 화살촉, 강조 같은 세부 외관은 TikZ 문서의 지식을 그대로 활용할 수 있습니다(기초는 “TikZ 기본” 참조).
qtree / tikz-qtree: 구문 트리의 최단 표기
언어학의 구성소 구조(constituency) 트리를 빠르게 그릴 때 오랫동안 표준이었던 것은 qtree입니다. 프리앰블에 \usepackage{qtree}를 쓰고, 본문에서 \Tree 뒤에 브래킷 표기의 트리를 넘깁니다. 표기의 핵심은 앞에 마침표 .가 붙은 라벨이 비말단(가지가 갈라지는) 노드를 나타내고, 마침표가 없는 맨 단어는 잎(말단)이 된다는 점입니다.
\Tree [.S [.NP Kim ] [.VP [.V saw ] NP ] ]이 한 줄은 루트 S 아래에 NP와 VP를 나누고, NP의 잎에 Kim, VP 아래에 V(잎은 saw)와 NP를 두는 트리를 그립니다. 몇 가지 약속이 있습니다. 트리는 반드시 \Tree 바로 뒤에 와야 하고, .S처럼 비말단 라벨은 마침표로 시작해야 하며, 닫는 괄호 ] 바로 앞에는 공백이 필요합니다(saw ]처럼). qtree에는 편의 기능도 많습니다. NP_i와 N^0는 트리 안에서 자동으로 수식 모드의 아래첨자/위첨자로 정리되고, X\1은 X$'$(X′)의 약어이며, \qroof{...}는 구 위에 삼각 지붕을 씌웁니다(예: \qroof{out of style}.PP). 자동 중앙 정렬을 끄려면 \usepackage[nocenter]{qtree} 옵션을 씁니다.
tikz-qtree(David Chiang)는 이 \Tree 표기를 TikZ 위에서 다시 구현한 것입니다. \usepackage{tikz}와 \usepackage{tikz-qtree}를 읽으면 같은 \Tree [.S ... ]를 그대로 사용할 수 있고, 출력은 TikZ 품질이 됩니다. 단순한 트리라면 qtree와 거의 완전히 호환되며, TikZ의 스타일 체계가 적용되므로 화살표와 가지 조정이 쉽다는 장점이 있습니다. 예를 들어 \tikzset{grow'=right}를 주면 트리가 위에서 아래가 아니라 왼쪽에서 오른쪽으로 자랍니다. 원래 qtree가 글꼴 메트릭만으로 선을 그리는 데 비해 tikz-qtree는 TikZ로 그리므로 선이 부드럽고 나중 장식도 쉽습니다.
순수 TikZ: child와 node
추가 패키지를 늘리고 싶지 않은 작은 트리라면 TikZ 본체의 child 메커니즘으로 충분합니다. 노드를 놓은 뒤 child {...}를 이어 쓰면 그 내용이 자식으로 배치되고, 부모에서 자식으로 가는 가지가 자동으로 그려집니다. child 안에는 보통 node {...}를 쓰고, 다시 child를 중첩해 손자를 만듭니다.
\begin{tikzpicture}[level distance=12mm, sibling distance=24mm]
\node {root}
child { node {a} }
child { node {b}
child { node {c} }
child { node {d} }
};
\end{tikzpicture}이 예는 root 아래에 a와 b를 두고, b 아래에 다시 c와 d를 나눈 트리를 위에서 아래로 그립니다. 마지막 세미콜론 ;은 트리 전체에서 하나뿐이며, \node ... ;의 끝에 둔다는 점에 주의하세요. 배치는 두 거리로 결정됩니다. 부모 층과 자식 층 사이의 세로 간격이 level distance(기본 15 mm), 옆으로 나란한 자식 사이의 간격이 sibling distance(기본 15 mm)입니다. 층마다 바꾸려면 level 1/.style={sibling distance=4cm}처럼 level ⟨n⟩/.style로 지정합니다. 트리가 자라는 방향은 [grow=right] 등으로 바꿀 수 있고, 가지의 형태는 edge from parent(예: 직각으로 꺾는 edge from parent fork down)로 제어합니다.
순수 TikZ는 손쉽지만 forest 같은 자동 패킹이 없기 때문에 자식 수나 깊이가 늘어나면 sibling distance를 직접 조정해 겹침을 피해야 합니다. 몇 단계짜리 작은 트리에는 충분하지만, 복잡한 구문 트리나 내용에 맞춰 간격을 맞추고 싶은 트리에서는 forest가 더 편합니다.
무엇을 고를까
망설여질 때의 기준입니다. 전반적으로 새 트리를 그린다면 forest를 먼저 고려하세요. 자동 레이아웃이 되고, 언어학부터 일반 트리까지 폭넓으며, 장식에는 TikZ의 모든 기능을 쓸 수 있습니다. 구문 트리 하나를 빠르게 그릴 뿐이라면 qtree / tikz-qtree의 \Tree 표기가 최단이며, 출력까지 다듬고 싶으면 tikz-qtree가 좋습니다. 의존성을 늘리고 싶지 않은 몇 단계짜리 트리라면 순수 TikZ의 child로 충분합니다.
| 도구 | 표기 | 적합한 용도 |
|---|---|---|
forest | [root [child] [child]](대괄호) | 복잡한 트리, 자동 정렬, 언어학 및 일반 트리 |
qtree | \Tree [.S [.NP ... ] ... ] | 구문 트리를 가장 빠르게. 글꼴 기반으로 가벼움 |
tikz-qtree | \Tree(qtree와 동일) | TikZ 품질의 구문 트리, 조정 쉬움 |
TikZ (trees) | \node {r} child {node {a}} | 작은 트리, 추가 패키지를 피할 때 |
모두 CTAN에 있으며 TeX Live와 MiKTeX에 포함되어 있습니다. forest와 tikz-qtree는 CTAN의 graphics/pgf/contrib/ 아래에 있고 TikZ/pgf에 의존합니다. 각 패키지의 자세한 내용은 자신의 컴퓨터에서 texdoc forest, texdoc tikz-qtree, texdoc qtree를 보는 것이 가장 확실합니다.