SVG foreignObject 텍스트: 내보내기에서 빠진 레이블 해결하기
브라우저에서는 보이지만 내보내면 사라지는 SVG 레이블을 해결하세요. foreignObject와 네이티브 텍스트를 비교하고 네임스페이스를 확인하며 기존 그림을 보존합니다.
목차
SVG 도형은 내보내기 후 남지만 레이블이 사라지면 누락된 레이블에 <foreignObject>가 있는지 확인하세요. 브라우저는 잘 배치해도 대상 렌더러는 지원하지 않는 HTML이 들어 있을 수 있습니다. 해당 레이블을 네이티브 SVG <text>와 <tspan>으로 바꾸거나 모양을 유지하는 내보내기 방식을 선택하세요.
먼저 실제 내보낸 파일을 브라우저에서 여세요. 거기에서도 레이블이 없다면 가져오기 도구를 원인으로 보기 전에 네임스페이스, 경계와 스타일을 확인하세요. 원본 그림을 유지하세요. 텍스트 컨테이너만 실패했다면 전체 이미지를 추적할 필요는 없습니다.
그림은 남지만 레이블은 사라지는 이유
SVG는 일반 도형과 다른 XML 네임스페이스의 콘텐츠를 섞을 수 있습니다. <path>로 그린 산과 <circle>로 그린 해는 네이티브 SVG입니다. <foreignObject> 안의 문단은 고유한 줄바꿈과 배치 규칙을 쓰는 HTML일 수 있습니다. MDN foreignObject 참고 문서는 이 차이를 설명합니다.
따라서 .svg 확장자가 모든 부분이 같은 렌더링 기능을 쓴다는 보장은 아닙니다. 대상은 산과 해는 그려도 HTML 문단은 생략할 수 있습니다. 글자 색을 바꾸거나 내보내기 해상도를 높여도 렌더러에 HTML 지원이 추가되지는 않습니다.
| 보이는 현상 | 다음 확인 사항 | 가능한 해결 |
|---|---|---|
| 도형은 양쪽에 표시되지만 레이블은 브라우저에만 표시 | 누락된 레이블이 foreignObject를 사용하는가? | 해당 레이블을 교체하거나 내보내기 방식 변경 |
| 브라우저에서도 HTML 레이블 없음 | XHTML 네임스페이스, 명시적 경계, 표시 여부와 스타일 | HTML 컨테이너부터 수정 |
| 네이티브 텍스트의 글꼴이나 줄 길이가 달라짐 | 글꼴 가용성과 선택한 줄 위치 | 글꼴 해결 또는 최종 글자 윤곽선화 |
| 그림 대부분이 없음 | 뷰포트, 클리핑과 문서 구조 | 더 넓은 범위의 빈 SVG 검사 사용 |
작은 테스트: 레이블만 바꾸기
경로, 원과 ‘Keep artwork and labels separate.’ 문구가 있는 480 × 240 SVG 카드를 만들었습니다. 첫 파일은 HTML 레이블을 사용합니다. 두 번째는 같은 도형을 유지하면서 레이블만 네이티브 텍스트와 명시적인 세 줄로 바꿉니다.
브라우저 미리보기에서는 두 레이블 모두 표시됐습니다. 내장 librsvg 2.61.1을 사용하는 sharp 0.34.4로 같은 파일을 PNG로 렌더링하자 아래 결과가 나왔습니다. HTML 레이블은 사라지고 네이티브 레이블은 남았습니다. HTML 레이블 출력은 레이블을 제거한 대조 파일과 픽셀 단위로도 같았습니다. 이 파일들과 해당 렌더러 버전의 테스트이며 모든 편집기의 호환성을 판정하는 결과는 아닙니다.

