notes
SVGR
SVGR로 SVG를 React 컴포넌트로 변환·사용하는 설정과 주의점 메모.
- SVG 를 손으로 JSX 로 옮기지 않아도 SVGR 이
<svg>컴포넌트로 바꿔 준다. fill="currentColor"로 바꾸면 글자색을 따라가서 테마 연동과 props 제어가 쉽다.- 아이콘은 SVGR, 사진과 큰 일러스트는
img나 Next Image 로 나눈다.
SVGR 이 뭔가
logo.svg 를 손으로 JSX 로 옮기지 않아도, 기계가 <svg>...</svg> 를 돌려주는 컴포넌트로 바꿔 준다.
비유하면 이렇다.
왜 쓰나
SVG 를 <img> 로 쓰면 색을 바꾸기 어렵다. fill 을 CSS 로 못 건드리고, currentColor 로 테마를 따라가게 할 수도 없고, 크기나 className 을 props 로 넘기기도 불편하다.
<img src="/icons/search.svg" />
SVGR 로 컴포넌트로 만들면 이렇게 쓴다.
<CommonSearch className="text-semantic-primary" width={20} />
fill="currentColor"이면 글자색을 따라간다.width,height,className을 props 로 조절한다.- TypeScript 자동완성이 된다.
동작 방식 두 가지
문서에 나오는 방식과 회사 모노레포에서 쓰는 방식이 다르다.
① 빌드할 때 변환 (번들러 플러그인)
import 하는 순간 번들러가 SVG 를 컴포넌트로 바꾼다. 문서의 ReactComponent as Logo 는 CRA 와 webpack(@svgr/webpack) 시절 문법이다.
// webpack + @svgr/webpack (예전 CRA 방식)
import { ReactComponent as Logo } from './logo.svg';
// Vite + vite-plugin-svgr 4.x 이상
import Logo from './logo.svg?react';
Vite 는 vite-plugin-svgr 를 쓰는데, 4.x 부터 ?react 를 붙여야 컴포넌트로 가져온다. Next.js 는 webpack 이면 @svgr/webpack 로더를, Turbopack 이면 turbopack.rules 에 같은 로더를 등록한다.
② 미리 변환해 두기 (CLI)
회사 모노레포는 이 방식이다. SVG 를 넣고, 스크립트를 돌리고, 만들어진 TSX 를 커밋한다.
pnpm run svgr:icons
svg/Name=search.svg
↓ SVGR CLI
common/CommonSearch.tsx
↓ import
import { CommonSearch } from '@monorepo/ui/icons/common'
import * as React from "react";
import type { SVGProps } from "react";
const CommonSearch = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={24}
height={24}
fill="currentColor"
viewBox="0 0 24 24"
{...props}
>
<path d="M16.375 10.125a6.25 6.25 0 1 0-12.5 0 ..." />
</svg>
);
export default CommonSearch;{...props} 덕분에 나머지 props 는 그대로 <svg> 에 넘어간다.
모노레포 워크플로
아이콘 카테고리는 common, color, navigation, detail 네 개다. 설정은 .svgrrc.js 와 scripts/svgr-icons.js 가 맡는다. @monorepo/ui/icons 는 경로 별칭(alias)이다.
문서의 장점을 쉬운 말로
동적 import 예시는 문서에 ReactComponent 와 img src 가 섞여 있어서 헷갈린다. 실무에서는 아이콘 이름이 정해져 있으면 정적 import, 런타임에 바꿔야 하면 아이콘 맵 객체(export:icon-map 스크립트)를 쓴다.
SVGR vs img, Next Image
아이콘은 SVGR 로, 사진은 OptimizedImage 나 Next Image 로 간다.
주의할 것
- SVG 가 너무 복잡하면 TSX 도 커진다. Figma 에서 내보내기 전에 단순화한다.
- CLI 방식은 런타임 변환이 아니다. SVG 를 추가하거나 바꾸면
pnpm run svgr:icons로 다시 만들고 커밋해야 한다. fill이 하드코딩된 SVG 는 색이 안 바뀐다..svgrrc.js에서currentColor로 치환하게 해 두었다.- 새 아이콘은
svg/폴더에 넣고 스크립트를 돌리는 게 전부다.
한 줄 요약
SVGR 은 SVG 를 손으로 JSX 로 안 짜도 되게 해 주는 변환기다. 회사 모노레포는 빌드마다 변환하는 대신 svgr:icons 로 .tsx 를 미리 만들어 두고, 앱은 @monorepo/ui/icons 만 import 한다. 문서의 webpack 예시는 설치 방식이 다를 뿐, SVG 를 React 컴포넌트로 바꾼다는 개념은 같다.