SVGO를 이용해 Sprite Svg 최적화하기

sumi-0011·2024년 10월 13일
2

지난 글에서 sprite SVG를 자동으로 생성하는 스크립트를 적어보았는데,
오늘은 그 스크립트를 한 단계 더 발전시켜, SVG를 최적화하고, 최적화한 SVG를 이용하여 sprite를 생성하는 방법에 대해 작성해보려고해요.

SVGO라는 라이브러리를 이용해서 SVG 파일을 최적화하고, 이를 sprite SVG 생성 과정에 통합해 보았어요.

SVGO를 이용한 SVG 최적화의 장점

SVG 최적화가 왜 필요할까요?
제가 생각한 이점은 아래와 같아요.

  1. 파일 크기 감소: 불필요한 데이터를 제거해서 파일 크기를 줄일 수 있어요. => 웹사이트의 로딩 속도 향상
  2. 코드 가독성 향상: 최적화 과정에서 SVG 코드가 정리되어 더 읽기 쉬워져요.
  3. 렌더링 성능 개선: 복잡한 경로를 단순화하면 브라우저가 SVG를 더 빠르게 렌더링할 수 있어요.

가장 큰 장점은 파일 크기 감소라고 생각해요.
sprite svg를 만들때 많은 svg를 사용하기 때문에 더욱 효과가 커질거라고 예상했어요.

SVG 최적화 및 Sprite SVG 생성 방법

SVGO란?

SVGO(SVG Optimizer)는 SVG 파일을 최적화하기 위한 Node.js 기반의 도구예요.
이 라이브러리는 아래와 같은 다양한 최적화 기법을 사용해 SVG 파일의 크기를 줄이고, 구조를 개선해줍니다.

  1. 불필요한 메타데이터 제거
  2. 중복된 요소 및 그룹 정리
  3. 경로 데이터 최적화
  4. 색상 값 정규화
  5. 기본값과 같은 속성 제거

SVGO는 플러그인 시스템을 통해 사용자가 원하는 대로 최적화 과정을 커스터마이징할 수 있어, 사용하기로 결정하였어요

1. SVGO 라이브러리 설치

npm install svgo

이 링크에서 자세한 내용을 확인할 수 있어요.

2. SVG 최적화 설정

제가 사용한 설정은 아래와 같아요.
혹시 이미지가 깨질 수 있을것 같아 간단한 설정만을 적용해보았아요.

const svgoConfig: SvgoConfig = {
  plugins: [
    {
      name: 'preset-default',
      params: {
        overrides: {
          removeViewBox: false,
          removeUselessStrokeAndFill: false,
          cleanupIds: false,
        },
      },
    },
    'removeXMLProcInst',
    'removeXMLNS',
    'removeDimensions',
    'minifyStyles',
    'removeComments',
    'removeHiddenElems',
    'removeEmptyAttrs',
    'removeEmptyText',
    'removeEmptyContainers',
    'collapseGroups',
    'removeMetadata',
    {
      name: 'convertPathData',
      params: {
        floatPrecision: 2,
      },
    },
  ],
};

이중에 알면 좋은 것들 몇개를 설명해보자면,,

  • removeViewBox: false: viewBox 속성을 유지해요. (SVG의 크기 조정에 중요!)
  • removeUselessStrokeAndFill: false: stroke와 fill 속성을 보존해요.
  • cleanupIds: false: ID 충돌을 방지하기 위해 ID를 그대로 유지해요.
  • convertPathData: 경로 데이터를 최적화하고, 소수점 정밀도를 2로 제한해요.

3. SVG 최적화 함수 생성

export const optimizeSvg = (svg: string): string => {
  const result = optimize(svg, svgoConfig);
  return result.data;
};

이 함수는 SVG 문자열을 받아서 최적화된 SVG 문자열을 반환하는 역할이예요.
다양한 곳에서 동일하게 사용하고 싶어 함수로 분리했어요.

4. 최적화된 SVG로 Sprite 생성

기존의 getSvgFiles 함수를 수정해서 SVG를 가져온 후 바로 최적화하도록 해볼게요.

const getSvgFiles = async (spriteInfo: SpriteInfoValue): Promise<SvgFile[]> => {
  const svgFiles = await Promise.all(
    spriteInfo.list.map(async (item) => {
      try {
        const res = await axios.get(`스프라이트 폴더 경로/${item}.svg`);
        // SVG를 가져온 후 바로 최적화해서 저장해요. 
        const optimizedSvg = optimizeSvg(res.data); 
        return {
          name: item,
          data: optimizedSvg,
        };
      } catch (error) {
        console.error(`❌ - Failed to fetch SVG for ${item}`);
        return null;
      }
    })
  );

  return svgFiles.filter((file) => file !== null) as SvgFile[];
};

마무리

이렇게 SVGO를 이용해 SVG를 최적화하고, 이를 sprite SVG 생성 과정에 통합해 보았어요. 최적화 과정을 추가했더니 생성된 sprite SVG의 크기가 눈에 띄게 줄어들더라고요. 특히 수백개의 국가 이미지를 다루는 프로젝트에서는 그 효과가 정말 크게 느껴졌어요.

실제로 최적화 전후의 sprite SVG 파일 크기를 비교해봤는데요,

위 스크린샷을 보시면 최적화 전후의 파일 크기 차이를 확실히 확인할 수 있어요
최적화 전 sprite SVG 파일의 크기가 538KB였는데, 최적화 후에는 252KB로 줄어들었어요. 반정도의 크기 감소를 이루어낸거죠! 🎉

이미지 하나의 용량을 줄여도 서비스의 성능을 크게 개선되는 것은 아니지만,
이런 작은 최적화 하나하나가 모여서 전체 프로젝트의 성능을 크게 향상시킬 수 있을거라고 생각해요. 👍

profile
안녕하세요 😚

0개의 댓글