원본 파일은 작아서 재현하기 쉽습니다. 다음을 html-label.svg로 저장하고 브라우저에서 여세요.
<svg xmlns="http://www.w3.org/2000/svg"
width="480" height="240" viewBox="0 0 480 240">
<rect width="480" height="240" rx="20" fill="#f5f1e7"/>
<path d="M40 135Q90 15 140 135Z" fill="#087f75"/>
<circle cx="90" cy="95" r="18" fill="#f4bc45"/>
<foreignObject x="180" y="70" width="230" height="110">
<div xmlns="http://www.w3.org/1999/xhtml"
style="font: 28px/1.25 Arial, sans-serif; color: #172b34;">
Keep artwork and labels separate
</div>
</foreignObject>
</svg>두 번째 파일에서는 foreignObject 요소 전체를 다음 레이블로 교체하고 native-label.svg로 저장하세요.
<text x="180" y="96" font-family="Arial, sans-serif"
font-size="28" fill="#172b34">
<tspan x="180" dy="0">Keep artwork</tspan>
<tspan x="180" dy="35">and labels</tspan>
<tspan x="180" dy="35">separate</tspan>
</text>x 값은 각 줄을 같은 가로 위치에서 시작하게 합니다. dy 값은 다음 줄을 아래로 이동합니다. 여기서는 의도적으로 HTML 자동 줄바꿈을 사용하지 않습니다. 작성자가 줄바꿈을 선택하고 맞는지 검증합니다. MDN은 tspan 배치를 설명하고, librsvg는 지원하는 SVG 요소를 정리하며 text와 tspan도 포함합니다.
이미지 변환기나 PDF 생성기 같은 실제 전달 경로로 두 파일을 여세요. 원본 미리보기뿐 아니라 저장된 결과를 비교하세요. 예제 크기와 같다고 다른 컴퓨터에서도 같은 글꼴이 보장되지는 않습니다.
브라우저에서도 레이블이 없을 때
파일을 만든 페이지만 보지 말고 직렬화된 .svg 파일을 확인하세요. HTML 안의 인라인 SVG와 독립 SVG 문서는 파싱 문맥이 다릅니다.
예제는 div를 http://www.w3.org/1999/xhtml에 명시적으로 넣습니다. MDN은 인라인 HTML 예제에서는 생략할 수 있어도 독립 SVG 문서의 HTML 콘텐츠에는 이 네임스페이스 선언이 필요하다고 설명합니다. JavaScript로 요소를 만들면 HTML 자식에 적합한 네임스페이스를 사용하세요. SVG 네임스페이스에서 만든 div는 HTML 문단 컨테이너가 아닙니다.
그런 다음 레이블의 다음 부분을 확인하세요.
foreignObject에 의도한 레이블 영역에 맞는 양수width와height를 명시하세요.- 모든 줄을 담을 공간을 확보하면서
x와y좌표를 보이는 그림 안에 두세요. - 컨테이너와 자식의
display,visibility, 불투명도와 글자 색을 확인하세요. - 주변 웹페이지 스타일시트에 의존하지 않고 내보낸 파일이 필요한 스타일을 포함하는지 확인하세요.
예제는 모든 레이블 스타일이 인라인이고 상자 너비가 230단위, 높이가 110단위입니다. 따라서 외부 CSS를 변수에서 제외합니다. 그렇다고 해당 기능이 없는 렌더러에서 foreignObject가 지원되지는 않습니다.
draw.io 내보내기는 소스에서 레이블 변환하기
편집 가능한 다이어그램이 남아 있다면 XML을 수동 편집하기 전에 그곳에서 레이블 내보내기를 수정하세요. 현재 draw.io 내보내기 문서는 지원되는 서식 레이블에 Convert Labels to SVG를 제공합니다. 도형이나 연결선을 선택하고 Text 탭의 Advanced 절을 열어 체크박스를 켜세요.
이 옵션에는 한계가 있습니다. 문서는 표, 목록, 링크나 배경색 같은 구조가 포함된 레이블을 이 변환에서 제외합니다. 옵션을 사용할 수 없다면 Formatted Text와 Word Wrap을 끄는 것도 문서에 설명된 방법입니다. 수동 줄바꿈을 넣고 레이아웃을 다시 확인해야 할 수 있습니다.
새 사본을 내보내고 실제 수신 애플리케이션에서 다시 여세요. ‘Text is not SVG’ 경고를 숨겨도 레이블이 변환되지는 않습니다. 글꼴 삽입은 글꼴 의존성을 해결하며 누락된 HTML 레이아웃 지원을 해결하지는 않습니다.
일러스트가 있는 다이어그램에서는 가져온 그림과 레이블을 별도로 유지하세요. draw.io 사용자 지정 SVG 도형 가이드는 그 작업 흐름의 그림 부분을 다룹니다.
다음 사용자를 고려해 텍스트 형식 선택하기
네이티브 텍스트는 수신자가 문구를 편집해야 할 때 유용한 해결책이지만 사용할 수 있는 글꼴이 여전히 필요합니다. 레이블 글꼴이 잘못 보이면 같은 컨테이너 누락 문제로 취급하지 말고 SVG 글꼴 검사를 따르세요.
| 전달 요구 | 실용적인 선택 | 확인할 사항 |
|---|---|---|
| 편집 가능한 문구 | 줄 위치를 의도적으로 정한 네이티브 text | 글꼴, 줄 길이와 수신 편집기 |
| 고정된 글자 모양 | 소스 편집기에서 최종 글자를 윤곽선화 | 올바른 모양. 편집 가능한 원본 보관 |
| 브라우저 전용 풍부한 레이아웃 | 해당 브라우저 방식이 요구를 충족하면 foreignObject 유지 | 실제 삽입 파일 또는 독립 파일 |
| 모양만 필요 | 전체 디자인을 표시하는 렌더러에서 PNG 내보내기 | 픽셀 크기와 전달 크기에서의 가장 작은 텍스트 |
윤곽선화는 소스 도구가 글자를 보고 변환할 수 있을 때만 작동합니다. 이미 불완전한 내보내기를 열고 남은 객체를 변환해도 가져온 문서에 없는 문구를 복원할 수는 없습니다. PNG는 픽셀을 보존하므로 편집 가능한 문구나 벡터 커팅 경로가 필요한 수신자에게는 적합하지 않습니다.
일러스트 카드에서 PerfectVector의 역할
카드의 일러스트가 PNG나 JPG로만 있다면 PerfectVector의 클립아트 SVG 변환 작업 흐름으로 해당 그림의 벡터 후보를 준비할 수 있습니다. 디자인 편집기에서 문구는 별도 텍스트 요소로 유지하세요. 일러스트 가장자리와 내부 틈을 확인하고 레이블을 추가한 뒤 완성 파일을 대상 렌더러에서 테스트하세요.
이미지 벡터화 가이드는 픽셀이 경로로 바뀌는 과정을 설명합니다. PerfectVector는 SVG의 HTML 레이블을 고치지 않습니다. 일러스트에 이미 좋은 경로가 있다면 유지하고 실패한 레이블만 바꾸세요. 누락된 레이블의 스크린샷에는 복원할 글자가 없으며, 보이는 글자를 추적해도 편집 가능한 문구가 아니라 모양이 만들어집니다.
수정한 SVG를 보내기 전
- 내보낸 사본을 브라우저와 실제 대상에서 다시 여세요.
- 마지막 줄까지 모든 레이블이 보이는지 확인하세요.
- 그림의 위치나 크기가 바뀌지 않았는지 확인하세요.
- 글꼴을 검증하거나 윤곽선화한 글자를 의도한 크기에서 확인하세요.
- 편집 가능한 소스를 전달 사본과 함께 보관하세요.
FAQ
SVG 텍스트가 Chrome에서는 보이지만 PNG로 내보내면 사라지는 이유는 무엇인가요? 레이블이 foreignObject 안의 HTML일 수 있으며 PNG 렌더러는 다른 SVG 하위 집합만 지원할 수 있습니다. 누락된 레이블 마크업을 확인하고 같은 내보내기 경로로 네이티브 텍스트 버전을 렌더링하세요.
XHTML 네임스페이스를 추가하면 모든 foreignObject 내보내기가 해결되나요? 아닙니다. 독립 SVG의 HTML 콘텐츠 네임스페이스를 고칩니다. 대상은 여전히 해당 콘텐츠를 지원해야 하고 레이블에도 적절한 크기와 보이는 스타일이 필요합니다.
tspan이 HTML 문단처럼 자동 줄바꿈을 할 수 있나요? 예제는 명시적인 줄과 세로 오프셋을 사용하며 HTML 문단 레이아웃을 재현하지 않습니다. 가용 공간에 맞게 줄바꿈을 고르고 대상 글꼴로 확인하세요.
레이블을 복원하려면 카드 전체를 벡터화해야 하나요? 기존 경로를 보존하고 원래 텍스트로 레이블을 다시 만드세요. 픽셀로만 있는 그림만 벡터화하세요. 추적한 글자는 도형이므로 편집 가능한 문구를 유지하지 않습니다.
Sources
- MDN — foreignObject — 다른 XML 네임스페이스의 콘텐츠, 위치·크기 속성과 독립 SVG의 XHTML 네임스페이스를 정의합니다.
- MDN — tspan — 네이티브 SVG 텍스트 부분의 배치를 설명합니다.
- draw.io — 내보낸 SVG 텍스트 문제 — 네이티브 레이블 변환, 서식 제한과 대체 내보내기 설정을 설명합니다.
- GNOME — Librsvg가 지원하는 SVG와 CSS 기능 — 렌더러가 지원하는 요소와 속성을 정리합니다.
일러스트가 아직 비트맵이라면 클립아트를 SVG로 준비하고 모양을 확인한 뒤 텍스트를 별도로 추가하세요. 전달하기 전에 내보낸 파일에서 둘 다 검증하세요.

