본문 바로가기
프론트엔드/Next.js

Next.js 페이지 성능 개선 - svg sprites 적용하기

by PARADISE247 2024. 3. 22.
반응형

기존에 내가 svg를 프로젝트 내에서 관리하던 방식은 다음과 같다. 

 

우선 프로젝트 내에서 나는 styled-components를 이용하여 스타일링을 적용하고 있었다.

각각 페이지나 큰 규모의 컴포넌트에 해당하는 스타일링 파일을 생성하고 모두 프로젝트 루트 밑에 styles/components 폴더 내에 

페이지 이름.js 라는 파일을 생성하여 관리했다. 

 

styles/componets
     |_ home.js
     |_ search.js
     |_ user.js

 

각각 스타일링 파일의 하단에 svg를 다음과 같이 정의해두었다.

styled-components의 스타일링 정의 파일의 하단에서 export 되는 svg

svg별로 이름을 지어주고 export하여 필요한 컴포넌트에서 import하는 방식을 사용 중이었다. 

 

그중 path 길이가 엄청 긴 svg들도 있었다. 스타일링 파일을 불러올 때마다 그 파일 내에 정의된 모든 svg까지 다 불러오는 것이 사이트 성능에도 좋지 않았던 것이다.

 

또한 이 방식은 파일의 번들 사이즈, 빌드 시 Load JS의 사이즈를 늘리는 데에 일조하였다. 

그리하여 나는 이러한 성능 저하 문제를 해결하고자 svg를 관리하는 파일을 따로 생성하는 svg sprites 방식을 채택하였다.

 

 

icon.jsx

// icon.jsx
const SvgIcon = ({ id, width, height, ...props }) => {
  return (
    <svg width={width} height={height} {...props}>
      <use href={`#${id}`} />
    </svg>
  );
};

export default SvgIcon;

icon.jsx를 생성하여 위와 같이 id, width, height를 인자로 받아오도록 하였다. 이 컴포넌트는 인자로 받아오는 id에 맞는 svg를 return해 줄 것이다. 

 

svg_sprites.jsx

const SvgSprites = () => {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" style={{ display: "none" }}>
      <symbol id="search-bar" viewBox="0 0 16 16" fill="none">
        <path
          d="M7.33333 12.6667C10.2789 12.6667 12.6667 10.2789 12.6667 7.33333C12.6667 4.38781 10.2789 2 7.33333 2C4.38781 2 2 4.38781 2 7.33333C2 10.2789 4.38781 12.6667 7.33333 12.6667Z"
          stroke="#F54A00"
          strokeWidth="1.5"
          strokeLinecap="round"
          strokeLinejoin="round"
        />
        <path
          d="M14.0016 14.0016L11.1016 11.1016"
          stroke="#F54A00"
          strokeWidth="1.5"
          strokeLinecap="round"
          strokeLinejoin="round"
        />
      </symbol>
      //... 생략
)}

그 후 svg_sprirtes.jsx를 생성하여 위와 같이 프로젝트 내에서 사용 중인 svg들을 각각 유니크한 아이디를 부여하여 정의 해준다. 

 

svg 불러오기

import SvgIcon from "../common/icon";
// ... 
<SvgIcon id="search-bar" width={16} height={16} />

svg를 불러올땐 위와 같이 icon.jsx로 만든 컴포넌트에 특정 아이디, width, height 를 인자로 보내주면 된다.

⭐️ 24.12.05 아래 _app.jsx 설명 추가되었습니다 🙋🏻‍♀️

이 후, svg를 특정 id로 전역에서 불러올 수 있게 _app.jsx에 다음과 같이 SvgSprites를 추가한다.

// _app.jsx
import SvgSprites from "@/components/common/svg_sprites";

function App({ Component, pageProps, token, refresh }) {
 // ... 생략
 
 <>
	<Head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      </Head>
     <GlobalStyle />
	 <SvgSprites />
      //...
 </>

}

 

적용 후

@next/bundle-analyzer를 이용해 파일의 번들 사이즈를 측정해보았을때 svg sprites 적용 후 다음과 같이 번들 사이즈가 대폭 감소한 것을 확인할 수 있다.

반응형