Next.js는 기본적으로 이미지 파일을 import 하게되면 리소스 URL 방식으로 가져오게 됩니다. 따라서 다음과 같은 import 구문은 string으로 작동하게되죠.
그런데 CRA나 다른 프레임워크를 사용하셨다면 이는 굉장히 불편하게 느껴질겁니다. 왜냐하면 다른 프레임워크는 SVG 파일에 대해서는 URL이 아닌 React 컴포넌트로 변환해 불러오게 됩니다. 이를 이용해 CSS의 fill 속성을 이용해 아이콘의 색상을 변경하는 방식을 사용하는 사람이 존재할 겁니다. (제가 그렇거든요..)
이를 해결하기 위해
next.config.js
를 어떻게 수정하고, 또 기존 URL 방식을 유지하면서 사용할 수 있도록 하는지 방법을 알아보도록 하겠습니다.패키지 설치
Next.js에서는 기본적으로 웹팩 플러그인을 지원합니다. 그리고 SVG파일을 React 컴포넌트로 변환하는 유명한 플러그인 패키지는
@svgr/webpack
입니다. 이 플러그인을 사용해야지만 저희가 원하는게 가능하기 때문에 설치를 진행해봅시다.웹팩 설정 추가하기
Next.js에는 각종 설정을 관리하기 위한 파일인
next.config.js
파일이 존재합니다. 해당 파일의 webpack
을 사용해 기존 Next.js에서 사용하는 웹팩 설정을 수정할 수 있습니다. 이를 이용해 svg 파일 불러오는 규칙을 수정할 예정입니다. 아래 내용을 확인하시고 적용하시면 됩니다.Next.js 13의 실험적 기능인 TurboPack에서는 @svgr/webpack 사용이 가능하나 기존 규칙인 url 파일 로더를 사용 할 수 없어, 둘 중 한가지만 사용해야합니다.
파일 불러오기
위 설정을 적용하고 SVG 파일을 이제 import 하게되면 아직 URL로 불러오는 것을 확인 할 수 있습니다. 저는 주로 이미지로서 사용하기 때문에 import 문에 쿼리를 작성해야 React 컴포넌트로 불러오도록 만든 상태입니다. 아래 예제를 보시면 쉽게 이해하실 수 있을 겁니다.
svg 파일 경로에 이상한 문구가 추가된걸 보실 수 있을겁니다.
!
를 사용하는건 위 설정에서 resourceQuery
를 통해 읽히는 쿼리 내용입니다. 이를 통해 ...svg!components
로 불러오게되면 @svgr/webpack
을 사용할 수 있도록 웹팩이 도와주는 겁니다. 이제 URL 방식과 React 컴포넌트 방식 두가지를 모두 사용할 수 있게되었습니다!ViewBox 문제
제가 알려드린대로 사용한다면 아마
width
와 height
에 문제가 생길겁니다. 실제 svg 파일과 렌더링된 svg 태그를 직접 비교해봤습니다.width, height는 제가 컴포넌트에 직접 설정했으니 무시해도 된다지만,
viewBox
라는 속성이 누락되어 있는 것을 확인하실수 있을겁니다. 이는 @svgr/webpack
의 설정 기본값이 svg 파일의 최적화 과정중 viewBox
라는 속성이 제거되어 렌더링 되는 문제가 있습니다.그러면 이
viewBox
속성이 궁금해집니다. MDN 문서의 내용을 봅시다.viewBox
속성은 특수한 container element 에 fit 하기 위한 주어진 graphics stretch 의 set 을 명시한다.
말이 어렵지 간단하게 풀어보자면 SVG 파일의 캔버스 크기를 설정하는 속성이라 생각하시면 됩니다. 해당속성은
min-x min-y width height
의 숫자로 구성된 문자열을 작성하게 되는데, svg 파일을 렌더링 할 때 캔버스 좌상단 좌표, 캔버스 크기를 의미하게 됩니다. 이 속성이 없다면 브라우저는 svg 태그의 렌더링 사이즈 기준으로 viewBox를 설정해서 그리게되는데, 이때 실제 이미지의 좌표와 렌더링 좌표가 틀어지면서 생기는 문제였던 겁니다.SVGO 설정
이를 해결하기 위해
@svgr/webpack
의 최적화 설정을 바꿔주겠습니다. svgr의 svg파일 최적화에는 svgo
라는 패키지를 이용하며, 최적화 설정을 다룰 수 있도록 만들어져 있습니다. svgo
의 설정은 svgo.config.js
파일을 만들어 관리하면 됩니다. 공식문서를 참조하여 설정을 만들겠습니다.svgo이 기본 플러그인 프리셋인
preset-default
플러그인을 불러오는데 옵션에 overrides
를 통해 프리셋 설정을 덮어 씌우게 됩니다. 플러그인 중 removeViewBox
라는 플러그인을 false
로 설정해 비활성화하여 viewBox가 사라지는 문제를 해결합니다. 해당 파일을 next.config.js
가 있는 폴더에 같이 위치해두고 실행을 해보면, viewBox
가 나타나는 것을 확인하실 수 있습니다.이로써 모든 문제를 해결하였습니다!
마무리
프레임워크는 모든것을 다해주지만, 설정이 유연하지 못하다면, 쓰는 것 만도 못한 상황이 닥치곤 합니다. 대표적으로 구 버전의
react-scripts
(create-react-app)가 있겠네요. 확실히 몇년 전보다는 프레임워크나 라이브러리의 지원이 상당히 유연하게 바뀐거 같습니다. 덕분에 공식문서를 보기만해도 이런 문제를 해결할 수 있는 정도까지 도달하게 되어 굉장히 편해진거 같습니다. 만약 문제가 생겨 설정을 바꿔야 한다면 공식문서를 참조하시는게 어떤가요?