웹 디자인과 프론트엔드 개발 환경에서 벡터(Vector) 그래픽 포맷인 **SVG(Scalable Vector Graphics)**는 해상도에 구애받지 않고 선명한 아이콘과 일러스트를 표현하는 표준 포맷으로 자리 잡았습니다. 하지만 모바일 앱이나 소셜 미디어 플랫폼, 프레젠테이션 문서 등 슬라이드 시스템에서는 SVG를 직접 지원하지 않는 경우가 많아, 여전히 범용성이 높은 **PNG(Portable Network Graphics)**나 JPG 같은 래스터(Raster, 비트맵) 포맷으로 변환해야 하는 상황이 빈번히 발생합니다.
단순히 파일 확장자만 바꾼다고 변환이 끝나는 것은 아닙니다. 특히 웹 브라우저 환경에서 자바스크립트와 HTML5 캔버스(Canvas) API를 이용해 클라이언트 단독으로 SVG를 PNG로 변환하려고 할 때, 보안 정책에 의해 렌더링이 차단되거나 투명 배경이 검은색으로 깨지고, 글꼴이 유실되는 등 까다로운 이슈들을 마주하게 됩니다. 이번 글에서는 SVG와 PNG의 수학적 렌더링 차이를 살펴보고, 실무 개발에서 악명 높은 캔버스 오염(Canvas CORS Taint) 이슈의 발생 원인과 확실한 우회 해결책을 상세히 정리해 드립니다.
1. 벡터(SVG) vs 래스터(PNG) 그래픽 표준 비교
두 형식은 이미지를 화면에 렌더링하고 메모리에 저장하는 방식에서 근본적인 차이가 존재합니다.
수학적 정의의 차이
- SVG (Vector): 수학적 함수와 좌표계(XML 포맷)를 이용해 선, 원, 다각형 및 베지에 곡선(Bézier Curve)을 기술합니다. 이미지를 아무리 확대하거나 축소해도 수학적 계산을 통해 실시간으로 다시 그리기 때문에 **해상도 무관성(Resolution Independence)**을 가집니다.
- PNG (Raster): 픽셀(Pixel)이라는 2차원 바둑판 눈금 격자에 각각의 색상 정보를 매핑하여 저장합니다. 특정 해상도에 종속되어 있어, 이미지를 원래 크기보다 크게 확대하면 픽셀이 뭉개지고 계단 현상(Aliasing)이 생기는 열화가 발생합니다. 대신 복잡하고 불규칙한 색상이 섞인 실제 사진 데이터를 표현하는 데 유리합니다.
두 포맷의 세부적인 특징과 차이점을 분석하면 다음과 같습니다.
| 비교 항목 | SVG (Scalable Vector Graphics) | PNG (Portable Network Graphics) |
|---|---|---|
| 기본 형식 | XML 기반 텍스트 (텍스트 에디터로 수정 가능) | 바이너리(이진) 바이트 스트림 데이터 |
| 작동 원리 | 수학적 좌표, 패스(Path), 벡터 방정식 렌더링 | 2차원 픽셀 격자 그리드 색상 매핑 |
| 압축 알고리즘 | Gzip/Brotli 등으로 문서 압축 가능 | 무손실 Deflate 압축 (DEFLATE 기반) |
| 해상도 특성 | 무한 확대 가능 (깨짐이나 화질 저하 없음) | 확대 시 픽셀 깨짐 및 블러/계단 현상 발생 |
| 주요 용도 | 아이콘, 로고, 다이어그램, 반응형 그래픽 | 실제 사진, 투명 채널이 필요한 고화질 웹 이미지 |
| 용량 특성 | 오브젝트 개수가 적을수록 가볍고 가독성 좋음 | 해상도와 색상 복잡도에 비례해 용량이 증가함 |
2. 브라우저 캔버스의 복병: CORS Taint (오염) 현상 분석
브라우저 내 자바스크립트를 이용해 클라이언트 측에서 SVG를 PNG로 변환하는 가장 대중적인 방법은 다음과 같습니다.
- SVG 문자열을 XMLSerializer나 Blob 객체로 변환하여 임시
Image객체의 소스(src)로 할당합니다. canvas.getContext('2d')객체의drawImage()메소드로 이미지 객체를 캔버스 프레임에 그립니다.canvas.toDataURL('image/png')를 실행하여 래스터 데이터(Base64)를 추출합니다.
하지만 이때 SVG 내부에 외부 도메인에 있는 폰트 파일이나 이미지 파일(xlink:href 또는 <image> 태그)이 주입되어 있다면, 브라우저는 보안상의 이유로 "Tainted Canvas" (오염된 캔버스) 경고를 뱉으며 toDataURL 호출을 즉시 차단합니다. 이는 타사 사이트의 중요 이미지를 자바스크립트로 가로채는 위사의 보안 취약점(Cross-Origin 정보 유출)을 막기 위한 브라우저의 기본 보안 정책입니다.
결정적 오작동의 주범: 속성 선언 순서 오류
CORS 정책이 올바르게 설정되어 있어도 자바스크립트 개발 시 속성을 선언하는 코드의 순서를 잘못 기입하면 캔버스 오염이 무조건 발생합니다.
// [오류 발생 케이스] src가 crossOrigin보다 먼저 정의된 경우
const img = new Image();
img.src = "https://external-domain.com/image.png";
img.crossOrigin = "anonymous"; // 무시되거나 CORS 에러 유발
// [정상 작동 케이스] crossOrigin을 먼저 정의한 뒤 src를 지정
const img = new Image();
img.crossOrigin = "anonymous";
img.src = "https://external-domain.com/image.png"; // 정상적으로 CORS 요청 전송
브라우저는 img.src가 입력되는 즉시 데이터를 메모리 및 캐시에 로드하기 시작합니다. 만약 crossOrigin = "anonymous" 속성이 지정되지 않은 채 src가 먼저 주입되면, 브라우저는 CORS 헤더가 필요 없는 일반 이미지 요청으로 판단해 캐시에 저장합니다. 그 후 코드 밑에서 부랴부랴 crossOrigin 속성을 지정해도 브라우저는 이미 CORS 권한 없이 받아온 캐시 데이터를 불러와 사용하므로, 캔버스는 복구 불가능하게 오염(Tainted) 처리됩니다. 따라서 반드시 crossOrigin 속성을 먼저 설정하고 src 주입을 나중에 수행하는 규칙을 철저히 지켜야 합니다.
3. 웹 캔버스 기반 무손실 변환 가이드 및 실무 팁
캔버스 오염을 방지하고 SVG를 완벽하게 PNG로 출력하기 위한 핵심 코딩 및 레이아웃 절차입니다.
① SVG 인라인 리소스 임베딩 작업
외부 폰트나 스타일시트를 사용 중이라면 링크 태그를 그대로 유지하기보다 SVG 내부에 <style> 태그를 열어 웹폰트(@import 또는 @font-face)나 CSS 코드를 텍스트로 직접 주입해 주는 편이 안전합니다. 또한 SVG 내 <image> 태그의 외부 소스는 미리 Base64 형태의 Data URL로 변환하여 XML 구조 안에 단일 데이터로 완전히 매포해 주는 것이 CORS 규약을 원천 차단하는 가장 깔끔한 방법입니다.
② 고해상도 출력을 위한 DPI 스케일링 설정
캔버스는 기본적으로 디바이스 픽셀 비율(window.devicePixelRatio)에 영향을 받습니다. 기본 크기로 그냥 드로잉하면 디나 비티나 등 고해상도 디스플레이(Retina 등)에서 글씨나 선이 뿌옇게 흐려지는 블러 현상이 나타납니다.
이를 예방하기 위해 아래와 같이 캔버스의 버퍼 해상도(width, height)를 실제 화면 표시 물리 픽셀 크기에 맞춰 2~3배 스케일링한 후 변환 작업을 돌려야 선명한 고품질의 PNG 결과물을 얻을 수 있습니다.
const scale = window.devicePixelRatio || 1;
canvas.width = svgWidth * scale;
canvas.height = svgHeight * scale;
ctx.scale(scale, scale); // 캔버스 좌표 공간 비율을 매칭
ctx.drawImage(img, 0, 0);
4. SVG to PNG 변환에 대한 자주 묻는 질문 (FAQ)
Q1. 변환된 PNG의 투명 배경이 검은색으로 채워지는 이유는 무엇인가요?
A1. SVG는 기본적으로 배경색 정보가 없으면 투명하게 처리됩니다. 하지만 이를 캔버스에 투명 배경으로 복사한 후 파일로 변환할 때, 투명(Alpha) 채널을 지원하지 않는 JPG 파일로 저장하거나 캔버스 드로잉 단계에서 픽셀 초기화를 수행하지 않으면 알파 값이 0인 영역이 시스템 기본값인 검은색으로 강제 렌더링될 수 있습니다. PNG 형식은 알파 투명도를 지원하므로 드로잉 전에 반드시 ctx.clearRect(0, 0, canvas.width, canvas.height)를 통해 도화지를 깨끗하게 비운 상태에서 드로잉하거나 배경으로 투명 흰색 등을 명시적으로 칠해준 후 PNG 변환을 시도해야 합니다.
Q2. 웹 브라우저 캔버스를 거치지 않고 Node.js 서버 환경에서 변환할 때도 CORS 문제가 생기나요?
A2. 아니오, 서버 사이드 환경에서는 동일 출처 정책(SOP)이나 CORS 규약을 강제하는 주체가 브라우저 엔진이 아니므로 Taint 오류가 나지 않습니다. Node.js 환경에서는 Sharp나 Canvas 라이브러리를 사용해 자유롭게 SVG 소스를 로드하고 내부 및 외부 연동 이미지를 불러와 안정적으로 무손실 변환을 마칠 수 있습니다.
Q3. SVG 내부에 내장된 텍스트 폰트가 PNG 변환 후 기본 시스템 폰트(굴림 등)로 깨져서 나옵니다.
A3. SVG 내부 <text> 요소가 사용하는 서체가 사용자 컴퓨터나 렌더링 환경에 사전 설치되어 있지 않거나, 임포트 주소가 유실되면 발생합니다. 이를 확실하게 막고 싶다면 텍스트 경로를 실선 오브젝트로 전부 깨부수어 기하학 패스로 변환하는 Convert to Outlines 가공 과정을 어도비 일러스트레이터나 피그마 등에서 거친 후 SVG 파일을 내보내면 어떤 환경에서나 폰트 깨짐 없이 완전히 동일한 기하 형상을 유지한 채 PNG로 변환할 수 있습니다.
5. 브라우저에서 안전하게 SVG를 PNG로 즉시 변환하기
외부 서버에 디자인 소스 코드가 유출되거나 라이선스가 있는 민감한 벡터 이미지가 업로드되어 외부에 박제될까 걱정이시라면, 100% 로컬 자바스크립트 샌드박스 내부에서 안전하게 변환을 도와주는 저희 SVG PNG 변환기 도구를 실행해 보시기 바랍니다.
통신 지연이나 유출 위협 없이 디바이스 내부 가상 캔버스를 활용해 무손실 PNG 추출이 완료됩니다. 아울러 웹 로딩 효율을 극한으로 끌어올리고자 하신다면 변환 후 파일 부피를 더 줄여주는 이미지 압축기 실무 가이드나, 반응형 디자인 퍼블리싱 레이아웃 규격 확인을 위한 소셜 미디어 이미지 리사이저 분석 칼럼을 함께 참고해 보세요.
관련 분야 추천 블로그 칼럼 목록
- 무손실 이미지 압축 알고리즘과 PNG/WebP 최적화 가이드: 데이터 압축 이론으로 알아본 고효율 에셋 서빙 요령
- 소셜 미디어 규격별 반응형 이미지 리사이징 전략: 인스타그램부터 유튜브까지 해상도 레이아웃 일관성 유지 팁



