CairoSVG: SVG를 올바른 크기의 PDF와 PNG로 내보내기
CairoSVG로 SVG 아트워크를 변환하고 출력 너비나 배율을 선택하세요. DPI와 부모 치수를 이해하고 전달 전에 PNG 픽셀 수와 PDF 페이지 크기를 확인하세요.
목차
래스터로 내보낼 때는 cairosvg.svg2png(), PDF로 내보낼 때는 cairosvg.svg2pdf()를 사용하세요. 특정 PNG 너비가 필요하면 output_width를 설정하고, 비율을 유지하며 확대하려면 scale을 사용하세요. parent_width는 백분율 치수를 계산할 컨테이너를 지정합니다. dpi는 픽셀과 물리적 단위의 관계를 제어하므로 값을 바꾸면 PNG와 PDF 크기에 서로 다른 영향을 줄 수 있습니다.
아래 예제는 작은 SVG 엠블럼으로 시작해 각 설정으로 생성된 파일을 확인합니다. 로고 내보내기를 자동화하는 디자이너와 문서용 아트워크를 준비하는 개발자에게 적합합니다. CairoSVG는 기존 SVG 콘텐츠를 렌더링합니다. PNG 로고를 편집 가능한 경로로 추적하지는 않습니다.
외부 리소스에 의존하지 않는 SVG로 시작하기
이 예제는 Python 3.12.11과 CairoSVG 2.9.1로 실행했습니다. 프로젝트 환경에 버전을 고정한 변환기를 설치하세요.
python -m pip install "CairoSVG==2.9.1"CairoSVG에는 네이티브 Cairo 라이브러리도 필요합니다. 설치나 가져오기에 실패하면 설치 문서의 운영체제별 안내를 따르세요.
직접 작성한 이 세 경로 엠블럼을 emblem.svg로 저장하세요. 사각형 구멍은 채우기 규칙이 빠졌을 때 쉽게 알아볼 수 있게 하고, 좁은 막대는 작은 디테일을 확인할 지점이 됩니다. 이 아트워크는 직접 작성한 시연용이며 PerfectVector 변환 결과가 아닙니다.
<svg xmlns="http://www.w3.org/2000/svg"
width="240" height="120" viewBox="0 0 240 120">
<path fill="#176b63" fill-rule="evenodd"
d="M20 100 V20 H100 V100 Z M40 40 V80 H80 V40 Z"/>
<path fill="#e5a43a" d="M110 100 L160 20 L210 100 Z"/>
<path fill="#24435d" d="M220 20 H230 V100 H220 Z"/>
</svg>루트 치수는 출력 뷰포트를 나타냅니다. viewBox는 아트워크 내부의 좌표 사각형을 나타냅니다. 여기서는 둘 다 2:1 비율입니다. 예제를 자신의 로고에 맞게 수정할 때도 이 관계를 의도적으로 설정하세요.
하나의 마스터를 필요한 크기로 내보내기
SVG 옆에 이 코드를 export_emblem.py로 저장한 다음 python export_emblem.py를 실행하세요.
import cairosvg
cairosvg.svg2png(
url="emblem.svg",
write_to="emblem-480.png",
output_width=480,
)
cairosvg.svg2pdf(
url="emblem.svg",
write_to="emblem.pdf",
)PNG는 480 × 240 픽셀이었습니다. PDF 페이지는 180 × 90 포인트로, 2.5 × 1.25 인치에 해당했습니다. 이는 제공한 예제 파일에서 측정한 값이며 모든 SVG에서 기대할 수 있는 치수는 아닙니다.
이에 해당하는 명령줄 명령은 다음과 같습니다.
cairosvg emblem.svg --output-width 480 -o emblem-480.png
cairosvg emblem.svg -o emblem.pdfCairoSVG의 API 및 명령줄 참조는 url을 통한 입력 파일명, bytestring을 통한 SVG 바이트, write_to를 통한 파일 출력을 설명합니다. CLI에서는 출력 파일명의 확장자가 형식을 결정합니다.

