> [Site index](https://perfectvector.com/llms.txt) — available pages and descriptions.

# Cytoscape.js SVG 노드 이미지: 맞춤 크기와 여백 조정

> 실행 가능한 예제로 Cytoscape.js 노드 안에 맞춤 SVG 아트워크를 배치합니다. 원본 여백과 contain·cover를 비교하고 로딩과 레이블 위치를 확인하세요.

Source: https://perfectvector.com/ko/blog/cytoscape-svg-node-artwork

Language: ko
Author: Irene Kim
Published: 2026-10-02T08:00:00+09:00
Updated: 2026-10-02T08:00:00+09:00

노드의 `background-image` 스타일에 SVG 이미지 URL을 지정한 뒤, 보여 주려는 아트워크에 맞는 크기 맞춤 방식을 선택하세요. 엠블럼이 로딩되지만 너무 작아 보인다면 그래프 노드를 키우기 전에 SVG 뷰포트 안의 빈 공간을 확인합니다. 양 끝이 사라진다면 이미지와 노드의 비율을 비교하고 잘림을 확인하세요.

Cytoscape.js는 `contain`, `cover`, `none` 맞춤 방식을 포함해 [SVG 노드 배경을 문서화](https://js.cytoscape.org/#style/background-image)하고 있습니다. 이 가이드는 경로 하나로 자체 제작한 엠블럼을 사용해 원본 범위와 그래프 스타일을 구분합니다. 편집 가능한 아트워크 마스터를 그래프 설정과 함께 보관하세요.

## 원본 이미지와 그래프 노드 구분하기

확인할 사각 영역은 아트워크가 실제로 그려진 범위, SVG 이미지 뷰포트, 노드 본체의 세 가지입니다. [SVG의 `viewBox`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/viewBox)는 뷰포트에 대응시키는 원본 좌표 사각형을 정의합니다. 눈에 보이는 그림보다 훨씬 넓은 공간을 포함할 수도 있습니다.

여백을 줄인 원본은 120 × 60이며 산호색 엠블럼은 x=6부터 x=114, y=6부터 y=54까지 차지합니다. 가운데 구멍도 같은 경로의 일부입니다.

```svg
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg>
<svg xmlns="http://www.w3.org/2000/svg"
     width="120" height="60" viewBox="0 0 120 60">
  <path fill="#f36f59" fill-rule="evenodd"
    d="M6 30L30 6H90L114 30L90 54H30Z M50 20H70V40H50Z"/>
</svg>
```

여백을 넣은 변형은 바깥쪽 SVG 치수와 `viewBox`만 바꿉니다.

```svg
<svg xmlns="http://www.w3.org/2000/svg"
     width="200" height="140" viewBox="-40 -40 200 140">
```

헤더, 경로, 닫는 태그는 그대로 유지하세요. 두 파일은 동일한 경로 좌표를 그립니다. 두 번째 파일은 그 주위에 더 많은 빈 원본 공간을 둡니다. 이 공간은 이미지와 함께 확대·축소되므로 배경 맞춤 방식을 바꾸는 것만으로 적절한 원본 범위 선택을 확실하게 대신할 수는 없습니다. 파일의 뷰포트와 보이는 아트워크가 맞지 않을 때는 [SVG 바운딩 박스 가이드](https://perfectvector.com/ko/blog/svg-bounding-box)가 도움이 됩니다.

## 네 가지 사례 예제 실행하기

Cytoscape.js [3.34.3](https://github.com/cytoscape/cytoscape.js/releases/tag/v3.34.3)을 버전이 고정된 공식 브라우저 번들로 로컬에서 제공해 테스트했습니다. [해당 릴리스 태그의 번들](https://raw.githubusercontent.com/cytoscape/cytoscape.js/v3.34.3/dist/cytoscape.min.js)을 `cytoscape-3.34.3.min.js`로 저장하고 아래 `example.html` 옆에 두세요. 예를 들어 `python3 -m http.server 8000`으로 폴더를 로컬 HTTP로 제공한 뒤 `http://localhost:8000/example.html`을 엽니다.

예제는 원본 SVG를 데이터 URI로 인코딩합니다. [`encodeURIComponent()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)는 채우기 색상의 `#`을 포함한 URI 문자를 이스케이프합니다. 라이브러리의 SVG 안내는 Base64 대신 이 인코딩을 사용하고, 여기에 제시한 XML 헤더를 넣도록 권장합니다. 외부 글꼴이나 이미지가 없는 독립적인 엠블럼 하나입니다.

```html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>SVG node fit comparison</title>
<style>
  body { font: 16px system-ui; margin: 20px; }
  #cy { width: 1100px; height: 250px; border: 1px solid #ddd; }
  #status { white-space: pre-wrap; }
</style>
<div id="cy"></div>
<pre id="status">Loading images</pre>
<script src="cytoscape-3.34.3.min.js"></script>
<script>
const header = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg>';
const path = 'M6 30L30 6H90L114 30L90 54H30Z M50 20H70V40H50Z';
function artwork(padded) {
  const width = padded ? 200 : 120;
  const height = padded ? 140 : 60;
  const viewBox = padded ? '-40 -40 200 140' : '0 0 120 60';
  return header + `<svg xmlns="http://www.w3.org/2000/svg"
    width="${width}" height="${height}" viewBox="${viewBox}">
    <path fill="#f36f59" fill-rule="evenodd" d="${path}"/></svg>`;
}
const cases = [
  ['tight contain', false, 'contain'],
  ['tight cover', false, 'cover'],
  ['padded contain', true, 'contain'],
  ['padded cover', true, 'cover']
].map(([label, padded, fit]) => ({
  label, fit,
  image: 'data:image/svg+xml;utf8,' + encodeURIComponent(artwork(padded))
}));
Promise.all(cases.map(item => new Promise((resolve, reject) => {
  const image = new Image();
  image.onload = () => resolve({
    label: item.label,
    width: image.naturalWidth,
    height: image.naturalHeight
  });
  image.onerror = () => reject(new Error(item.label + ' failed to load'));
  image.src = item.image;
}))).then(loaded => {
  cytoscape({
    container: document.getElementById('cy'),
    elements: cases.map((item, index) => ({
      data: { id: 'n' + index, ...item },
      position: { x: 110 + index * 260, y: 95 }
    })),
    style: [{ selector: 'node', style: {
      width: 120, height: 80, padding: 0, shape: 'rectangle',
      'background-color': '#f1f3f5',
      'background-image': 'data(image)',
      'background-fit': node => node.data('fit'),
      'background-width': 'auto', 'background-height': 'auto',
      'background-width-relative-to': 'inner',
      'background-height-relative-to': 'inner',
      'background-position-x': '50%', 'background-position-y': '50%',
      'background-repeat': 'no-repeat', 'background-clip': 'node',
      'border-width': 1, 'border-color': '#222',
      label: 'data(label)', 'text-valign': 'bottom',
      'text-halign': 'center', 'text-margin-y': 10, 'font-size': 12
    }}],
    layout: { name: 'preset', fit: false },
    zoom: 1, pan: { x: 0, y: 0 },
    userZoomingEnabled: false, userPanningEnabled: false,
    boxSelectionEnabled: false
  });
  document.getElementById('status').textContent =
    'Cytoscape ' + cytoscape.version + '\n' +
    JSON.stringify(loaded, null, 2);
}).catch(error => {
  document.getElementById('status').textContent = error.message;
});
</script>
</html>
```

상태 블록은 그래프 초기화 전에 미리 불러온 이미지의 치수를 보고합니다. [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth)의 설명처럼 `naturalWidth`는 이미지 고유의 밀도 보정 너비를 CSS 픽셀로 읽습니다. 이 테스트 파일에서 여백을 줄인 이미지는 120 × 60, 여백을 넣은 이미지는 200 × 140으로 보고되었습니다. 이는 이미지 치수이며 산호색 경로를 측정한 값이 아닙니다.

## 같은 노드 크기에서 무엇이 달라지는지 비교하기

모델의 네 노드는 모두 120 × 80이며 노드 패딩은 0입니다. 원본 테스트 파일을 Chrome에서 그래프 줌 1과 1.5로 확인했습니다. 노드 스타일은 120 × 80을 유지했고, 보고된 렌더링 치수는 1.5에서 180 × 120이 되었습니다. 해당 브라우저에서의 정적 비교이며 호환성이나 줌 성능 벤치마크가 아닙니다.

| 원본과 맞춤 방식       | 이 테스트 파일에서 관찰한 모습                           |
| --------------- | ------------------------------------------- |
| 여백을 줄임, contain | 뾰족한 양 끝이 보이는 완전한 엠블럼                        |
| 여백을 줄임, cover   | 더 큰 엠블럼이지만 왼쪽과 오른쪽 끝이 노드에서 잘림               |
| 여백을 넣음, contain | 작은 엠블럼 주위에 상당한 빈 공간이 있음                     |
| 여백을 넣음, cover   | 여백을 넣은 contain보다 조금 크지만 여백을 줄인 사례들보다는 훨씬 작음 |

여백을 줄인 원본의 이미지 비율은 2:1이고 노드는 1.5:1입니다. 120 × 60 이미지 전체를 120 × 80 안에 넣으면 세로 공간이 남습니다. 그 노드를 덮으면 잘리기 전에 이미지가 160 × 80으로 확대되므로 가로 양 끝이 본체 밖으로 나갑니다.

여백을 넣은 원본에서는 사용 가능한 이미지 사각형에 각 변마다 40단위의 추가 공간이 들어 있습니다. contain 맞춤에서는 배율이 120/200이 아닌 80/140으로 제한됩니다. 따라서 너비 108단위인 동일한 엠블럼은 모델 단위로 약 62를 차지합니다. 이 수치는 선언된 치수로 계산한 값이며 스크린샷의 픽셀 측정값이 아닙니다.

**원본 범위와 맞춤 방식**

![원본 여백이 넓은 작은 엠블럼, 노드 프레임 안에 완전히 들어가는 더 큰 엠블럼, 좁은 프레임에 양 끝이 잘린 엠블럼을 보여 주는 그림.](https://perfectvector.com/blog/cytoscape-svg-node-artwork/source-bounds-fit.webp)

*개념도: 원본 여백과 맞춤 방식은 보이는 아트워크를 각각 독립적으로 바꿀 수 있습니다. 이 그림은 Cytoscape 스크린샷이나 변환 결과물이 아닙니다.*

## 아트워크 범위를 살펴본 뒤 맞춤 방식 선택하기

엠블럼 전체를 보여 주는 것이 중요하다면 여백을 줄인 원본과 contain으로 시작하세요. 보여야 하는 선이나 효과를 위해 충분한 원본 여백은 남겨 둡니다. 뷰포트를 지나치게 좁히면 필요한 아트워크까지 잘릴 수 있습니다. 모든 여백을 없애라는 뜻은 아닙니다.

디자인에서 가장자리 잘림을 허용할 수 있다면 cover를 사용하세요. 이 예제에서는 뾰족한 끝을 가리므로 그 끝이 엠블럼의 특징이라면 좋은 선택이 아닙니다. 노드를 더 넓게 만들면 맞춤 비율이 바뀌어 끝이 보일 수 있지만, 그래프 레이아웃도 달라집니다. 두 치수를 같은 비율로 키우면 잘림은 그대로입니다. 어떤 제약을 바꿀지 결정하세요.

이 비교에서는 `background-width`와 `background-height`를 `auto`로 유지합니다. 명시적인 값은 크기 맞춤에 쓰이는 이미지 치수를 덮어쓸 수 있습니다. 노드의 `padding`도 별개의 입력입니다. 라이브러리는 배경 크기 계산에 패딩을 포함하는지, 안쪽 본체를 사용하는지를 설명합니다. 이 제어 항목을 추가하기 전에 [background-image 참조 문서](https://js.cytoscape.org/#style/background-image)를 확인하세요. 패딩이 0인 이 테스트 파일은 먼저 원본 여백을 분리해 살펴봅니다.

SVG 수준의 meet, slice, 정렬 결정은 [preserveAspectRatio 가이드](https://perfectvector.com/ko/blog/svg-preserveaspectratio)로 이어서 확인하세요. SVG 내부 맞춤을 바꾸는 것과 Cytoscape 배경 맞춤을 바꾸는 것은 별개의 작업입니다.

## 잘림보다 로딩을 먼저 진단하기

상태에 로딩 실패가 보고된다면 다음 단계는 contain을 cover로 바꾸는 것이 아닙니다. 이미지 리소스 자체를 열고 URL과 선언된 치수를 확인한 다음, 위의 경로만 있는 독립적인 엠블럼으로 단순화하세요. 데이터 URI에서는 원시 마크업이나 이스케이프하지 않은 색상 값을 이어 붙이지 말고 SVG 문자열 전체를 인코딩합니다.

이미지로 쓰는 SVG는 문서로 여는 SVG와 제약이 다릅니다. [MDN의 이미지로 사용하는 SVG 가이드](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image)는 이미지 컨텍스트에서 스크립트와 외부 리소스에 적용되는 제약을 설명합니다. 외부 스타일시트나 글꼴에 의존하는 아트워크 파일은 별도의 전달 테스트가 필요합니다. 이 예제는 그런 의존성을 피하고 그래프 레이블을 SVG 바깥에 둡니다.

이미지가 로딩된다면 명확하게 가로로 긴 모양으로 맞춤과 노드 잘림을 확인하세요. 그런 다음 애플리케이션이 지원하는 노드 크기와 브라우저 환경에서 실제 아트워크를 시험합니다. Cytoscape 문서는 브라우저별 SVG 고려 사항을 안내합니다. 이 Chrome 관찰 결과가 Firefox나 다른 모든 엔진의 문제까지 해결하지는 않습니다.

## 레이블과 편집 가능한 아트워크를 분리하기

예제는 그래프 레이블에 `label: 'data(label)'`을 사용하며 SVG 텍스트는 포함하지 않습니다. 엠블럼을 다시 만들지 않고도 문구를 바꿀 수 있습니다. SVG 경로는 원본 마스터에 남고, 그래프는 노드 식별, 배치, 관계를 관리합니다.

확인한 테스트 파일은 Canvas 표면에 그렸습니다. 거기에 SVG 배경이 보인다고 내부 경로가 따로 편집 가능한 그래프 요소가 되지는 않습니다. 구멍, 실루엣, 색상을 바꿔야 할 때를 위해 마스터를 보관하세요. 그래프 내보내기는 별도 작업이며 내보내기 도구 선택과 전달 테스트가 필요합니다. 이 가이드는 내보낸 그래프가 편집 가능한 엠블럼 경로를 유지한다고 약속하지 않습니다. [Graphviz 아트워크 가이드](https://perfectvector.com/ko/blog/graphviz-svg-node-images)는 다른 다이어그램 렌더러에서 이미지 참조를 전달하는 방식을 살펴봅니다.

맞춤 엠블럼이 PNG나 JPG로만 있다면 [그 원본을 벡터 아트워크로 변환](https://perfectvector.com/ko/image-to-vector)한 뒤 실루엣, 구멍, 작은 세부 요소를 확인하고 SVG 범위를 설정하세요. PerfectVector는 편집 가능한 원본 형상 복구를 도울 수 있습니다. 배경 스타일, 노드 레이블, 그래프 내보내기는 별도 단계로 남습니다. 적합한 SVG가 이미 있다면 바로 맞춤 확인으로 넘어갈 수 있습니다.

## 자주 묻는 질문

**cover를 써도 SVG 노드 이미지가 작은 이유는 무엇인가요?**
원본 이미지의 뷰포트에 경로 주변의 넓은 빈 공간이 포함되어 있을 수 있습니다. 그래프 레이아웃을 바꾸기 전에 같은 노드 치수에서 범위를 좁힌 사본을 비교하세요.

**맞춤 엠블럼에는 contain과 cover 중 무엇을 써야 하나요?**
엠블럼 전체가 중요하면 contain을 선택하세요. 관찰한 가장자리 잘림이 디자인에서 허용될 때만 cover를 선택하고, 자신의 원본과 노드 모양으로 확인합니다.

**SVG 노드 배경이 편집 가능한 그래프 경로를 만드나요?**
테스트한 Canvas 예제는 SVG를 이미지로 그립니다. 경로 편집을 위해 아트워크 마스터를 보관하세요. 이 예제에서 내부 윤곽은 별도의 그래프 노드나 간선이 아닙니다.

**SVG 안에 레이블을 넣어도 되나요?**
이 예제는 레이블을 그래프 데이터에 두고 경로만 있는 아트워크를 사용합니다. SVG 텍스트, 글꼴, 이미지 컨텍스트 의존성은 각각 별도의 브라우저 확인과 전달 확인이 필요합니다.

## 출처

1. [Cytoscape.js — 배경 이미지](https://js.cytoscape.org/#style/background-image) — 이미지 URL 스타일, 맞춤, 크기 덮어쓰기, 패딩 기준, SVG 고려 사항.
2. [Cytoscape.js — 릴리스 v3.34.3](https://github.com/cytoscape/cytoscape.js/releases/tag/v3.34.3) — 원본 테스트 파일에 사용한 고정 릴리스.
3. [Cytoscape.js — v3.34.3 브라우저 번들](https://raw.githubusercontent.com/cytoscape/cytoscape.js/v3.34.3/dist/cytoscape.min.js) — 브라우저 테스트용으로 로컬에서 제공한 공식 태그 버전 구현.
4. [MDN — viewBox](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/viewBox) — 원본 좌표 사각형과 뷰포트 매핑.
5. [MDN — encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) — SVG 데이터 URI 구성 요소 이스케이프.
6. [MDN — naturalWidth](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth) — 경로 범위와 구분되는 로딩된 이미지 치수.
7. [MDN — 이미지로 사용하는 SVG](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image) — 이미지 컨텍스트 제약과 의존성 점검.

엠블럼이 래스터에서 출발한다면 [편집 가능한 SVG 마스터를 만들고](https://perfectvector.com/ko/image-to-vector), 윤곽과 원본 범위를 확인한 다음 자신의 노드 레이아웃에서 contain과 cover를 비교하세요.

## Explore

- [Read the HTML article](https://perfectvector.com/ko/blog/cytoscape-svg-node-artwork)
- [Leaflet SVG 마커: iconAnchor로 끝점 맞추기](https://perfectvector.com/ko/blog/leaflet-svg-marker-anchor.md)
- [배율을 혼동하지 않고 SVG 경로 길이 측정하기](https://perfectvector.com/ko/blog/measure-svg-path-length.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
