본문 바로가기

개발

SVG 어디까지 써봤니?

웹에서 이미지를 표현하는 방식에는 크게 두 가지로 볼 수 있는데,
하나는 jpg, png와 같은 비트맵 방식이고, 다른 하나는 벡터 이미지인 svg이다.

 

SVG는 Scalable Vector Graphics로 경로(path)와 점(point) 같은 요소를 XML로 표현한 벡터 방식의 이미지로 크기를 늘리거나 줄이는 것에 열화가 되지 않아 icon이나 brand logo를 넣는 것에 많이 사용하게 되고, 그래프를 그리는 경우에도 svg를 활용하여 그릴 수도 있다.

 

 

우리를 고통스럽게 하는 건 위와 같은 경우가 있기 때문이다. 

svg의 스펙은 W3C에서 관리하는 스펙에 따라 관리되고 있지만, 이를 웹에 노출하는 방식에는 많은 선택지들이 존재하게 된다.

 

# XML

<svg width="258" height="340" viewBox="0 0 258 340" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M128.6 62.8306C57.6 62.7306 0.1 120.231 0 191.131C0 219.831 9.6 247.731 27.3 270.431C28.6 272.031 29.9 273.731 31.3 275.331C33.3 277.731 35.4 280.031 37.6 282.231L37.8 282.431C62.6 308.931 94 328.431 128.7 339.031C163.4 328.431 194.8 308.931 219.6 282.431L219.8 282.231C222 280.031 224 277.731 226.1 275.331C227.5 273.731 228.8 272.031 230.1 270.431C273.8 214.531 263.9 133.731 208 90.1306C185.2 72.4306 157.3 62.8306 128.6 62.8306ZM128.6 240.631C101.4 240.631 79.4 218.631 79.4 191.431C79.4 164.231 101.4 142.231 128.6 142.231C155.8 142.231 177.8 164.231 177.8 191.431C177.8 218.631 155.8 240.631 128.6 240.631Z" fill="#FF7E36"/>
  <path d="M170.5 60.1307C180.7 57.9307 187.2 47.8307 185 37.6307C183.1 28.9307 175.4 22.7306 166.5 22.7306C163.7 22.7306 160.9 23.4307 158.4 24.6307C155.3 8.23066 139.5 -2.56935 123.1 0.53065C110.9 2.83065 101.3 12.4307 99 24.6307C96.5 23.4307 93.7 22.7306 90.9 22.7306C80.5 22.7306 72 31.2307 72 41.6307C72 50.5307 78.2 58.2307 86.9 60.1307C113.9 50.6307 143.4 50.6307 170.5 60.1307Z" fill="#00B493"/>
</svg>

가장 기본적으로 우리가 많이 접하는 형태이다.

 

# URL

background-image: url("data:image/svg+xml,%3Csvg width='258' height='340' viewBox='0 0 258 340' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M128.6 62.8306C57.6 62.7306 0.1 120.231 0 191.131C0 219.831 9.6 247.731 27.3 270.431C28.6 272.031 29.9 273.731 31.3 275.331C33.3 277.731 35.4 280.031 37.6 282.231L37.8 282.431C62.6 308.931 94 328.431 128.7 339.031C163.4 328.431 194.8 308.931 219.6 282.431L219.8 282.231C222 280.031 224 277.731 226.1 275.331C227.5 273.731 228.8 272.031 230.1 270.431C273.8 214.531 263.9 133.731 208 90.1306C185.2 72.4306 157.3 62.8306 128.6 62.8306ZM128.6 240.631C101.4 240.631 79.4 218.631 79.4 191.431C79.4 164.231 101.4 142.231 128.6 142.231C155.8 142.231 177.8 164.231 177.8 191.431C177.8 218.631 155.8 240.631 128.6 240.631Z' fill='%23FF7E36'/%3E%3Cpath d='M170.5 60.1307C180.7 57.9307 187.2 47.8307 185 37.6307C183.1 28.9307 175.4 22.7306 166.5 22.7306C163.7 22.7306 160.9 23.4307 158.4 24.6307C155.3 8.23066 139.5 -2.56935 123.1 0.53065C110.9 2.83065 101.3 12.4307 99 24.6307C96.5 23.4307 93.7 22.7306 90.9 22.7306C80.5 22.7306 72 31.2307 72 41.6307C72 50.5307 78.2 58.2307 86.9 60.1307C113.9 50.6307 143.4 50.6307 170.5 60.1307Z' fill='%2300B493'/%3E%3C/svg%3E");

