Graphviz SVG 이미지: 노드 그림의 이동성 유지하기
Graphviz 노드에 SVG 그림을 추가하고 이미지 참조를 확인하세요. 완전한 에셋 묶음, 이동한 다이어그램과 자체 포함 전달용 사본을 비교 테스트합니다.
목차
Graphviz 다이어그램에 벡터 노드와 화살표가 있어도 사용자 지정 노드 그림은 여전히 별도 이미지 파일을 가리킬 수 있습니다. SVG를 옮긴 뒤 그림이 사라지면 그림을 바꾸기 전에 생성된 이미지 참조를 확인하세요. 전달 패키지의 일부가 빠진 것일 수 있습니다.
아래에서 테스트한 SVG 출력에서 Graphviz는 motif.svg를 링크된 이미지로 유지합니다. 전체 묶음은 렌더링되지만 다이어그램만 옮기면 그림이 사라집니다. 명시적으로 패키징한 사본은 그림 바이트를 포함하며 같은 브라우저 테스트에서 렌더링됩니다. 이 패키징 단계도 모티프를 네이티브 그래프 경로로 바꾸는 대신 SVG 이미지 요소로 남겨 둡니다.
노드 이름과 관계를 위해 DOT 소스를 보관하세요. 그림 원본도 따로 보관하고 실제 출력 파일을 받을 뷰어나 게시 작업 흐름으로 테스트하세요.
노드, 노드 그림과 파일 참조 구분하기
Graphviz의 image 속성은 노드 안에 표시할 그림 이름을 지정합니다. 노드의 그래프 식별자나 관계를 대체하지는 않습니다. 문서에서는 원본 크기를 요구합니다. SVG 이미지에는 적절한 단위의 width와 height를 명시하세요.
여기의 원본 모티프는 96 × 64 좌표 공간을 쓰는 2개 경로 그림입니다. 바깥 크기는 96pt × 64pt입니다. 둘러싼 노드와 화살표는 Graphviz가 만듭니다.
| 구성 요소 | 관리 위치 | 발생 가능한 문제 |
|---|---|---|
| 노드 이름, 레이블과 간선 | DOT 소스 | 잘못된 그래프 관계나 문구 |
| 사용자 지정 모티프 | 그림 SVG 원본 | 누락된 크기, 부적합한 세부 또는 잘못된 비율 |
| 다이어그램에서 모티프로의 링크 | 내보낸 SVG 이미지 참조 | 해석된 경로에 그림 없음 |
| 최종 배치와 크기 | 렌더러 출력과 실제 수신 뷰어 | 잘림, 늘어남 또는 지원하지 않는 의존성 |
이미지 요소는 SVG 그림이나 픽셀을 가리킬 수 있습니다. 래스터 소스는 별도의 SVG 삽입 이미지 진단으로 조사하세요. .svg로 끝나는 파일명만으로 어느 파일의 내용도 확정할 수 없습니다.
렌더러를 명시하고 작은 예제 실행하기
Graphviz 16.1.0이라고 보고하는 WebAssembly 빌드인 @viz-js/viz 3.31.0을 dot 레이아웃 엔진과 기본 SVG 출력으로 사용했습니다. 이는 해당 빌드와 렌더러의 테스트이며 모든 Graphviz 설치의 이미지 로딩 동작이 같다는 주장은 아닙니다.
새 Node.js 프로젝트 폴더에서 고정된 패키지 버전을 설치하세요.
npm install @viz-js/viz@3.31.0원본 그림을 motif.svg로 저장하세요.
<svg xmlns="http://www.w3.org/2000/svg"
width="96pt" height="64pt" viewBox="0 0 96 64">
<path fill="#173b40" fill-rule="evenodd"
d="M48 4C70 4 88 17 88 32S70 60 48 60S8 47 8 32S26 4 48 4Z
M48 14C31 14 19 22 19 32S31 50 48 50S77 42 77 32S65 14 48 14Z"/>
<path fill="#28bfa3"
d="M43 20H53V27H60V37H53V44H43V37H36V27H43Z"/>
</svg>그래프를 diagram.dot으로 저장하세요.
digraph G {
graph [rankdir=LR, bgcolor="white", margin=0.1];
node [shape=box, fontname="Arial", fontsize=16,
color="#173b40", penwidth=1.5,
fixedsize=true, width=1.8, height=1.1];
artwork [label="", image="motif.svg", imagescale=true];
review [label="Review"];
artwork -> review [color="#173b40", penwidth=1.5];
}그런 다음 아래 코드를 render.mjs로 저장하고 그 폴더에서 node render.mjs를 실행하세요.
import { instance } from '@viz-js/viz';
import fs from 'node:fs';
const viz = await instance();
const dot = fs.readFileSync('diagram.dot', 'utf8');
const svg = viz.renderString(dot, {
engine: 'dot',
format: 'svg',
images: [{ name: 'motif.svg', width: '96pt', height: '64pt' }]
});
fs.mkdirSync('bundle', { recursive: true });
fs.copyFileSync('motif.svg', 'bundle/motif.svg');
fs.writeFileSync('bundle/diagram.svg', svg);
process.stdout.write(`Graphviz ${viz.graphvizVersion}\n`);Viz.js의 API 문서는 images 옵션을 이미지 크기 정보로 설명합니다. 이를 제공하면 레이아웃에 해당 그림 정보를 전달하지만 파일 바이트를 결과에 넣지는 않습니다. 단위를 명시하면 단위 없는 숫자를 CSS 픽셀로 취급하는 혼동을 피할 수 있습니다. 이 API는 단위 없는 크기에 포인트를 사용합니다.
네이티브 Graphviz 설치의 공식 image 문서는 로컬 이미지 리소스와 원본 파일에서 읽는 크기를 설명합니다. WebAssembly 메타데이터 설정을 네이티브 명령에 복사한 뒤 같은 로딩 방식을 사용한다고 가정하지 마세요.
렌더러가 작성한 결과 확인하기
생성된 SVG에는 다음 요소가 들어 있습니다.
<image xlink:href="motif.svg"
width="118.8px" height="79.2px"
preserveAspectRatio="xMinYMin meet"
x="5.4" y="-79.2"/>크기와 위치는 이 예제에서 관찰한 값입니다. 전달을 좌우하는 부분은 xlink:href="motif.svg"입니다. 결과는 여전히 해당 상대 경로에 리소스가 있어야 합니다.
diagram.svg만 다른 폴더에 복사하고 그림은 남겨 두세요. 완전한 묶음과 비교하세요. 두 폴더를 로컬 HTTP로 제공하고 각 SVG를 HTML object 요소를 통해 문서로 표시했습니다.

