React에서 폰트 아이콘 대신 SVG 시스템 구축
폰트 아이콘의 한계를 보완하고 로딩 비용과 접근성 문제를 해결하는 React 환경에서의 SVG 기반 아이콘 시스템 설계와 구현 방법론
목차
개요
많은 프로젝트가 아직 폰트 아이콘을 사용한다. 그러나 폰트 아이콘은 렌더링, 스케일링, 접근성 측면에서 제약이 있다. React 앱에서는 SVG를 활용한 아이콘 시스템이 더 나은 선택이 된다. 이 글에서는 react svg 아이콘 시스템을 설계하고, svg sprite react 방식과 컴포넌트 기반 접근을 비교하며, 아이콘 성능 최적화 리액트 관점에서 구현 방법을 살펴본다.
왜 SVG 아이콘인가?
성능과 품질
SVG는 벡터 기반이라 해상도에 관계없이 선명하다. 필요할 때만 로드하고 캐시하면 네트워크 비용을 줄일 수 있다. 또한 CSS로 색상과 크기를 제어하기 쉬워 재사용성이 높다.
접근성과 제어
SVG는 aria 속성, title 요소 등으로 접근성 향상이 가능하다. 개별 아이콘에 의미를 부여하거나 장식용으로 숨기는 처리가 명확하다.
설계 전략
SVG 아이콘 시스템은 주로 세 가지 방식으로 나뉜다.
- SVG 스프라이트(심볼) + <use> 호출
- 인라인 SVG를 컴포넌트로 사용 (React 컴포넌트)
- 외부 파일을 동적으로 가져와 삽입
각 방식은 트레이드오프가 있다. 스프라이트는 네트워크 요청 최소화와 캐시 이점이 크다. 인라인 컴포넌트는 트리쉐이킹과 스타일 제어가 용이하다.
SVG 스프라이트 사용하기
스프라이트는 여러 <symbol>을 하나의 파일로 묶어 사용한다. 브라우저는 한 번만 로드하면 된다. React에서 보편적으로 쓰이는 패턴은 애플리케이션 초기 단계에 스프라이트를 DOM에 주입하는 것이다.
스프라이트 주입 예시
function useSprite(url) {\n React.useEffect(() => {\n if (!document.getElementById('svg-sprite')) {\n fetch(url)\n .then(res => res.text())\n .then(svg => {\n const div = document.createElement('div');\n div.id = 'svg-sprite';\n div.style.display = 'none';\n div.innerHTML = svg;\n document.body.insertBefore(div, document.body.firstChild);\n });\n }\n }, [url]);\n}\n\n// 사용 예: useSprite('/assets/icons/sprite.svg');
위 코드는 애플리케이션이 마운트될 때 스프라이트를 한 번만 주입한다. 별도 빌드 파이프라인에서 sprite.svg를 생성하면 된다.
React 아이콘 컴포넌트
스프라이트에 포함된 심볼을 참조하는 Icon 컴포넌트를 만든다. 접근성 속성을 기본으로 제공하면 재사용성이 높아진다.
Icon 컴포넌트 예시
const Icon = ({ name, size = 16, title, decorative = false, className = '' }) => {\n const ariaHidden = decorative ? true : undefined;\n const ariaLabel = decorative ? undefined : title || name;\n\n return (\n <svg className={className} width={size} height={size} aria-hidden={ariaHidden} aria-label={ariaLabel} role={decorative ? 'img' : 'img'} focusable="false">\n <use xlink:href={`/assets/icons/sprite.svg#${name}`} />\n </svg>\n );\n};
JSX 내 <use>의 xlink:href는 빌드 설정이나 배포 경로에 따라 상대경로로 조정한다. 서버에서 캐시 헤더를 잘 설정하면 재요청이 줄어든다.
인라인 SVG 컴포넌트 대안
아이콘을 개별 React 컴포넌트로 변환하면 트리쉐이킹으로 사용하지 않는 아이콘을 제거할 수 있다. 각 파일을 svgr로 변환하면 props로 색상과 크기를 쉽게 제어할 수 있다. 다만 여러 인스턴스가 많으면 DOM 크기가 커질 수 있다.
성능 최적화 포인트
- 스프라이트는 한 번만 로드해 캐시 이득을 본다.
- Icon 컴포넌트는 React.memo로 감싸 불필요한 재렌더링을 줄인다.
- width/height 대신 viewBox로 크기 조절을 통일한다.
- CSS로 색상 제어 시 currentColor를 사용해 재사용성을 높인다.
- 필요 시 서버에서 gzip 또는 brotli 압축을 적용한다.
마이그레이션 전략
기존 폰트 아이콘에서 전환할 때는 단계적으로 진행한다. 우선 핵심 컴포넌트에만 SVG를 적용한다. 이후 런타임에 폰트 의존 코드를 제거하고 스프라이트로 교체한다. 자동화 스크립트로 아이콘 이름을 표준화하면 수작업을 줄일 수 있다.
결론
React 앱에서는 react svg 아이콘 시스템이 유지보수와 성능 측면에서 유리하다. 프로젝트 규모와 팀 워크플로우에 따라 svg sprite react 방식과 인라인 컴포넌트 중 적합한 방법을 선택하면 된다. 또한 아이콘 성능 최적화 리액트를 고려해 캐시, 압축, 재렌더링 방지 같은 세부 전략을 적용하면 실사용 성능 개선 효과를 얻을 수 있다.