Icon 활용 방식 개선하기 ( w. svg-sprite )

박상우·5일 전
2
post-thumbnail

최근 두 개의 프로젝트를 병행하고 있다. 항상 프로젝트를 하면 icon을 많이 활용하게 된다.

앞서 시작한 프로젝트에서 icon을 관리하고 호출하는 방식을 이후 시작한 프로젝트에 적용해보면서 더 나은 방식이 있을 것이라는 생각이 들어 개선 과정을 정리하게 되었다.

이전 프로젝트에서는 어떻게 사용하고 있나.

우선 모든 svg 아이콘을 개별 컴포넌트( 또는 svg 파일 )로 관리하고 있다.

그리고 icon 컴포넌트 리스트를 통해 어떤 활용할 수 있는 이미지들을 관리하고, 활용하는 컴포넌트 또는 페이지에서 Icon 컴포넌트를 호출하고 컴포넌트 이름을 props로 넘겨주어, Icon 컴포넌트 내부에서 해당 Icon을 특정하여 활용하고 있다.

이 방식은 다른 프로젝트에서도 비슷하게 활용하고 있어 크게 어색한 방식이라는 생각이 들진 않았지만, 초기 세팅과정에 번거로움 있고, 아이콘을 등록하는 과정에서 2 ~ 3개의 파일을 거쳐야한다는 점이 불편하게 느껴졌다.

그래서 개선할 수 있는 방법을 찾다가 svg sprite이라는 기법을 발견하게 되었다.


svg sprite?

svg sprite은 여러 개의 svg 파일을 하나의 svg 파일로 합쳐서 관리하고 <use> 태그를 통해서 특정 아이콘만 활용하는 방식을 말한다.

svg sprite를 활용하면 우선 파일 크기를 줄일 수 있고, 기존의 각각 icon 파일을 요청하는 방식에 비해 1개의 파일만 요청하여 활용하기 때문에 네트워크 부하가 줄어들며, 뿐만 아니라 다운로드 받은 1개의 파일에 대해서 브라우저 캐싱이 가능하기 때문에 더 빠르게 로딩이 가능하다.


사용해보자

방법은 간단하다. 모든 svg 파일에 있는 태그 정보를 우선 하나의 svg 파일로 모은다. 그리고 각 svg 파일에 해당하는 부분을 태그로 구분한다.

그리고 이후 컴포넌트에서 사용할 아이콘을 지정하기 위해 각 symbol 태그의 id 속성에 icon의 이름을 지정해둔다.

svg-sprite 코드 설명

  • <defs> 태그 : svg 내부에서 재사용할 요소들을 그룹화 하는 컨테이너 역할
  • <symbol> 태그 : 재사용할 그래픽 요소 (svg Icon)를 구분/정의하는 역할, 이때 <symbol> 태그 내부에 있는 요소들은 랜더링 되지 않고, 이후 <use> 태그를 통해 사용해야 한다.

그 다음 svg-sprite 기법으로 만든 하나의 파일을 통해 icon을 랜더링할 Icon 컴포넌트를 만든다 ( React / Next.js 기준 )

interface IconProps {
  id: string;
  size?: 'md' | 'lg';
  className?: string;
}

const sizeValue = {
  md: 20,
  lg: 24,
};

const Icon = ({ id, size = 'lg', className }: IconProps) => {
  return (
    <svg
      width={sizeValue[size]}
      height={sizeValue[size]}
      className={className}
      fill='none'
    >
      <use href={`/images/svg-sprite.svg#${id}`} />
    </svg>
  );
};

export default Icon;

컴포넌트 내부에서 태그를 통해서 원하는 Icon 컴포넌트를 지정하여 랜더링 할 수 있다.

<use> 태그 내 href 속성에 {svg sprite 파일 경로 }#{ svg icon id } 값을 넘겨주어 Icon을 특정할 수 있다.


사용해보니…

일단 눈에 띄게 개선되었다라고 느껴진 부분은 프로젝트 폴더 내 icon 파일들이 사라졌다는 점과 새로운 아이콘을 등록할 때 svg-sprite.svg 파일만 수정하면 된다는 점이었다.

그리고 모든 icon을 프로젝트 디렉토리에서 관리하는 방식과 svg-sprite.svg 단일로 관리하는 방식의 물리적인 용량 차이를 비교해봤을 때도 생각보다 큰 차이가 느껴졌다.

초기 단계라 11개의 아이콘만 관리하고 있음에도, 8KB → 2KB로 6KB( 약 75% ) 정도 용량 차이가 있었다. 더 많은 파일을 관리하게 되면 그만큼 더 큰 개선이 이루어질 것이라고 생각되어 개선 방향이 긍정적이지 않았나 하는 생각이 들었다.


svg-sprite는 무적?

모든 기술에는 장단점이 있듯 svg-sprite를 활용하는 것에도 한계가 있을 수 있다.

먼저, svg-sprite는 모든 아이콘을 불러온다.

앞서 모든 Icon을 개별 파일로 저장하는 경우, 총 용량이 더 클 수는 있지만 Icon을 활용할 떄 마다 불러오기 때문에 Icon 활용을 적게 하는 경우에서는 svg-sprite를 활용하는 것이 더 많은 리소스를 사용하게 될 수 도 있다.

오히려 복잡한 관리 방식

svg-sprite 방식을 활용하면 단일 파일로 모든 이미지 정보를 관리하고, svg 파일 내부 코드들은 벡터 기반 그래픽들의 정보들이라 읽기가 힘들어 많은 아이콘들을 관리하게 되면 그만큼 파일 내부가 복잡해지기 때문에 오히려 여러 개의 파일로 관리하는 것보다 관리가 어려울 수 있다.


이외에도 여러 단점이 있을 수 있지만, 현재 진행하고 있는 우리 프로젝트에서는 svg-sprite를 활용하는 것이 더 나은 선택이라고 생각했다.

사이드 프로젝트 규모에서 활용하는 Icon 개수가 그렇게 많지 않고, MVP 기준으로 최소 기능을 구현하기 때문에 대부분의 Icon을 활용하게 되어 적은 용량으로 관리하는 것이 더 나은 방식인 것 같다.

아마 규모가 더 커지거나, 이후 실무에서 이런 방식을 적용하는 경우에는 부분적으로 주요한 비즈니스 로직에 있는 icon 들만 최적화 한다거나, 트래픽을 통해 자주 방문하는 페이지의 icon들에 대해서만 svg-sprite를 활용한다면 svg-sprite의 장점을 더욱 극대화 시킬 수 있지 않을까 생각한다.


Reference

https://velog.io/@sasha1107/SVG-스프라이트-기법으로-사이트-성능-향상시키기리액트에서-스프라이트-SVG-사용하기

https://velog.io/@sumi-0011/react-icon-manage

https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use

https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol

profile
나도 잘하고 싶다..!

0개의 댓글

관련 채용 정보