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

# SVG.js: 그림 가져오기, 경로 편집, SVG 내보내기

> 신뢰할 수 있는 SVG 마크업을 SVG.js로 가져와 이름이 있는 경로의 색을 바꾸세요. 전체 루트·자식 전용 출력을 비교하고 원본 도형과 저장 파일을 확인합니다.

Source: https://perfectvector.com/ko/blog/svgjs-import-export-artwork

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

부분 편집을 위해 SVG.js에 그림을 가져오려면 신뢰할 수 있는 SVG 마크업을 `.svg()`에 전달하고, 작성한 ID로 원하는 요소를 찾아 그 요소의 채움 색을 바꾸세요. 독립 파일로는 그림의 전체 SVG 루트를 내보냅니다. 자식만 내보낸 결과는 조각입니다. 문서로 전달하려면 의도한 치수와 `viewBox`를 가진 루트가 필요합니다.

이 안내는 직접 만든 속 빈 마름모와 별도의 삼각형을 사용합니다. 삼각형은 황토색에서 산호색으로 바뀌고, 마름모는 청록색 채움과 구멍을 유지합니다. 아래의 완전한 예제를 공식 [3.2.6 릴리스](https://github.com/svgdotjs/svg.js/releases/tag/3.2.6)로 고정한 SVG.js **3.2.6**으로 시험했습니다. 이 관찰은 단순한 자체 작성 경로 두 개에 관한 것이며 다른 SVG의 모든 기능을 다루지는 않습니다.

## 편집 가능한 도형과 이미지 중 무엇이 필요한지 정하기

파일 URL을 만드는 JavaScript import 문은 로드 문제에 답합니다. 그것만으로 파일의 경로가 편집기의 실제 SVG 트리에 들어가지는 않습니다. SVG.js의 현재 [가져오기·내보내기 문서](https://svgjs.dev/docs/3.2/importing-exporting/)는 마크업을 가져오고 바깥 SVG 요소 또는 그 자식을 얻는 방법을 설명합니다.

| 표현 방식                       | 이 예제에서 접근할 수 있는 대상 | 전달 점검                       |
| --------------------------- | ------------------ | --------------------------- |
| 실제 SVG 루트로 가져온 신뢰할 수 있는 마크업 | 이름이 `accent`인 경로   | 편집 루트를 확인하고 내보낸 파일 다시 열기    |
| 이미지 요소로 로드한 SVG             | 이미지 요소 전체          | 이미지 데이터 별도 점검               |
| 자식 전용 마크업                   | 원래 루트 없는 경로 요소 두 개 | 루트, 치수, `viewBox`를 의도적으로 제공 |

이미지 안의 SVG도 여전히 SVG 콘텐츠입니다. 다만 이미지 래퍼 대조군에서 바깥 SVG 트리에는 이미지 요소 하나만 있고 직접적인 경로는 없습니다. 그 트리에서 `accent`를 찾아도 아무것도 나오지 않습니다. 내장 이미지의 문서 안까지 접근하지 않기 때문입니다. MDN은 별도의 [SVG 이미지 컨텍스트](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image)와 제한을 설명합니다. 선명한 렌더링만으로 편집 방식을 추정하지 마세요.

더 넓은 삽입 방식 선택은 [인라인 SVG와 이미지 비교](https://perfectvector.com/ko/blog/inline-svg-vs-img)를 읽으세요. Fabric의 캔버스 객체 모델을 원한다면 [Fabric.js 가져오기 안내](https://perfectvector.com/ko/blog/fabricjs-import-svg)가 다른 파서와 편집 API를 다룹니다.

## 이름이 있는 경로 하나를 편집하고 각 표현 저장하기

아래 완전한 코드를 빈 폴더에 `starter.html`로 저장하세요. 예를 들어 `python3 -m http.server 8000`으로 HTTP 서버를 실행한 뒤 `http://localhost:8000/starter.html`을 엽니다. 스크립트는 CDN에서 고정 버전 패키지를 로드하므로 네트워크 연결이 필요합니다.

페이지는 원본 그림, 실제로 편집한 사본, 이미지 래퍼 대조군을 표시합니다. 링크에서는 원본, 편집 전후 전체 루트, 자식만 있는 텍스트 조각, 새 루트로 감싼 사본, 이미지 래퍼를 다운로드합니다. 보고서는 캔버스에 그린 SVG 이미지에서 픽셀을 읽으며 PNG를 내보내지는 않습니다.

```html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Original SVG.js artwork import and export</title>
<style>
  body { margin: 24px; font: 16px system-ui; background: #f6f2e8; }
  main { display: grid; grid-template-columns: repeat(3, 260px); gap: 20px; }
  figure { margin: 0; }
  svg, img { display: block; background: white; border: 1px solid #bbb; }
  pre { white-space: pre-wrap; font-size: 12px; }
</style>
<h1>Trusted artwork, one fill edit and two export forms</h1>
<main>
  <figure><img id="original" alt="Original artwork"><figcaption>Original SVG image</figcaption></figure>
  <figure><div id="live"></div><figcaption>Imported live SVG, accent edited</figcaption></figure>
  <figure><div id="wrapper"></div><figcaption>Image wrapper, original artwork</figcaption></figure>
</main>
<p id="downloads"></p>
<pre id="report"></pre>
<script src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@3.2.6/dist/svg.min.js"></script>
<script>
  const markup = '<svg xmlns="http://www.w3.org/2000/svg" id="original-artwork" width="240" height="160" viewBox="0 0 240 160">'
    + '<path id="body" d="M80 20 L140 80 L80 140 L20 80 Z M80 56 L104 80 L80 104 L56 80 Z" fill="#176b5b" fill-rule="evenodd"/>'
    + '<path id="accent" d="M172 48 L220 80 L172 112 Z" fill="#d4a53a"/></svg>';
  const url = text => 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(text);
  async function pixels(text) {
    const image = new Image();
    image.src = url(text);
    await image.decode();
    const canvas = document.createElement('canvas');
    canvas.width = 240;
    canvas.height = 160;
    const ctx = canvas.getContext('2d');
    ctx.drawImage(image, 0, 0);
    const rgba = (x, y) => [...ctx.getImageData(x, y, 1, 1).data];
    return { naturalWidth: image.naturalWidth, naturalHeight: image.naturalHeight,
      opening: rgba(80, 80), body: rgba(80, 40), accent: rgba(188, 80), corner: rgba(0, 0) };
  }
  function inventory(text) {
    const node = new DOMParser().parseFromString(text, 'image/svg+xml').documentElement;
    return { root: node.localName, viewBox: node.getAttribute('viewBox'),
      paths: [...node.querySelectorAll('path')].map(p => ({ id: p.id, d: p.getAttribute('d'), fill: p.getAttribute('fill') })),
      imageCount: node.querySelectorAll('image').length };
  }
  async function run() {
    document.getElementById('original').src = url(markup);
    const host = SVG().addTo('#live').size(240, 160).viewbox(0, 0, 240, 160);
    host.svg(markup);
    const artwork = host.findOne('#original-artwork');
    const before = artwork.svg();
    const accent = artwork.findOne('#accent');
    const beforeD = accent.attr('d');
    accent.fill('#b95434');
    const full = artwork.svg();
    const children = artwork.svg(false);
    const rewrapped = SVG().size(240, 160).viewbox(0, 0, 240, 160);
    rewrapped.svg(children);
    const wrappedFull = rewrapped.svg();
    const imageWrapper = SVG().addTo('#wrapper').size(240, 160).viewbox(0, 0, 240, 160);
    imageWrapper.image(url(markup)).size(240, 160);
    const wrapperFull = imageWrapper.svg();
    const files = { 'master.svg': markup, 'before.svg': before, 'edited.svg': full,
      'children-only.txt': children, 'rewrapped.svg': wrappedFull, 'image-wrapper.svg': wrapperFull };
    for (const [name, text] of Object.entries(files)) {
      const a = document.createElement('a');
      a.href = name.endsWith('.txt') ? 'data:text/plain;charset=utf-8,' + encodeURIComponent(text) : url(text);
      a.download = name;
      a.textContent = name;
      a.style.marginRight = '12px';
      document.getElementById('downloads').append(a);
    }
    const results = {};
    for (const [name, text] of Object.entries(files)) {
      if (name.endsWith('.svg')) results[name] = { inventory: inventory(text), pixels: await pixels(text) };
    }
    document.getElementById('report').textContent = JSON.stringify({
      requestedPackageVersion: '3.2.6',
      scriptURL: document.querySelector('script[src]').src,
      selectedAccentFound: Boolean(accent), selectedAccentDUnchanged: beforeD === accent.attr('d'),
      allPathDUnchanged: JSON.stringify(inventory(before).paths.map(p => p.d)) === JSON.stringify(inventory(full).paths.map(p => p.d)),
      childrenHasOuterSVG: /<svg[\s>]/i.test(children),
      wrapperDirectPathCount: imageWrapper.find('path').length,
      wrapperAccentFound: Boolean(imageWrapper.findOne('#accent')), results
    }, null, 2);
  }
  run();
</script>
</html>

```

가져온 마크업에는 `original-artwork`라는 중첩 루트가 있습니다. 예제는 내보내기 전에 그 루트를 선택하므로, 전달 사본은 무관한 상위 컨테이너에 의존하지 않고 작성한 `240 × 160` 뷰포트를 가집니다. 그다음 해당 루트 안의 `accent`를 선택합니다. SVG.js는 [선택자 기반 참조와 요소 메서드](https://svgjs.dev/docs/3.2/referencing-creating-elements/)를 문서화합니다. 명시적인 부분 이름을 사용하면 경로 순서에 의존하지 않아도 됩니다.

이 코드는 의도적으로 자체 고정 마크업에만 한정됩니다. **SVG 업로드 정화 도구가 아닙니다**. 임의의 문자열을 파싱하거나 삽입한다고 안전함이 입증되지는 않습니다. MDN의 [DOMParser 참고 문서](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString)는 파싱과 신뢰할 수 없는 콘텐츠 삽입의 위험을 구분합니다. 업로드에 이 루틴을 적용하기 전에 별도 검증·신뢰 정책을 설계하세요.

## 실시간 미리보기뿐 아니라 저장 결과 확인하기

실제 브라우저 실행에서 다음을 확인했습니다.

| 저장 표현          | 문서 트리의 경로 | 이미지 | 삼각형 채움            |
| -------------- | --------- | --- | ----------------- |
| 원본             | 2         | 0   | `#d4a53a`         |
| 편집 전 전체 루트     | 2         | 0   | `#d4a53a`         |
| 편집 후 전체 루트     | 2         | 0   | `#b95434`         |
| 새 전체 루트에 넣은 자식 | 2         | 0   | `#b95434`         |
| 이미지 래퍼         | 0         | 1   | 이미지 데이터 안의 원래 황토색 |

원래 두 경로의 `d` 문자열은 편집 전후 출력에서 동일하게 유지됐습니다. 삼각형 내부 표본은 RGBA `(212, 165, 58, 255)`에서 `(185, 84, 52, 255)`로 바뀌었습니다. 마름모 내부 표본은 `(23, 107, 91, 255)`를 유지했고, 구멍과 바깥 모서리는 알파 `0`이었습니다. 독립 SVG 파일 다섯 개 모두 이미지로 다시 열었을 때 고유 치수가 `240 × 160`이었습니다.

**이름이 있는 부분 하나 바꾸기**

![같은 속 빈 마름모 그림에서 별도 삼각형만 금색에서 산호색으로 바뀌는 개념 비교](https://perfectvector.com/blog/svgjs-import-export-artwork/named-path-edit.webp)

*부분 색상 편집의 개념 삽화입니다. 장식 경계와 화살표는 도해용 단서입니다. 실행한 시작 예제, 저장 원본 목록, 브라우저 픽셀 점검이 실제 근거를 제공합니다.*

이 결과는 이 시험 파일에서 의도한 편집을 확인합니다. 바이트 단위로 같은 XML 보존, 모든 필터·CSS 지원, 제조 작업 적합성을 입증하지는 않습니다. 라이브러리의 직렬화는 이 특정 경로 문자열을 유지하면서도 문서 마크업을 바꿀 수 있습니다. 원본을 전달 사본과 함께 보관하세요.

자신의 그림에서는 실제 사용하는 구조를 확인하세요. 이름과 그룹, 클리핑, 그라디언트, 변환, 스트로크, 텍스트가 해당합니다. 내보낸 파일을 수신 애플리케이션에서 다시 열고 의도한 편집을 반복하세요. [SVG 편집 가이드](https://perfectvector.com/ko/blog/how-to-edit-an-svg)는 가져오기 코드를 바꾸기 전에 원본 구조를 진단하는 데 도움이 됩니다.

## 자식 전용 출력을 의도적인 조각으로 다루기

이번 실행에서 `artwork.svg(false)`는 바깥 `svg` 태그 없이 경로 두 개를 반환했습니다. 그림 루트의 뷰포트가 빠졌습니다. 별도의 `rewrapped` SVG 루트는 자식을 받기 전에 `240 × 160` 치수와 같은 `viewBox`를 제공합니다. 내보낸 파일에서는 확인한 산호색 삼각형이 렌더링됩니다.

대상에 따라 완전한 문서와 조각 중 하나를 고르세요. 독립 다운로드에는 의도한 전체 루트를 유지합니다. 기존 그림에 삽입한다면 자식이 어느 상위 좌표계, 상속 스타일, 정의를 사용할지 정하세요. 이 단순한 시험 파일에는 외부 리소스나 공유 정의가 없으므로, 참조가 있는 조각이 필요한 모든 의존성을 함께 전달하는지는 시험하지 않습니다.

이미지 래퍼 출력에는 디코딩 바이트가 원본과 일치하는 인코딩 SVG가 유지됐습니다. 이 대조군은 표현 방식의 차이를 보여 주며 래스터 변환이 아닙니다. 원본이 이미 사용 가능한 벡터 도형이라면 다시 트레이싱하기 전에 요소 선택이나 내보내기 경계를 고치세요.

## 원본에 편집할 경로가 없는 경우

평면 PNG나 JPG 일러스트에 개별적으로 색을 바꿀 영역이 필요하다면 [PerfectVector로 SVG 후보를 준비](https://perfectvector.com/ko/image-to-vector)하세요. 윤곽과 구멍을 확인한 다음 애플리케이션에 필요한 부분 이름을 작성합니다. 벡터화는 어느 영역의 이름이 `accent`여야 하는지 알지 못하며, 가져온 문서가 편집기 데이터 모델에 맞는다고 보장하지도 않습니다.

해당 도형이 이미 있다면 적절한 SVG 원본을 유지하세요. [벡터화 개요](https://perfectvector.com/ko/blog/what-is-image-vectorization)로 코드 앞단에 래스터-벡터 준비가 필요한지 판단할 수 있습니다.

## 자주 묻는 질문

**SVG.js는 편집용 SVG 문자열을 가져올 수 있나요?**
네. 이 시작 예제는 자체의 신뢰할 수 있는 마크업을 실제 SVG 컨테이너로 가져와 작성한 경로를 선택하고 채움을 바꿉니다. 임의 업로드에는 별도 신뢰·검증 정책이 필요하며 마크업 API는 정화 도구가 아닙니다.

**그림은 보이는데 accent 경로를 찾을 수 없는 이유는 무엇인가요?**
실제 마크업을 가져왔는지 이미지를 놓았는지 확인하세요. 이 이미지 래퍼 대조군은 SVG 그림을 표시하지만 래퍼 트리에서 직접 접근할 accent 경로는 없습니다. 선택한 상위 요소와 원본의 실제 ID도 확인하세요.

**자식만 내보낸 결과가 완전한 SVG 파일인가요?**
이 시험 파일에서는 아닙니다. 바깥 SVG 뷰포트 없이 경로 두 개만 포함합니다. 독립 파일에는 의도한 전체 루트를 쓰거나, 조각을 삽입할 때 대상 루트와 좌표계를 명시적으로 제공하세요.

**편집에 성공하면 내보내기가 모든 SVG 기능을 보존한다고 볼 수 있나요?**
아닙니다. 단순한 두 경로, 채움 값, 정확한 경로 데이터, 다시 연 파일 다섯 개를 확인했습니다. 그림에 필요한 특정 기능과 수신 애플리케이션을 시험하고 원본을 보관하세요.

## 출처

1. [SVG.js — 가져오기·내보내기, 버전 3.2](https://svgjs.dev/docs/3.2/importing-exporting/) — 마크업 가져오기와 전체 루트·자식 전용 직렬화입니다.
2. [SVG.js — 요소 참조·만들기, 버전 3.2](https://svgjs.dev/docs/3.2/referencing-creating-elements/) — 이름이 있는 요소를 찾고 속성을 바꾸는 방법입니다.
3. [SVG.js — 릴리스 3.2.6](https://github.com/svgdotjs/svg.js/releases/tag/3.2.6) — 실행한 시작 예제에서 고정한 공식 릴리스입니다.
4. [MDN — 이미지로 사용하는 SVG](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image) — 이미지 삽입 컨텍스트와 제한입니다.
5. [MDN — DOMParser.parseFromString](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString) — 마크업 파싱과 신뢰할 수 없는 입력의 별도 처리입니다.

***

일러스트가 래스터 픽셀로만 있고 부분 편집이 필요하다면 [자신의 그림으로 벡터 후보를 준비하세요](https://perfectvector.com/ko/image-to-vector). 윤곽과 구멍을 확인하고 원본을 보관한 뒤 수신 작업 과정에서 이름을 지정한 편집과 저장 SVG를 검증하세요.

## Explore

- [Read the HTML article](https://perfectvector.com/ko/blog/svgjs-import-export-artwork)
- [MapLibre SVG 아이콘: 픽셀과 심볼 크기 확인하기](https://perfectvector.com/ko/blog/maplibre-svg-symbol-image.md)
- [SVG 패턴 변환: 윤곽은 유지하고 채우기만 회전하기](https://perfectvector.com/ko/blog/svg-pattern-transform.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
