SVG Sprite로 네트워크 요청 절반 줄이기

JunSeok·2025년 3월 22일
0

지식 기록

목록 보기
15/16
post-thumbnail

기존 사용 방식 및 네트워크 요청

JSX에 SVG 파일을 직접 import해서 사용하면 편리하지만 JS 번들 크기 늘어나고 불필요한 네트워크 요청 증가한다.

import NotFoundIcon from '@/assets/icons/404_sign.svg';

<img src={NotFoundIcon} alt="NotFoundLogo" className="size-40" />

아래는 랜딩 페이지의 네트워크 탭인데, 네트워크 요청의 절반이 아이콘 요청이다.

SVG Sprite

Sprite는 그래픽 리소스를 한 파일 안에 모아서 필요한 부분만 뽑아 쓰는 기법을 가리킨다.
SVG Sprite 파일을 생성하면 SVG 파일을 한 파일에 모아서 필요한 부분만 뽑아서 사용할 수 있다.

이점

  • 아이콘 HTTP 요청 줄임으로써 페이지 로딩 시간 단축할 수 있다.
  • 새로운 아이콘 요소 쉽게 추가할 수 있다.
  • SVG sprite 파일을 따로 생성하기 때문에 JS 번들 크기 줄어든다.

생성 및 사용 방법

  1. <svg /> 태그를 <symbol /> 로 바꾼 svg 콘텐츠를 모아 하나의<svg />로 래핑한다.
  2. symbol 태그의 id로 아이콘을 구분한다.
  3. <svg />태그로 감싼 <use /> 태그의 href 속성에서 id를 사용하여 아이콘 사용한다.

이를 통해 아이콘이 아무리 많아도 스프라이트 파일 한 번만 요청하면 되고, 이후엔 <use />를 통해 각 아이콘을 재사용할 수 있어 성능과 관리 효율이 좋아진다.

자동화 작업

스크립트 작성

프로젝트에서 사용하는 SVG 파일들을 모아 단일 SVG Sprite로 결합하는 스크립트를 작성한다.

// generateSprite.ts
import fs from 'fs';
import { globSync } from 'glob';
import { HTMLElement, parse } from 'node-html-parser';
import path from 'path';

// 프로젝트 내에 있는 모든 SVG 파일 모은다.
const svgFiles = globSync('src/shared/assets/icons/*.svg');
const symbols: string[] = [];

// 각 SVG 파일을 읽고 svg 태그를 symbol 태그로 바꾸고 필요한 속성만 취한다.
svgFiles.forEach((file) => {
  const code = fs.readFileSync(file, 'utf-8');
  const svgElement = parse(code).querySelector('svg') as HTMLElement;
  const symbolElement = parse(`<symbol/>`).querySelector(
    'symbol'
  ) as HTMLElement;
  const fileName = path.basename(file, '.svg');

  svgElement.childNodes.forEach((child) => symbolElement.appendChild(child));

  symbolElement.setAttribute('id', fileName);
  if (svgElement.attributes.viewBox) {
    symbolElement.setAttribute('viewBox', svgElement.attributes.viewBox);
  }

  symbols.push(symbolElement.toString());
});

// 정적 폴더에 작성한다.
const svgSprite = `<svg>${symbols.join('')}</svg>`;
fs.writeFileSync('public/sprite.svg', svgSprite);

빌드 전에 스크립트 실행.

"scripts": {
    "dev": "vite",
    "generateSprite": "tsx generateSvgSprite.ts",
    "build": "npm run generateSprite && tsc -b && vite build",
  },

사용

추가적인 import 없이, 아이콘 컴포넌트를 생성해서 사용한다.

interface IconProps {
  name: string;
  style?: string;
  ariaLabel?: string;
}

export const Icon = ({ name, style, ariaLabel = name }: IconProps) => {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" className={style} aria-label={ariaLabel}>
      <use href={`/sprite.svg#${name}`} />
    </svg>
  );
}

<Icon name='404_sign' style='size-40' ariaLabel="NotFoundLogo" />

적용 이후

출처

아이콘으로 SVG 스프라이트를 만드는 방법
SVG Sprite 기법을 사용해 나만의 특별한 Icon 컴포넌트 개발

profile
최선을 다한다는 것은 할 수 있는 한 가장 핵심을 향한다는 것

0개의 댓글

관련 채용 정보