Search
😵

TIL: React+Webpack에서 SVGR을 사용할 때 SVG 최적화 막기

Date
2021/06/01
Tags
TIL
React
Frontend
Created by

상황

React 프로젝트에서 Webpack을 사용하고 있고, @svgr/webpack을 통해 SVG 파일이 Bundling + React Component로 Rendering되도록 관리하고 있다.
원래 React에서는 SVG 파일을 바로 렌더링할 수 없다. CRA 등에서 SVG를 간편하게 리액트 컴포넌트로서 사용할 수 있는 건 (CRA 등에 내장된) SVGR 덕분이다.
<rect></rect> 안에 애니메이션 프로퍼티가 height으로 지정된 SVG 아이콘 파일이 있었는데, Bundling을 거쳐 Webpack Dev Server로 결과물을 보니 SVG 애니메이션이 아예 먹통이었다.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: none; display: block; shape-rendering: auto;" width="current" height="current" fill="current" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"> <g transform="rotate(180 50 50)"> <rect x="14" y="12.5" width="22" height="40"> <animate attributeName="height" calcMode="spline" values="50;75;10;50" times="0;0.33;0.66;1" dur="1s" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" repeatCount="indefinite" begin="0s"></animate> </rect> <rect x="39" y="12.5" width="22" height="40"> <animate attributeName="height" calcMode="spline" values="50;75;10;50" times="0;0.33;0.66;1" dur="1s" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" repeatCount="indefinite" begin="-0.3333333333333333s"></animate> </rect> <rect x="64" y="12.5" width="22" height="40"> <animate attributeName="height" calcMode="spline" values="50;75;10;50" times="0;0.33;0.66;1" dur="1s" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" repeatCount="indefinite" begin="-0.6666666666666666s"></animate> </rect> </g> </svg>
XML
위 코드는 Equalizer 애니메이션 아이콘 SVG 코드이다.

원인

Inspector로 확인해보니 SVG <rect> Element가 <path> Element로 렌더링되어 있는 것을 확인할 수 있었다. 그래서 <rect></rect> 내에 있었던 height 애니메이션 프로퍼티가 전혀 작동하지 않고 있던 것이었다.
<svg width="18px" height="18px" fill="#56F58E" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" display="block" style="margin: auto; background: 0px 0px;"> <path d="M86 87.5H64v-40h22z"> <animate attributeName="height" calcMode="spline" values="50;75;10;50" dur="1s" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" repeatCount="indefinite" begin="0s"></animate> </path> <path d="M61 87.5H39v-40h22z"> <animate attributeName="height" calcMode="spline" values="50;75;10;50" dur="1s" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" repeatCount="indefinite" begin="-0.3333333333333333s"></animate> </path> <path d="M36 87.5H14v-40h22z"> <animate attributeName="height" calcMode="spline" values="50;75;10;50" dur="1s" keySplines="0.5 0 0.5 1;0.5 0 0.5 1;0.5 0 0.5 1" repeatCount="indefinite" begin="-0.6666666666666666s"></animate> </path> </svg>
XML
<path>에는 height attribute가 없기 때문에 당연히 애니메이션이 작동하지 않는다.
분명 SVGR에서 어떠한 최적화를 거치는 것으로 생각했고, SVGR이 기본적으로 SVG를 Component로 변환하기 전에 SVG를 최적화하기 위해 SVGO를 사용하고 있다는 것을 알 수 있었다.

해결 방안

Webpack Config 파일의 @svgr/webpack 부분에서 SVGO 옵션을 꺼 주면 된다.
{ test: /\.svg$/, use: [ { loader: '@svgr/webpack', options: { svgo: false, }, }, ], }
JavaScript
나는 꼼수로 해결하고 나서 위 방법을 알게 되었는데, 그냥 <rect>rx="0" ry="0" 프로퍼티를 주면 SVGO에서 <path>로 최적화되지 않는다.

References