링크된 모티프가 없어도 생성된 노드 상자와 화살표는 남습니다. 그래프 레이아웃을 다시 만들어도 빠진 파일은 생기지 않습니다. 예상 에셋 위치를 복원하거나 전체 묶음을 전달하거나 대상에 맞는 패키징 단계를 선택하세요.
SVG를 문서로 여는 것과 HTML img로 표시하는 것은 다른 테스트입니다. MDN의 SVG 이미지 사용 가이드는 이미지 문맥에서 외부 리소스를 제한할 수 있지만 데이터 URL로 인라인 포함할 수 있다고 설명합니다. 문서에서 설명하는 이미지 문맥 제한은 직접 여는 SVG 문서나 object, iframe을 통한 문서 삽입에는 적용되지 않습니다. 실제 사용할 전달 문맥을 확인하세요.
이 단순한 모티프를 명시적으로 패키징하기
이 자체 포함 원본 모티프에서는 다음 스크립트가 알려진 참조 하나를 파일의 SVG 바이트로 정확히 교체합니다. package.mjs로 저장하고 렌더링 뒤 실행하세요.
import fs from 'node:fs';
const svg = fs.readFileSync('bundle/diagram.svg', 'utf8');
const needle = 'xlink:href="motif.svg"';
if (svg.split(needle).length !== 2) {
throw new Error('Expected exactly one motif reference');
}
const data = 'data:image/svg+xml;base64,' +
fs.readFileSync('bundle/motif.svg').toString('base64');
const packaged = svg.replace(needle, `xlink:href="${data}"`);
fs.writeFileSync('self-contained.svg', packaged);이는 특정 대상을 위한 패키징 예제이며 범용 SVG 인라인 도구가 아닙니다. 이 출력의 알려진 참조와 외부 글꼴, 이미지, 스타일시트나 다른 의존성이 없는 모티프를 처리합니다. 더 복잡한 그림은 별도의 의존성 검사가 필요합니다.
패키징 사본은 브라우저 테스트에서 모티프가 표시되었습니다. 이미지 참조 값을 가린 뒤 두 출력 문자열을 비교하니 그래프 도형이 같았습니다. 파일에는 이미지 요소 하나가 그대로 있으며, 이제 참조가 data:image/svg+xml;base64,로 시작합니다.
SVG 이미지 바이트를 삽입하면 그림의 벡터 소스를 유지하면서 이 파일 경로 의존성을 없앨 수 있습니다. 그렇다고 네이티브 Graphviz 노드 모양이 되거나 내부 연결점이 생기거나 다른 편집기가 경로를 직접 노출한다고 보장되지는 않습니다. 수신 측 가져오기 동작을 테스트하세요.
svg_inline을 이미지 삽입과 혼동하지도 마세요. Graphviz의 SVG 출력 문서는 이를 HTML 포함용 헤더 없는 출력으로 설명합니다. 같은 그래프에서 svg_inline을 선택해도 motif.svg 참조가 생성됐습니다. 출력 모드가 그림을 패키징하지는 않았습니다.
크기와 크기 조절을 이동성과 구분하기
Graphviz의 imagescale 참고 문서는 이미지를 노드 안에 맞추는 것과 원본의 자연 크기를 구분합니다. 이 예제의 imagescale=true는 균일하게 크기를 조절해 맞춥니다. both 옵션은 너비와 높이를 따로 조절하므로 비율이 바뀔 수 있습니다.
모티프가 표시되지만 늘어났다면 크기 조절 옵션을 확인하세요. 일부만 보이면 자체 경계와 노드의 사용 가능 공간을 확인하세요. 파일 이동 후 사라지면 리소스 경로부터 확인하세요. SVG 크기 가이드는 선언한 크기와 그리기 좌표의 차이를 설명합니다.
| 증상 | 먼저 확인할 사항 | 시도할 수정 |
|---|---|---|
| 다이어그램 이동 후 그림이 사라짐 | 생성된 이미지 참조와 상대 에셋 위치 | 묶음을 복원하거나 테스트한 원본을 명시적으로 패키징 |
| 그래프 레이아웃은 실행되지만 그림 없음 | 원본 크기와 빌드별 이미지 설정 | 해당 빌드가 예상하는 파일과 이미지 메타데이터 확인 |
| 모티프가 늘어나 보임 | imagescale 설정과 의도한 비율 | 왜곡을 원하지 않으면 균일 맞춤 사용 |
| SVG를 직접 열면 되지만 웹페이지에서는 실패 | 페이지의 이미지 또는 문서 문맥 사용 여부 | 지원되는 삽입 방식과 리소스 정책 테스트 |
| 렌더러를 바꾼 뒤 출력이 달라짐 | 선택한 렌더러와 SVG 구조 | 내보낸 XML과 최종 모양 재확인 |
공식 SVG 출력 페이지는 Cairo 출력의 XML 가독성과 변환 가능성이 기본 SVG 출력과 다를 수 있다고 설명합니다. 여기서는 Cairo를 테스트하지 않았습니다. 재현 가능한 프로젝트에서는 렌더러를 명시하고 바꿀 때 패키징 검사를 반복하세요.
원본을 잃어버린 그림은 앞 단계에서 복원하기
적합한 일러스트 모티프가 PNG나 스캔으로만 남았다면 PerfectVector가 도움이 될 수 있습니다. 과학 그림 복원 작업 흐름은 사용 전에 확인할 벡터 후보를 제공합니다. 모티프만 자르고 실루엣과 빈 공간을 확인한 뒤 그래프에 추가하기 전에 다운로드 SVG의 경계와 크기를 검증하세요.
이 복원은 노드 관계, 화살표 의미나 DOT 레이블을 재구성하지 않습니다. 그런 정보는 그래프 소스에 유지하세요. 원본 SVG가 있으면 사용하고, 관리하기 쉬운 단순한 기호는 직접 다시 그리며, 사진은 래스터 이미지로 보존하세요. 이미지 벡터화 개요는 복원의 한계를 설명합니다.
다른 다이어그램 도구는 사용자 지정 그림을 다른 방식으로 패키징합니다. Mermaid 아이콘 가이드는 등록한 아이콘 데이터를 다루고, draw.io 사용자 지정 SVG 그림은 가져온 이미지와 네이티브 스텐실을 구분합니다. 그림 준비에 대상의 요구사항을 반영하세요.
FAQ
Graphviz SVG 출력은 노드 이미지를 자동으로 포함하나요? 테스트한 기본 SVG 출력에서는 다이어그램에 별도 motif.svg 파일을 가리키는 이미지 참조가 있습니다. 자신의 출력을 확인하고 의존 파일을 전달하거나 테스트한 패키징 단계를 사용하세요.
svg_inline은 SVG 이미지 경로를 그래프에 병합하나요? 아닙니다. HTML 포함용 헤더 없는 출력 모드입니다. 테스트에서는 외부 motif.svg 참조가 유지됐습니다.
자체 포함 SVG는 편집 가능한 네이티브 노드 도형과 같나요? 아닙니다. 패키징 예제는 SVG 바이트를 포함한 이미지 요소를 유지합니다. 그래프 구조는 DOT에 남고, 실제 수신 편집기가 그림을 어떻게 노출할지 결정합니다.
Sources
- Graphviz — image — 로컬 노드 이미지 리소스와 필요한 SVG 크기를 설명합니다.
- Graphviz — imagescale — 균일 맞춤과 독립적인 너비·높이 조절을 설명합니다.
- Graphviz — SVG 출력 — 기본·Cairo 출력과 svg_inline의 의미를 설명합니다.
- Viz.js — API — 이미지 크기 메타데이터, 명시적 단위와 SVG 렌더링 호출을 설명합니다.
- MDN — 이미지로 사용하는 SVG — 이미지 문맥의 외부 리소스 제한과 문서 삽입의 차이를 설명합니다.
그림 라이브러리 전체를 준비하기 전에 노드 하나를 전달 작업 흐름으로 테스트하세요. 래스터 모티프만 남았다면 SVG 그림 후보를 준비하고 간격과 비율을 확인하세요. 그런 다음 DOT 그래프에 추가하고 이동하거나 패키징한 출력을 수신 뷰어에서 검증하세요.

