Base64 SVG가 표시되지 않을 때: 실무에서 바로 쓰는 해결 가이드
이 문제는 실제 프로젝트에서 정말 자주 발생합니다.
img src="data:image/svg+xml;base64,..."가 문법상 맞아 보여도 아무것도 렌더링되지 않습니다.- 같은 SVG 문자열이 한 곳에서는 동작하지만 CSS 배경에서는 깨집니다.
- 코드 리뷰에서는 놓치기 쉽지만, 디버깅 비용은 크게 듭니다.
익숙한 상황이라면 이 가이드가 재현 가능한 해결 경로를 제시해 줄 수 있습니다.
왜 디버깅이 어려운가
대부분 한 줄짜리 버그가 아닙니다. 보통은 여러 단계가 얽힌 문제입니다.
- SVG 원본 자체가 이미 잘못되어 있을 수 있습니다.
- 인코딩 방식이 사용하려는 대상 환경과 맞지 않을 수 있습니다.
- HTML, CSS, JSON은 서로 다른 이스케이프 규칙을 요구합니다.
- 보안 정리와 렌더링 규칙이 환경마다 다릅니다.
그래서 같은 SVG가 어떤 곳에서는 보이고, 다른 곳에서는 실패합니다.
가장 흔한 원인 우선순위
-
잘못된 MIME 접두사
data:image/svg+xml;base64,또는data:image/svg+xml,를 사용해야 합니다. -
잘못된 Base64 인코딩 흐름
SVG에 비 ASCII 문자가 포함되면 단순btoa(svg)는 깨질 수 있습니다. -
컨텍스트별 이스케이프 불일치
특히 CSS에서는#, 따옴표 같은 문자가 로딩을 깨뜨릴 수 있습니다. -
위험하거나 차단된 SVG 내용
스크립트, 이벤트 핸들러, 외부 참조는 제거되거나 차단될 수 있습니다. -
손상된 SVG 구조
viewBox누락, 잘못된 XML, 유효하지 않은 태그가 렌더링을 막을 수 있습니다.
SVGView에서 이 문제를 해결하는 방식
사용자에게 추측하게 두지 않고, 세 단계로 처리합니다.
1) 입력 레이어: import 전에 검증
src/lib/svg/import-handler.ts에서 다음을 수행합니다.
- 파일 타입과 크기 제한 적용 (최대 10MB)
<svg>루트가 있는지 XML 파싱 및 검증- 파싱 오류를 빠르게 반환
이 단계에서 잘못된 입력을 일찍 걸러냅니다.
2) 안전 레이어: 미리보기 전에 정리
src/lib/svg/sanitizer.ts에서 다음을 제거합니다.
<script>on*이벤트 핸들러 속성<foreignObject>- 외부 참조 (
href,xlink:href,src)
이렇게 하면 보안이 좋아지고 렌더링 불일치도 줄어듭니다.
3) 출력 레이어: Base64와 URL 인코딩 Data URI를 모두 제공
src/lib/svg/exporter.ts에서는 다음과 같이 처리합니다.
export function exportToDataUri(svg: string): string {
const encoded = btoa(unescape(encodeURIComponent(svg)));
return `data:image/svg+xml;base64,${encoded}`;
}
export function exportToDataUriEncoded(svg: string): string {
const encoded = encodeURIComponent(svg);
return `data:image/svg+xml,${encoded}`;
}
그래서 다음이 가능합니다.
- 호환성을 우선하면 Base64 선택
- 더 짧고 읽기 쉬운 문자열이 필요하면 URL 인코딩 선택
- 항상 올바른
image/svg+xmlMIME 타입 유지
어떤 인코딩을 선택해야 하나
- 대상 환경이 불확실할 때: 먼저 Base64를 선택합니다.
- 더 짧고 읽기 쉬운 문자열이 필요할 때: URL 인코딩을 선택합니다.
- CSS background에 쓸 때: 적절히 이스케이프한 URL 인코딩이 보통 더 안전합니다.
관련 도구:
재현 가능한 문제 해결 체크리스트
- 접두사 확인:
data:image/svg+xml;base64,또는data:image/svg+xml, - 유효한
<svg>루트와viewBox존재 여부 확인 - UTF-8 안전 인코딩 흐름 확인
- CSS/JSON 컨텍스트용 이스케이프 확인
- 내보내기 전 sanitization 수행
- Base64와 URL 인코딩을 번갈아 테스트해 빠르게 비교
FAQ
왜 <img>에서는 되는데 CSS에서는 실패하나요?
CSS 문자열 파싱은 더 엄격한 이스케이프 규칙을 요구합니다. 보통 URL 인코딩이 더 안전합니다.
image/svg+xml로 바꾸기만 하면 항상 해결되나요?
아닙니다. MIME 타입은 일부일 뿐입니다. 인코딩, 이스케이프, SVG 자체의 유효성도 모두 중요합니다.
Data URI가 외부 SVG 파일보다 항상 더 좋은가요?
아닙니다. 작은 인라인 자산에는 좋지만, 크거나 여러 번 재사용되는 자산은 외부 파일이 더 나을 때가 많습니다.
정리
"Base64 SVG가 표시되지 않는다"는 하나의 버그가 아니라 파이프라인 문제입니다.
검증 -> sanitization -> 이중 인코딩 -> 컨텍스트 매칭 흐름을 표준화하면, 문제를 훨씬 더 예측 가능하게 다룰 수 있습니다.