키워드: svgr, svg, id collision, unique id, sed, regex
상황
loplat UI에서 svgr을 이용하여 Icon 컴포넌트를 만든다.
실제 프로젝트에서 Icon을 사용할 때, 하나의 아이콘을 2번 렌더링하면 이미지가 깨지는 현상을 발견했다.
// 2번 렌더링
<InfocircleOutlineIcon {...props} />
...
<InfocircleOutlineIcon {...props} />
원인이 무엇인지 고민해보니 svg 속성 중 id가 random값이 아닌 고정값인 것을 확인했다. __a, __b 가 suffix로 붙지만 'infocircle_outline_svg__a' 라는 id값 자체는 고정이라 컴포넌트를 2번 렌더링하면 id 충돌이 일어나는 것이다.
loplat UI 코드를 통해 svgr 이 만들어주는 id는 static하는 것을 확인했다.
<svg
width={size}
height={size}
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
style={style}
className={className}
viewBox="0 0 32 32"
>
<defs>
<path
d="..."
id="infocircle_outline_svg__a" // id 고정
/>
</defs>
<g transform="translate(2 2)" fill="none" fillRule="evenodd">
<mask id="infocircle_outline_svg__b" fill="#fff"> // id 고정
<use xlinkHref="#infocircle_outline_svg__a" /> // id 고정
</mask>
<g mask="url(#infocircle_outline_svg__b)"> // id 고정
<path fill={fillColor} d="M-2-2h32v32H-2z" />
</g>
</g>
</svg>
먼저 grep을 이용하여 조작할 파일을 지정한다. ('uniqueId'라는 문자열을 포함하고 있고 'generated' 폴더 안에 있는 txs 파일, 즉 Icon 컴포넌트 파일들) 그 후, xargs를 이용하여 이 파일들을 sed 명령어의 인자로 전달한다. -i 옵션을 통해 파일을 '수정'하고, -e 옵션 뒤에는 실행할 명령을 적는다. 실행문은 정규표현식을 이용하여 기존의 'id__a'를 'id__a__{uniqueId}' 형태로 치환한다. (정규표현식과 shell 스크립트를 다듬어 한 줄로 표현할 수도 있지만 가독성과 이해를 위해 4줄로 분리하였다)
그 뒤 yarn svgr 명령어에 해당 shell script를 실행하는 명령을 추가한다.(svgr cli와 template을 통해 리액트 컴포넌트를 만들고나서(해결과정 2), 그 파일들에 대해 assign-id-to-svg.sh 스크립트를 실행해야 함)
// package.json
"svgr": "npx @svgr/cli --template svgr-cli.template.js && ... && cd src/assets/Icon/tools && sh assign-id-to-svg.sh"