문제에 맞는 제어 옵션 선택하기
이름이 비슷한 옵션도 서로 다른 문제를 해결합니다. CairoSVG 크기 참조는 부모 컨테이너와 요청한 출력 치수를 구분합니다.
| 요구사항 | Python 옵션 | CLI 옵션 | 확인할 사항 |
|---|---|---|---|
| PNG 너비를 정확히 480 픽셀로 만들기 | output_width=480 | --output-width 480 | 높이와 아트워크 비율 |
| 계산된 출력 치수를 두 배로 만들기 | scale=2 | --scale 2 | 두 치수가 모두 두 배가 되었는지 |
| 백분율로 표현된 루트 너비나 높이 계산하기 | parent_width, parent_height | --width, --height | 지정한 컨테이너의 백분율 |
| 인치 같은 물리적 단위 해석하기 | dpi | --dpi | PNG 픽셀 치수와 PDF 물리적 크기를 각각 확인 |
픽셀 치수를 사용하는 원본에 각 옵션을 따로 적용했습니다.
| 설정 | PNG 치수 | PDF 페이지 치수 |
|---|---|---|
| 기본값 | 240 × 120 px | 180 × 90 pt |
output_width=480 | 480 × 240 px | 360 × 180 pt |
scale=2 | 480 × 240 px | 360 × 180 pt |
dpi=192 | 240 × 120 px | 90 × 45 pt |
마지막 행이 주의할 부분입니다. DPI를 두 배로 높여도 픽셀 치수의 SVG에서 PNG 픽셀 수는 늘지 않았습니다. 같은 픽셀 치수가 PDF에서 더 작은 물리적 공간을 차지하게 되었습니다. 전달 요구사항이 픽셀 수라면 출력 치수를 지정하세요.
두 출력 치수를 모두 지정하면 캔버스 사각형이 설정됩니다. 그렇다고 로고가 그 상자를 빈틈없이 채우는 것은 아닙니다. SVG의 종횡비 규칙과 viewBox 내부의 빈 공간이 여전히 영향을 줍니다. 원래 비율을 유지하려면 출력 치수 하나만 먼저 지정하고 결과를 확인하세요.
백분율 치수에는 부모가 필요합니다
루트가 width="50%" height="50%"를 사용하는 예제 복사본에서 이 호출은 960 × 480 픽셀의 부모를 지정합니다.
cairosvg.svg2png(
url="emblem-percent.svg",
parent_width=960,
parent_height=480,
write_to="emblem-percent.png",
)출력은 480 × 240 픽셀로, 부모 너비와 높이 각각의 절반이었습니다. 이 때문에 parent_width=480과 output_width=480은 서로 바꿔 쓸 수 없습니다.
CairoSVG가 SVG 크기가 정의되지 않았다고 알리면 먼저 루트 치수를 확인하세요. 용도에 맞는 양수 치수를 문서에 지정하거나, 백분율 계산에 필요한 부모 치수를 제공하세요. 브라우저에서 아트워크가 표시되는 크기로 의도한 페이지 크기를 추정하지 마세요.
물리적 치수는 다르게 동작합니다
원본의 viewBox는 유지한 채 루트를 width="2.5in" height="1.25in"으로 바꾸세요. 테스트에서 dpi=96은 240 × 120 PNG를, dpi=192는 480 × 240 PNG를 생성했습니다. 두 PDF는 모두 180 × 90 포인트를 유지했습니다.
여기서는 원본이 물리적 크기를 정의하므로 인치당 픽셀 수를 늘리면 PDF의 물리적 페이지 크기는 유지하면서 래스터 해상도가 높아집니다. 같은 원리로 의도적으로 작성한 페이지에 밀리미터나 인치를 사용할 수 있습니다. 픽셀 수가 많다고 A4나 letter 페이지라고 가정하지 말고 내보낸 PDF의 페이지 상자를 확인하세요.
로고를 텍스트, 여백, 여러 요소가 있는 보고서 안에 배치해야 한다면 문서 레이아웃 단계를 사용하세요. ReportLab SVG 배치 가이드는 PDF를 직접 만드는 방법을, WeasyPrint 리소스 및 크기 확인은 HTML 문서를 다룹니다.
벡터로 유지된 부분까지 출력 확인하기
Pillow로 PNG 헤더를 읽고 pypdf 6.10.0으로 PDF 페이지 상자와 콘텐츠 스트림을 읽었습니다. 픽셀 치수 원본에서 만든 네 PDF에는 모두 경로 그리기 연산이 있었고 페이지 이미지는 0개였습니다. 이는 이미지가 없는 이 단순한 예제의 기하학적 요소가 벡터로 유지되었음을 확인해 줍니다. 임의의 SVG가 완벽하게 재현된다는 증거는 아닙니다.
자신의 출력 치수를 확인하려면 같은 환경에 pillow와 pypdf를 설치하고 실행하세요.
from PIL import Image
from pypdf import PdfReader
with Image.open("emblem-480.png") as image:
print("PNG pixels:", image.size)
page = PdfReader("emblem.pdf").pages[0]
print("PDF points:", float(page.mediabox.width),
float(page.mediabox.height))
print("Page images:", len(page.images))PageObject 참조는 mediabox와 images를 설명합니다. 이미지 수는 유용한 진단 정보지만 모든 도형, 글꼴, 효과가 정확하게 유지되었음을 입증하지는 못합니다.
전달 전에 다음을 확인하세요.
- PNG와 PDF를 열고 엠블럼을 SVG와 비교하세요. 구멍, 삼각형, 막대, 여백을 확인하세요.
- PNG의 픽셀 치수와 PDF의 물리적 치수를 각각 검증하세요.
- 좁은 틈과 작은 디테일을 포함해 실제 사용할 크기로 아트워크를 확인하세요.
- 원본 SVG를 보관하고 파일을 변경하거나 변환기를 업그레이드한 뒤에는 이 확인을 다시 실행하세요.
CairoSVG의 SVG 지원 페이지는 가능한 경우 벡터 출력을 유지한다고 설명합니다. 삽입된 래스터 이미지는 래스터 콘텐츠로 남습니다. 파일이 SVG로 감싼 PNG라면 내보내기 전에 삽입 이미지 진단으로 확인할 수 있습니다.
CairoSVG는 정적 렌더러입니다. 애니메이션, 스크립트, 고급 텍스트 레이아웃, 많은 필터는 지원하는 작업 범위 밖에 있습니다. 문서는 지원 필터로 feOffset, feBlend, feFlood만 나열합니다. 다른 효과에 의존하는 아트워크라면 결과를 꼼꼼히 비교하거나 해당 기능을 지원하는 애플리케이션에서 내보내세요. 변환 호출의 성공만으로는 충분하지 않습니다.
원본에 필요할 때만 벡터 마스터 복원하기
로고가 PNG나 JPG로만 남아 있다면 CairoSVG로 내보내기 전에 PerfectVector로 래스터를 SVG로 변환할 수 있습니다. 편집기에서 복원한 도형, 작은 구멍, 브랜드 글자를 확인한 다음 외부 리소스에 의존하지 않는 SVG 마스터를 저장하세요. 로고 벡터화 작업 흐름에서 이 검사를 설명합니다.
기존의 편집 가능한 SVG는 바로 내보내기 단계로 넘어갈 수 있습니다. PNG로 변환한 뒤 다시 추적하면 유용한 원본 기하학적 정보가 사라집니다. 사진이 의도한 콘텐츠라면 래스터 이미지로 유지해도 됩니다.
래스터 로고만 있다면 PerfectVector에서 자신의 이미지로 시도해 보세요. SVG의 윤곽과 구멍을 확인한 다음 CairoSVG 출력의 픽셀 치수와 물리적 페이지 크기를 모두 검증하세요.
FAQ
DPI를 바꿔도 PNG 크기가 그대로인 이유는 무엇인가요? SVG 루트가 픽셀 치수를 사용하면 DPI를 바꿔도 PNG 픽셀 수가 반드시 달라지는 것은 아닙니다. 이 예제의 240 × 120 픽셀 SVG는 192 DPI에서도 같은 크기를 유지했습니다. 출력 픽셀이 더 필요하면 output_width나 scale을 사용하세요.
부모 너비와 출력 너비는 같은가요? 아닙니다. parent_width는 백분율 치수를 계산할 컨테이너를 지정합니다. output_width는 최종 출력 너비를 요청합니다. 예제에서는 루트 너비가 50%이고 parent_width가 960이면 480 픽셀로 계산되었습니다.
CairoSVG는 항상 완전히 벡터인 PDF를 만드나요? 아닙니다. CairoSVG는 가능한 경우 벡터 출력을 유지하지만 SVG에는 래스터 이미지와 지원되지 않는 기능이 포함될 수 있습니다. 파일 확장자를 증거로 삼지 말고 PDF의 콘텐츠와 외관을 확인하세요.
Sources
- CairoSVG 문서 — 설치, 변환 API, 크기 제어 옵션, 렌더링 제한을 설명합니다.
- CairoSVG SVG 1.1 지원 — 벡터 유지, 삽입 이미지, 지원되지 않는 기능을 설명합니다.
- pypdf PageObject 참조 — PDF 검사에 사용한 페이지 상자와 이미지 인터페이스를 설명합니다.

