Mac에서 Graphviz 계층 구조를 들여쓰기 개요처럼 보이게 하려면 각 노드에 행과 들여쓰기 좌표를 지정한 다음 neato -n2로 렌더링하세요. 이렇게 하면 부모와 자식 간의 간선을 유지하면서 읽는 순서를 제어할 수 있습니다.
이 안내에서는 6개 노드로 된 예제를 만들고 PDF로 내보냅니다. 목표는 구체적입니다. 한 줄에 노드 하나씩 배치하고, 자손은 부모 바로 아래에 두며, 같은 깊이의 노드는 동일한 들여쓰기를 적용합니다. Graphviz는 고정 위치 렌더링을 -n 명령줄 옵션으로 설명합니다.
일반적인 Graphviz 트리는 왜 개요처럼 보이지 않을까요?
계층 구조는 관계를 설명하지만, 들여쓰기 개요에는 읽는 순서도 지정해야 합니다. 이 예제에서 루트에는 두 개의 분기가 있으며, 첫 번째 분기의 자손이 두 번째 분기보다 먼저 표시되어야 합니다. 원하는 순서는 다음과 같습니다.
Node R
Node A
Node C
Node D
Node B
Node E
그래프의 관계는 루트에서 A, 루트에서 B, A에서 C, A에서 D, B에서 E입니다. B가 다음 줄에 나온다는 이유만으로 D와 B 사이에 관계가 생기지는 않습니다. DOT에서는 -> 연산자로 방향 간선을 표현합니다. 노드 선언과 노드 표시 속성은 언어의 별도 요소입니다. 공식 DOT 언어 참조를 확인하세요.
Graphviz의 dot 엔진은 계층형 또는 레이어형 그림을 만듭니다. 교차와 간선 길이를 줄이면서 간선이 공통된 방향을 향하도록 합니다. 이런 목적은 분기형 다이어그램에 적합하지만, 위에 표시된 것처럼 노드마다 한 행을 할당하는 개요 형식을 정의하지는 않습니다. dot 레이아웃 문서를 확인하세요.
자주 쓰이는 몇 가지 속성은 문제의 일부만 해결합니다.
| 설정 | 문서에 명시된 용도 | 해결되지 않는 점 |
|---|---|---|
rankdir=LR |
레이아웃 방향을 왼쪽에서 오른쪽으로 변경 | 세로 개요 순서를 지정하지 않음 |
rank=same |
하위 그래프의 노드를 같은 랭크에 배치 | 모든 노드에 각자의 개요 행을 할당하지 않음 |
ordering=out |
입력 순서대로 나가는 간선이 왼쪽에서 오른쪽으로 표시되도록 제한 | 깊이에 따른 들여쓰기와 행 좌표를 정의하지 않음 |
이러한 범위는 rankdir, rank, ordering에 관한 공식 참조에 명시되어 있습니다. 이 글에서 설명하는 정확한 행 배치를 만들려면 해당 속성을 조합하는 것보다 좌표를 명시하는 편이 더 직접적입니다.
Mac에서 Graphviz를 준비하려면 어떻게 해야 하나요?
Terminal을 엽니다. 이미 Homebrew를 사용 중이라면 다음 명령으로 Graphviz를 설치하세요. 공식 Graphviz 다운로드 페이지에는 이 Mac 설치 방법이 나와 있습니다.
brew install graphviz
대신 MacPorts를 사용한다면 같은 다운로드 페이지에 sudo port install graphviz가 나와 있습니다. 이미 사용 중인 패키지 관리자를 선택하세요. 둘 다 설치되어 있지 않다면 이 안내를 계속하기 전에 해당 페이지의 관련 설치 링크를 따라 진행하세요.
렌더러를 사용할 수 있는지 확인합니다.
neato -V
-V 옵션은 Graphviz 버전 정보를 출력합니다. 컴퓨터별 결과를 비교할 때 표시된 버전을 기록해 두세요. 이 글에 특정 버전 번호가 나와 있을 필요는 없습니다. Graphviz는 이 옵션을 명령줄 참조에 설명합니다.
들여쓰기 계층 구조를 만들려면 어떻게 해야 하나요?
다음 전체 셸 블록은 새 작업 폴더를 만들고 그 안에 DOT 파일을 작성합니다. Terminal에서 실행하세요. 작업이 끝나면 폴더 경로가 출력됩니다. 따옴표로 묶은 heredoc 구분자는 DOT 텍스트를 입력한 그대로 보존합니다.
outline_dir=$(mktemp -d "$HOME/graphviz-outline.XXXXXX")
if [ -n "$outline_dir" ] && cd "$outline_dir"; then
cat > hierarchy.dot <<'DOT'
digraph Hierarchy {
graph [splines=ortho, bgcolor=white];
node [
shape=box,
width=1.2,
height=0.35,
fixedsize=true,
fontname="Courier",
fontsize=12
];
r [label="Node R", pos="100,300"];
a [label="Node A", pos="136,252"];
c [label="Node C", pos="172,204"];
d [label="Node D", pos="172,156"];
b [label="Node B", pos="136,108"];
e [label="Node E", pos="172,60"];
r -> a;
r -> b;
a -> c;
a -> d;
b -> e;
}
DOT
pwd
fi
노드 위치가 개요 형식을 결정합니다. 각 행은 아래로 48포인트씩 이동하고, 깊이가 하나 늘어날 때마다 오른쪽으로 36포인트씩 이동합니다. 이 숫자는 간격 선택을 보여 주는 예시일 뿐, Graphviz의 기본값은 아닙니다. pos 문서에 따르면 노드 위치는 노드 중심을 기준으로 하며, -n과 함께 사용할 경우 neato는 위치를 포인트 단위로 해석합니다.
| 노드 | 깊이 | 행, 0부터 시작 | 중심 위치 |
|---|---|---|---|
| Node R | 0 | 0 | 100,300 |
| Node A | 1 | 1 | 136,252 |
| Node C | 2 | 2 | 172,204 |
| Node D | 2 | 3 | 172,156 |
| Node B | 1 | 4 | 136,108 |
| Node E | 2 | 5 | 172,60 |
이 구성에서 좌표 규칙은 x = 100 + 36 × depth 및 y = 300 − 48 × row입니다. Node D에서 Node B로 돌아오는 흐름을 살펴보세요. 행 번호는 늘어나지만 깊이는 얕아집니다. 이 한 번의 전환이 그림을 사슬이 아니라 개요처럼 보이게 합니다.
모든 상자의 크기가 같으므로 중심 좌표가 같으면 왼쪽 가장자리도 정렬됩니다. 길이가 동일한 예시 레이블을 사용하면 텍스트 배치를 쉽게 비교할 수 있습니다. fixedsize=true을 사용하면 Graphviz는 내용에 맞춰 상자를 키우지 않고 지정된 노드 크기를 사용하며, 레이블이 너무 크면 경고를 표시합니다. fixedsize 참조를 확인하세요.
결과를 렌더링하고 확인하려면 어떻게 해야 하나요?
같은 Terminal 세션과 작업 폴더에서 다음을 실행합니다.
neato -n2 -Tpdf hierarchy.dot -o hierarchy.pdf
여기서 -n2는 겹침 조정 없이 제공된 노드 배치를 유지하고, 자체 위치가 없는 간선의 경로를 계산합니다. 따라서 모든 노드에는 pos 값이 필요합니다. -Tpdf와 -o 옵션은 각각 PDF 출력 형식과 저장 위치를 지정합니다. 이러한 동작은 명령줄 참조에 설명되어 있습니다.
Finder에서 작업 폴더를 열고 hierarchy.pdf을 여세요. PDF 출력에는 Cairo 렌더러가 포함된 Graphviz 빌드가 필요하며, 이는 Graphviz의 PDF 출력 페이지에 명시되어 있습니다. 이 예제는 문서와 대조해 확인했지만, 조사 환경에서 Graphviz를 사용할 수 없어 실제 렌더링 테스트는 하지 못했습니다.
다음 세 가지를 따로 확인하세요.
- 위에서 아래로 읽었을 때 R, A, C, D, B, E가 각각 연속된 행에 있어야 합니다.
- 들여쓰기를 비교했을 때 A와 B가 정렬되고, C, D, E는 그보다 한 단계 더 오른쪽에 정렬되어야 합니다.
- 관계를 따라가 봅니다. R은 A와 B에 연결되고, A는 C와 D에 연결되며, B는 E에 연결됩니다.
첫 번째와 두 번째 확인은 좌표 구성을 점검합니다. 세 번째는 실제 그래프를 점검합니다. 이 확인들을 분리하면 보기에는 정돈되어 있지만 부모와 자식 간선이 잘못된 다이어그램을 찾아내기 쉽습니다.
연결선이 파일 브라우저의 트리와 똑같이 보이나요?
노드의 행과 들여쓰기는 명시적으로 지정하지만, 연결선 경로는 여전히 계산됩니다. 이 예제는 splines=ortho를 요청하며, 이 설정은 축에 맞춘 선분으로 간선을 그립니다. Graphviz 문서에는 이 라우팅이 포트를 처리하지 못한다고도 나와 있으므로, 나침반 포트를 추가해 특정한 꺾임 모양을 강제하는 방법은 문서에 명시된 방식이 아닙니다. splines 참조를 확인하세요.
따라서 이 구성은 자동으로 경로를 지정한 직각 연결선을 포함하는 들여쓰기 계층 구조를 만듭니다. 정확한 위치에 분기 접합부가 놓이는 하나의 공통 세로선을 지정하지는 않습니다. 연결선의 기하 구조가 꼭 필요하다면 간선 경로를 명시적으로 지정하는 추가 구성이 필요합니다. splines=ortho만으로는 그 요구를 표현할 수 없습니다.
연결선이 보이지 않는 깔끔한 개요를 원하면 그래프 설정을 splines=none으로 바꾸고 다시 렌더링하세요. DOT 파일에는 부모와 자식 간선이 계속 포함되지만, 렌더러가 해당 선을 표시하지 않습니다. 이는 같은 splines 참조에 설명된 렌더링 옵션입니다.
의미를 바꾸지 않고 예제를 수정하려면 어떻게 해야 하나요?
먼저 간선 목록과 별개로 원하는 읽기 순서를 작성하세요. 부모를 먼저 배치한 뒤 첫 번째 자식과 그 자손을 배치하고, 그 다음 자식으로 넘어갑니다. 그 순서대로 모든 노드에 행을 하나씩 할당한 다음 깊이에 따라 들여쓰기를 정하세요.
예를 들어 Node D 뒤에 Node A의 자식을 하나 더 추가하려면 Node B보다 앞서 읽기 순서에 넣으세요. 깊이를 2로 지정하고 이후 행을 아래로 이동한 다음 A에서 새 노드로 간선을 추가합니다. 행 번호가 바뀐다는 이유만으로 기존 부모 관계가 변경되지는 않습니다.
수정한 버전이 잘못되어 보이면 다음 순서로 점검하세요.
- 그림이 다른 배치로 흩어집니다: 명령이 여전히
neato -n2를 사용하는지 확인하세요. 이 예제는 일반적인 자동 레이아웃 대신 지정된 위치를 사용합니다. - 렌더링 시 위치 누락이 보고됩니다: 간선 문에만 등장하는 ID를 포함해 모든 노드 ID를 확인하세요. 이 방식에서는 각각 위치가 지정된 선언이 필요합니다.
- 레이블이 상자 밖으로 나옵니다: 공통 상자 크기를 늘리거나 레이블을 짧게 줄이세요. 고정 크기 상자는 자동으로 커지지 않습니다.
- 상자를 키운 뒤 행이 겹칩니다: 행 간격을 늘리세요. 선택한 렌더링 모드는 위치를 유지하며 겹침을 수정하지 않습니다.
- 분기가 잘못된 노드에 연결됩니다: 간선 문을 수정하세요. 상자를 이동해도 잘못된 관계는 바로잡을 수 없습니다.
위치 누락 및 겹침 조건은 Graphviz에 문서화된 -n2 동작에 따릅니다. 레이블 조건은 fixedsize 동작에 따릅니다. 간격을 늘리는 것은 수동으로 배치한 이 예제에 해당하는 설계 조정입니다.
계층 구조의 간선 목록은 관계의 기준으로, 좌표 표는 표시 방식의 기준으로 유지하세요. 소규모 Mac 데스크톱 다이어그램에서는 이렇게 분리하면 결과를 쉽게 관리할 수 있습니다. 계층 구조가 바뀌면 간선을 수정하고, 읽는 순서가 바뀌면 행을 수정하며, 레이블을 위한 공간이 더 필요하면 간격을 수정하세요.