svgo에서 viewBox를 지우는 이유

June 01, 2023

react로 svg를 다룰 때 겪을 가능성이 큰 문제에 대해 정리하였다. 분명 넣을 때는 멀쩡했는데, 빌드 완료한 코드의 svg가 좀 이상한 문제가 발생하는 경우가 있다. 그건 svgo 때문에 발생했을 가능성이 크다.

svgo?

SVG Optimizer의 약자로, svg 최적화 도구다. 보통 svgr을 사용하게 되면 기본적으로 켜져 있기 때문에 접하기 쉽다.

svgr?

react에서 svg를 사용할 때 많이 쓰는 방법 중 하나가 svgr을 이용하는 것이다. svgr은 svg 파일을 React component로 바꿔줘서 쓰기 쉽게 해 주는 툴이다. 그리고 svgr에서는 기본적으로 svgo를 이용해 svg 최적화를 진행한다.

viewBox?

svg를 그릴 때, svg viewport의 위치와 크기를 정할 수 있다. 이 값이 바뀜에 따라 svg가 그려지는 위치가 바뀐다. viewBox의 설정 없이 svg의 width와 height를 바꾸면 잘려 나오는 svg를 볼 수 있다.

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> <rect x="0" y="0" width="100%" height="100%" /> <circle cx="50%" cy="50%" r="4" fill="white" /> </svg> <svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"> <rect x="0" y="0" width="100%" height="100%" /> <circle cx="50%" cy="50%" r="4" fill="white" /> </svg>

viewbox.png (두 svg의 차이는 viewBox밖에 없다)

svgo에 무슨 문제가 있는가

최적화 과정에서 viewBox를 제거한다(!).

그냥 묻지도 따지지도 않고 지우는 건 아니고, widthheight 속성이 viewBox와 같은 경우에만 지운다. 제거를 안 하는 옵션을 따로 제공하고 있지 않고, 관련 plugin을 꺼야 한다.

{ loader: '@svgr/webpack', options: { svgoConfig: { plugins: [ { removeViewBox: false }, ], }, }, }

이런 식으로.

하지만, 사람들은 왜 이 기능이 default로 켜져 있는지 의아해 했고, 많은 사람들이 기본으로 꺼져 있기를 원했다.

왜 안 고치고 있나요?

물론 오픈소스기 때문에 사람들은 해당 레포에서 의문을 제기하기 시작했다.

benefit.png ...그리고 가차없이 닫혔다.

svgo에 있는 한 메인테이너가 viewBox 속성 자체도 용량을 가지고 있기 때문에 바이트 수를 줄이기 위해 지웠다고 답한 뒤, 장장 4년에 걸친 댓글 싸움을 하기에 이르렀다. 해당 메인테이너는 viewBox는 width랑 height가 각각 같을 때만 지우는데 무슨 문제냐는 입장이다.

하지만 당연히 문제가 생긴다. scalability 관련해서 문제가 생기는데, viewBox가 없는 svg인 경우 css로 해당 svg의 크기를 변경할 때 짤리는 현상이 발생한다. scale.png

그렇기 때문에 사람들이 viewBox 제거를 끄자고 계속 주장하지만...

minority.png

메인테이너는 "아 이해했어. 쓸모가 있을 때가 있구나. 하지만 몇몇 사람들 때문에 default optimization을 끄는건 싫어"라고 하며 의견을 묵살했다. 많은 사람들이 반론을 제기하지만 결국 다 묵살.

시간은 흘러 이슈가 발행됐던 날로부터 몇 년이 지났고, 물론 변한 것은 없었다. 사람들은 점점 화가 나기 시작했고, 급기야 짤방까지 만들며 비난을 하기에 이르렀으며, 결국 포크를 해야 한다는 극단적인 주장까지 나오기도 했다.

cat.png (화가 많이 나신 듯)

결국 지친 사람들은 다른 방법을 찾게 되는데, 더 이상 관리하고 있지 않는 해당 레포의 초기 메인테이너를 찾아가 컨택을 하기에 이르렀다.

original.png

그 메인테이너는 현재 svgo가 npm 주간 다운로드 15M이나 되는데, breaking change를 제대로 된 확인 없이 자신이 merge할 수는 없다고 하며 대신 viewBox 관련 이슈에 대한 내용을 README.md Troubleshooting 최상단에 올리는 PR을 merge하게 된다.

readme.png troubleshooting.png

이렇게 README에 적히게 되었고, 2023-06-01 현재 svgo의 마지막 code merge이다.

결론

오픈소스도 결국 사람이 만드는 프로젝트고, 사람이 운영한다. 세상에는 수 많은 사람들이 있고, 그 중에서는 별의 별 사람들이 있다는 사실을 항상 기억하며 오픈소스를 사용하는 것이 좋다고 생각한다. 언제나 오픈소스가 이상적으로 돌아가진 않고, 오히려 예상했던 대로 잘 굴러가는 케이스가 극히 드물지 않을까? 마치 사업처럼.

또 오픈소스 관리자의 입장이 이해가 안 가는 것도 아닌 게, 수 많은 사람들이 이용하고 있는 도구의 기본값이 갑자기 바뀌게 되면 엄청난 파급력을 불러일으킬 것이기 때문에 조심하는 것도 그럴 수 있긴 하다고 생각한다. 물론 그럼에도 불구하고 해당 이슈는 사실상 버그 아닌가 싶어서 마음에 드는 대처는 아니었다.

그리고 svgo로 최적화 시킨 svg는 viewBox 뿐만 아니라 다른 부분들도 높은 확률로 박살이 나 있어서, 그냥 끄는 게 정신건강에 이롭다...

// webpack.config.js { test: /\.svg$/, use: ['@svgr/webpack'], options: { svgo: false } }

이렇게 꺼 버리자. svg를 최적화 하려면 js 단에서 하는 게 아니라 svg 파일 단에서 하는게 맞다고 생각한다. 안 그러면 디자이너가 원하는 대로의 모습이 나오지 않는다.

Reference

MDN reference - viewBox

SVGO Github issue - What is the benefit of stripping viewBox?


Profile picture

Written by Mingyu Kim who works as a front-end engineer.