css url에 svg 파일 path를 잡는 것 아니라 data: 스킴을 사용해서 인라인으로 임베딩 할 수 있는데, xml을 url encode 된 상태로 넘겨, css에 background로 사용할 수도 있습니다.

 

- base64

data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjU4IiBoZWlnaHQ9IjM0MCIgdmlld0JveD0iMCAwIDI1OCAzNDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTEyOC42IDYyLjgzMDZDNTcuNiA2Mi43MzA2IDAuMSAxMjAuMjMxIDAgMTkxLjEzMUMwIDIxOS44MzEgOS42IDI0Ny43MzEgMjcuMyAyNzAuNDMxQzI4LjYgMjcyLjAzMSAyOS45IDI3My43MzEgMzEuMyAyNzUuMzMxQzMzLjMgMjc3LjczMSAzNS40IDI4MC4wMzEgMzcuNiAyODIuMjMxTDM3LjggMjgyLjQzMUM2Mi42IDMwOC45MzEgOTQgMzI4LjQzMSAxMjguNyAzMzkuMDMxQzE2My40IDMyOC40MzEgMTk0LjggMzA4LjkzMSAyMTkuNiAyODIuNDMxTDIxOS44IDI4Mi4yMzFDMjIyIDI4MC4wMzEgMjI0IDI3Ny43MzEgMjI2LjEgMjc1LjMzMUMyMjcuNSAyNzMuNzMxIDIyOC44IDI3Mi4wMzEgMjMwLjEgMjcwLjQzMUMyNzMuOCAyMTQuNTMxIDI2My45IDEzMy43MzEgMjA4IDkwLjEzMDZDMTg1LjIgNzIuNDMwNiAxNTcuMyA2Mi44MzA2IDEyOC42IDYyLjgzMDZaTTEyOC42IDI0MC42MzFDMTAxLjQgMjQwLjYzMSA3OS40IDIxOC42MzEgNzkuNCAxOTEuNDMxQzc5LjQgMTY0LjIzMSAxMDEuNCAxNDIuMjMxIDEyOC42IDE0Mi4yMzFDMTU1LjggMTQyLjIzMSAxNzcuOCAxNjQuMjMxIDE3Ny44IDE5MS40MzFDMTc3LjggMjE4LjYzMSAxNTUuOCAyNDAuNjMxIDEyOC42IDI0MC42MzFaIiBmaWxsPSIjRkY3RTM2Ii8+CiAgPHBhdGggZD0iTTE3MC41IDYwLjEzMDdDMTgwLjcgNTcuOTMwNyAxODcuMiA0Ny44MzA3IDE4NSAzNy42MzA3QzE4My4xIDI4LjkzMDcgMTc1LjQgMjIuNzMwNiAxNjYuNSAyMi43MzA2QzE2My43IDIyLjczMDYgMTYwLjkgMjMuNDMwNyAxNTguNCAyNC42MzA3QzE1NS4zIDguMjMwNjYgMTM5LjUgLTIuNTY5MzUgMTIzLjEgMC41MzA2NUMxMTAuOSAyLjgzMDY1IDEwMS4zIDEyLjQzMDcgOTkgMjQuNjMwN0M5Ni41IDIzLjQzMDcgOTMuNyAyMi43MzA2IDkwLjkgMjIuNzMwNkM4MC41IDIyLjczMDYgNzIgMzEuMjMwNyA3MiA0MS42MzA3QzcyIDUwLjUzMDcgNzguMiA1OC4yMzA3IDg2LjkgNjAuMTMwN0MxMTMuOSA1MC42MzA3IDE0My40IDUwLjYzMDcgMTcwLjUgNjAuMTMwN1oiIGZpbGw9IiMwMEI0OTMiLz4KPC9zdmc+

