Figma·Illustrator 에서 SVG 를 export 하면 보통 40-80 KB. 같은 그래픽 이 SVGO 한 번이면 5-10 KB. 차이의 거의 전부가 편집 도구의 메타데이터 다. 이 가이드는 편집 도구가 SVG 에 무엇을 박는지, 제거해도 안전한 것은 무엇인지, inline vs 외부 참조 선택, sprite 시트, 사용자 업로드 SVG 의 XSS 방어를 정리한다.
편집 도구가 박는 군더더기
전형적인 Figma export:
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<!-- Generator: figma -->
<metadata>
<rdf:RDF xmlns:rdf="...">...</rdf:RDF>
</metadata>
<defs>
<clipPath id="clip0_1_2">
<rect width="24" height="24" fill="white" transform="translate(0)" />
</clipPath>
</defs>
<g clip-path="url(#clip0_1_2)">
<path d="M12 2C6.48..." fill="#0F172A" />
</g>
</svg>제거 가능:
<metadata>,<sodipodi:*>,<inkscape:*>— 편집 도구 전용 네임스페이스.- XML 주석.
- 기본값 attribute —
fill="none",stroke-linecap="butt"등. - 빈
<defs>, 빈<g>. - 쓰이지 않는
clipPath,mask,filter. - path data 의 과한 정밀도 —
d="M 12.0000001 2.0000003"→M 12 2. id="clip0_1_2"같은 무의미한 자동 id.- XML 선언 (
<?xml ... ?>) — HTML 안 inline 할 때 불필요.
SVGO 한 줄 명령
npm i -D svgo
npx svgo icon.svg -o icon.optimized.svg
# 폴더 일괄
npx svgo -f icons/ -o icons-min/
# config 파일 (svgo.config.js)
module.exports = {
multipass: true,
plugins: [
"preset-default",
{name: "removeViewBox", active: false}, // viewBox 보존 (반응형 필수)
{name: "removeDimensions", active: true}, // width/height 제거 → CSS 자유
],
};브라우저에서 시각 확인하려면 SVGOMG (https://jakearchibald.github.io/svgomg/) — slider 로 각 옵션 영향 즉시 비교.
viewBox 유지, width/height 제거
편집 도구 export 는 보통 width="24" height="24" viewBox="0 0 24 24". 세 가지 모두 동일 정보. viewBox 만 두면 SVG 가 크기 무관 벡터 가 되어 CSS 로 자유롭게 resize.
<!-- 권장 -->
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="..." />
</svg>
<!-- CSS -->
.icon { width: 24px; height: 24px; }
.icon-large { width: 48px; height: 48px; }inline vs 외부 참조
Inline SVG — 권장 (작은 아이콘)
<button>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="..." />
</svg>
복사
</button>- 장점: HTTP 요청 0. CSS 로
currentColor색 변경 자동. JS 로 한 path 만 변경 가능. - 단점: 같은 아이콘 N 번 = HTML bytes N 번. gzip 이 잘 압축하지만 N=수십+면 의미.
외부 SVG — 큰 일러스트레이션
<img src="/hero.svg" alt="..." width="800" height="400" />
<!-- 또는 -->
<object data="/diagram.svg" type="image/svg+xml"></object>- 장점: 브라우저 캐시. 한 번 다운로드 → 사이트 전역 재사용.
- 단점:
img안 SVG 는 CSS / JS 로 내부 조작 X.
Data URI inline
SVG 를 base64 또는 URL-encoded data URI 로 inline. CSS background 안 주로 사용.
background-image: url("data:image/svg+xml,%3Csvg ... %3E");이미지 → Base64 (Data URI) 가 SVG 도 데이터 URI 로 변환. 단 SVG 는 base64 보다 URL-encoded 가 ~30% 작아 권장.
Sprite 시트 — 많은 아이콘
20+ 아이콘이 있고 inline 이 부담스러울 때. 모든 아이콘을 한 SVG 의 <symbol> 로 정의 → <use> 로 참조.
<!-- sprite.svg -->
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="i-search" viewBox="0 0 24 24">
<path d="..." />
</symbol>
<symbol id="i-trash" viewBox="0 0 24 24">
<path d="..." />
</symbol>
</svg>
<!-- 사용 -->
<svg class="icon"><use href="/sprite.svg#i-search" /></svg>
<svg class="icon"><use href="/sprite.svg#i-trash" /></svg>브라우저는 sprite.svg 를 한 번만 받음. fill: currentColor 로 색상 컨트롤. 외부 sprite cross-origin 일 때 CORS 필요.
색상·테마 — currentColor
하드코딩한 색을 currentColor 로 바꾸면 CSS color 속성으로 자동 추종.
<!-- before -->
<svg viewBox="0 0 24 24"><path d="..." fill="#0F172A" /></svg>
<!-- after -->
<svg viewBox="0 0 24 24"><path d="..." fill="currentColor" /></svg>
/* CSS */
.icon { color: var(--fg); }
.icon:hover { color: var(--accent); }
[data-mode="dark"] .icon { color: var(--fg-dark); }다크 모드·테마 시스템과 자연 어울림. lucide-react·heroicons 등 라이브 러리가 다 사용하는 패턴.
사용자 업로드 SVG — XSS 방어
SVG 는 HTML / JS 를 포함할 수 있는 위험 포맷. 사용자 업로드를 그대로 렌더하면 XSS.
<!-- 악의적 SVG 예 -->
<svg xmlns="http://www.w3.org/2000/svg">
<script>alert(1)</script>
<a href="javascript:alert(1)"><text>click</text></a>
<image href="x" onerror="alert(1)" />
</svg>방어책:
- inline 금지 —
<img src="upload.svg">으로 표시.<img>안 SVG 는 script 가 동작 X. - inline 이 꼭 필요하면 DOMPurify 같은 sanitizer (server 또는 client).
- uploaded SVG 는 별도 도메인 (예:
uploads.example.com) 에서 서빙 — cookie 도메인 분리. - CSP
script-src 'self'+object-src 'none'으로 fallback 방어.
아이콘 라이브러리 vs 직접
2026 년 표준 선택지:
- lucide-react — open source, tree-shake, 1500+ 아이콘. 가장 흔한 선택. 도구 당 ~1 KB.
- heroicons — Tailwind 팀. 200+ 아이콘. outline/solid 변형.
- radix-icons — 무게감 일관, 디자인 시스템 친화.
- tabler-icons — 4500+ 무료.
직접 만들 때는 viewBox 24×24 또는 16×16 통일, stroke width 일관 (1.5 또는 2), rounded join 통일. 디자인 시스템에 박힐 때 시각 일관성 ↑.
흔한 함정
1. removeViewBox 실수
SVGO 의 preset-default 가 기본으로 viewBox 제거. 반응형 SVG 깨짐. 항상 removeViewBox: false.
2. 정밀도 손실
SVGO 기본 정밀도 3. 아이콘에는 충분, 정밀 일러스트는 시각 변형. 필요 시 floatPrecision: 5.
3. fill="none" stroke="currentColor" 미적용
outline 아이콘은 fill 없이 stroke. solid 아이콘은 stroke 없이 fill. 한 컴포넌트에 두 스타일 섞으면 색상 컨트롤 깨짐.
4. JSX 안 dash → camelCase
React 에서 stroke-width → strokeWidth, clip-path → clipPath. SVG attribute 그대로 쓰면 warning.
5. aria-hidden 누락
의미가 텍스트로도 표현된 아이콘 (예: "복사" 버튼 옆 copy 아이콘) 은 aria-hidden="true". SR 가 중복 읽기 회피.
6. CSP 위반
inline SVG 안 style attribute 또는 <style> 태그가 style-src 'self' CSP 와 충돌. 외부 CSS 로 옮기거나 'unsafe-inline' 허용.
요약
- 편집 도구 export → SVGO 로 60-80% 감소.
viewBox유지,width/height제거 → CSS 자유.- 작은 아이콘 inline (현재 표준), 큰 일러스트는 외부 + 캐시. 20+ 아이콘 은 sprite.
fill="currentColor"로 테마 자동 추종.- 사용자 업로드 SVG 는
<img>로 표시 또는 DOMPurify sanitize. - 아이콘 라이브러리 (lucide-react 등) 가 직접 관리보다 cost-effective.