Data URI를 SVG로 되돌리는 안전한 방법
SVG Data URI는 작은 아이콘을 HTML이나 CSS에 넣을 때 편리합니다. 하지만 긴 data:image/svg+xml... 문자열만 남아 있고 편집 가능한 SVG가 필요하다면 조금 더 조심해야 합니다.
핵심은 첫 번째 쉼표를 기준으로 나누고, 뒤쪽 payload만 디코딩한 뒤 SVG로 검증하는 것입니다. 이 글은 Stack Overflow의 실용적인 논의 Converting a data URI back to SVG를 참고했습니다.
형식 확인하기
data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...
data:image/svg+xml,%3Csvg%20xmlns%3D%22http...
쉼표 앞은 MIME type과 encoding 정보이고, 쉼표 뒤가 실제 SVG payload입니다.
Base64 디코딩
function dataUriBase64ToSvg(dataUri) {
const [, payload] = dataUri.split(",", 2);
if (!payload) {
throw new Error("Invalid SVG Data URI");
}
return new TextDecoder().decode(
Uint8Array.from(atob(payload), (char) => char.charCodeAt(0)),
);
}
TextDecoder를 쓰면 UTF-8 텍스트, 기호, 메타데이터를 더 안전하게 보존할 수 있습니다.
URL 인코딩 디코딩
function dataUriEncodedToSvg(dataUri) {
const [, payload] = dataUri.split(",", 2);
if (!payload) {
throw new Error("Invalid SVG Data URI");
}
return decodeURIComponent(payload);
}
이 형식은 CSS background에서 자주 보이며, 단순한 아이콘에서는 Base64보다 짧고 읽기 쉬울 수 있습니다.
범용 디코더
function dataUriToSvg(dataUri) {
const [header, payload] = dataUri.split(",", 2);
if (!header?.startsWith("data:image/svg+xml") || !payload) {
throw new Error("Expected an SVG Data URI");
}
if (header.includes(";base64")) {
return new TextDecoder().decode(
Uint8Array.from(atob(payload), (char) => char.charCodeAt(0)),
);
}
return decodeURIComponent(payload);
}
디코딩 후에는 <svg> 루트가 있는지, XML로 파싱되는지 확인해야 합니다.
모범 사례
- 복원된 XML을 검증합니다.
- script, event handler, 외부 참조,
foreignObject를 제거합니다. viewBox, 크기, clipping을 확인합니다.- SVG Viewer에서 결과를 미리 봅니다.
- 필요하면 SVG to Data URI로 다시 내보냅니다.
흔한 실수
- Data URI 전체를 디코딩하는 것.
- URL 인코딩된 SVG를 Base64로 처리하는 것.
- 신뢰할 수 없는 SVG를 정리하지 않고 재사용하는 것.
- CSS, HTML, JSON의 escaping 차이를 무시하는 것.
SVGView 워크플로
Data URI를 디코딩하고, SVG Viewer에 붙여 넣고, SVG Sanitizer로 정리한 뒤, SVG Optimizer로 줄이고, SVG to Data URI로 새 문자열을 생성하세요.