https://easy64.org/svg-editor/

svg url 인코드를 하는 방식 말고 base64로 표현해주어서, css에 background로 사용할 수도 있습니다.

다만 data스킴에서 base64를 지원하는 이유는 png, jpeg와 같은 이진 데이터를 string으로 표현하기 쉽게 지원하기 위해서이고, xml로 표현되어있는 svg를 base64로 전환하게 되면 더 길어지기 때문에 최적화된 방식은 아닙니다. (데이터 3바이트당 4자가 필요하며 끝에 약간의 패딩이 필요할 수 있습니다.)

 

임베드된 방식으로 하는 경우 별도의 HTTP 요청 및 헤더 오버해드가 없기에 가벼운 파일의 경우 임베딩 하는 것도 좋은 방식입니다.

 

# SVGO

svg는 xml로 이루어지다 보니 같은 형상 이어도 표현할 수 있는 방식이 다양하다 보니, 특히 다양한 편집기에서 내보낸 파일은 중복되고 쓸모없는 정보를 포함시키다 보니 네트워크 페이로드를 낭비하게 됩니다. 그렇기에 SVG 렌더링 결과에 영향을 주지 않는 메타데이터, 주석, 숨겨진 요소, 기본 또는 비최적 값들을 안전하게 제거하거함으로 svg를 최적화하여 사용할 수 있습니다. 

 

GitHub - svg/svgo: ⚙️ Node.js tool for optimizing SVG files

⚙️ Node.js tool for optimizing SVG files. Contribute to svg/svgo development by creating an account on GitHub.

github.com

<svg xmlns="http://www.w3.org/2000/svg" width="258" height="340" fill="none">
  <path d="M128.6 62.83C57.6 62.73.1 120.232 0 191.132c0 28.7 9.6 56.6 27.3 79.3 1.3 1.6 2.6 3.3 4 4.9 2 2.4 4.1 4.7 6.3 6.9l.2.2c24.8 26.5 56.2 46 90.9 56.6 34.7-10.6 66.1-30.1 90.9-56.6l.2-.2c2.2-2.2 4.2-4.5 6.3-6.9 1.4-1.6 2.7-3.3 4-4.9 43.7-55.9 33.8-136.7-22.1-180.3-22.8-17.7-50.7-27.3-79.4-27.3Zm0 177.801c-27.2 0-49.2-22-49.2-49.2 0-27.2 22-49.2 49.2-49.2 27.2 0 49.2 22 49.2 49.2 0 27.2-22 49.2-49.2 49.2Z" fill="#FF7E36"/>
  <path d="M170.5 60.13c10.2-2.2 16.7-12.3 14.5-22.5-1.9-8.7-9.6-14.9-18.5-14.9-2.8 0-5.6.7-8.1 1.9-3.1-16.4-18.9-27.2-35.3-24.1-12.2 2.3-21.8 11.9-24.1 24.1-2.5-1.2-5.3-1.9-8.1-1.9-10.4 0-18.9 8.5-18.9 18.9 0 8.9 6.2 16.6 14.9 18.5 27-9.5 56.5-9.5 83.6 0Z" fill="#00B493"/>
</svg>

78프로 감소

# SVGR

 

SVGR - Transforms SVG into React Components. - SVGR

Transforms SVG into React Components.

react-svgr.com

svgr은 svg를 react 환경에서 바로 가져다가(import) 사용할 수 있도록 react component화를 지원하는 도구입니다.

svgo과정을 통한 최적화, html을 jsx로 변환하는 과정을 제공해주어서 리액트에서 더 편하게 svg를 다룰 수 있게 됩니다.

//webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/i,
        issuer: /\.[jt]sx?$/,
        use: ['@svgr/webpack'],
      },
    ],
  },
}

webpack loader를 통해 적용해 볼 수 있습니다.