SVG → JSX 변환기
SVG를 React JSX 컴포넌트로 브라우저에서 즉시 변환. 카멜케이스 속성, className, TypeScript, forwardRef, memo 래핑 지원. 무료, 회원가입 불필요.
- 브라우저에서 처리
- 데이터가 브라우저 밖으로 나가지 않습니다
- 무료 · 회원가입 불필요
WeChat으로 스캔하여 공유
예시·자세한 설명·자주 묻는 질문 실제 출력이 있는 예시, 다른 도구와의 차이, 자주 묻는 질문.
속성 변환 규칙
| SVG | JSX |
|---|---|
stroke-width | strokeWidth |
stroke-linecap | strokeLinecap |
fill-rule | fillRule |
clip-path | clipPath |
class | className |
font-size | fontSize |
text-anchor | textAnchor |
xmlns="..." | (제거됨) |
출력 모드
- 기본: TypeScript 주석 없는 일반 함수 컴포넌트.
- TypeScript:
React.FC<React.SVGProps<SVGSVGElement>>타입 적용. className, style, onClick이 타입 안전하게 작동합니다. - forwardRef:
React.forwardRef로 감싸 부모 컴포넌트에 SVG 요소 ref를 공개합니다. - memo: 최종 내보내기를
React.memo로 감싸 불필요한 리렌더링을 방지합니다.
주요 사용 사례
- Figma나 Illustrator에서 내보낸 SVG를 React 아이콘 컴포넌트로 변환
- SVG 아이콘 라이브러리를 JSX 기반 디자인 시스템으로 마이그레이션
- SVG 아이콘이 className, style 등 React props를 받을 수 있도록 설정
- props 스프레드로 aria-label을 받는 접근성 아이콘 컴포넌트 구축
변환 예시
24 × 24 더하기 아이콘을 컴포넌트 이름 PlusIcon, 옵션은 모두 끈 상태로 변환합니다:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="#000" stroke-width="2" stroke-linecap="round" d="M12 5v14M5 12h14"/></svg>
출력:
import React from 'react';
function PlusIcon(props) {
return (
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" {...props}><path stroke="#000" strokeWidth="2" strokeLinecap="round" d="M12 5v14M5 12h14" /></svg>
);
}
export default PlusIcon;
xmlns는 사라지고 stroke-width, stroke-linecap은 camelCase가 되며, 나머지 마크업은 그대로입니다. {...props}는 루트 자체 속성 뒤에 들어갑니다. svgr 기본값(expandProps: 'end')과 같은 위치라서 호출하는 쪽 값이 우선합니다. <PlusIcon width={48} fill="red" />는 48 px, 빨간색으로 렌더링되고 height는 24 그대로입니다. 값은 문자열로 남지만(strokeWidth="2") React는 문자열과 숫자를 모두 받습니다. TypeScript, forwardRef, memo를 모두 켜면 같은 아이콘이 const PlusIcon = forwardRef<SVGSVGElement, React.SVGProps<SVGSVGElement>>(function PlusIcon(props, ref) { ... })가 되고, <svg> 자체 속성 뒤에 ref={ref} {...props}, 끝에 export default memo(PlusIcon);가 붙습니다. React 19부터는 forwardRef가 필요 없고 함수 컴포넌트가 ref를 prop으로 받을 수 있습니다.
Illustrator에서 Internal CSS로 내보내고 인라인 style과 xlink:href가 들어간 아이콘입니다. 컴포넌트 이름은 Icon:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><!-- Generator: Adobe Illustrator --><defs><style>.cls-1{fill:#e11d48;}</style></defs><path id="a" class="cls-1" style="stroke:#000;stroke-width:2" d="M12 5v14"/><use xlink:href="#a"/></svg>
출력:
import React from 'react';
function Icon(props) {
return (
<svg viewBox="0 0 24 24" {...props}>{/* Generator: Adobe Illustrator */}<defs><style>{".cls-1{fill:#e11d48;}"}</style></defs><path id="a" className="cls-1" style={{ "stroke": "#000", "strokeWidth": "2" }} d="M12 5v14" /><use xlinkHref="#a" /></svg>
);
}
export default Icon;
주석은 {/* ... */}가 되며 React는 이를 그리지 않습니다. <style> 안의 CSS는 JavaScript 문자열 하나가 되어 중괄호가 더 이상 JSX로 읽히지 않습니다. 안의 엔티티는 디코딩하고 <![CDATA[ ... ]]> 감싸기는 벗깁니다. style 속성은 값을 그대로 옮긴 객체가 되고, xlink:href는 xlinkHref가 됩니다. esbuild 0.21.5로 컴파일하고 React 19.2.0 개발 빌드로 렌더링하면 <svg viewBox="0 0 24 24"><defs><style>.cls-1{fill:#e11d48;}</style></defs><path id="a" class="cls-1" style="stroke:#000;stroke-width:2" d="M12 5v14"></path><use xlink:href="#a"></use></svg>가 되며 콘솔 경고는 없습니다.
붙여넣기 전에: 내보내기 설정
- Figma: 레이어를 선택하고 Export → SVG. ID로 요소를 다루지 않는다면 “Include “id” attribute”는 끈 채로 둡니다.
- Illustrator: File → Export → Export As → SVG(메뉴 이름은 영문판 기준). Styling을 Presentation Attributes로 두면 가장 짧은 컴포넌트가 됩니다. Internal CSS와 Inline Style은
<style>블록이나style="..."문자열을 만들며(Adobe: SVG 내보내기 옵션), 이 도구는 위 예시처럼 CSS 문자열과 스타일 객체로 바꿉니다.<style>블록은 페이지 전체에 적용되므로 두 아이콘이 모두.cls-1을 쓰면 서로의 색을 바꿉니다. <?xml ... ?>선언은 도구가 지우고 주석은 JSX 주석으로 바꾸므로<!-- Generator: ... -->를 먼저 지울 필요가 없습니다.
직접 고쳐야 하는 부분
각 행은 출력을 esbuild 0.21.5로 컴파일하고 React 19.2.0으로 렌더링해 확인했습니다.
| 붙여넣은 SVG | 도구 출력 | React에서의 결과 | 이렇게 바꾸기 |
|---|---|---|---|
style="fill:red !important", 같은 속성 중복, style 안의 CSS 주석 | 출력 없음: 변환을 멈추고 복사를 끄며 상태 줄에 스타일 안의 위치를 표시 | — | 규칙을 <style> 블록이나 CSS 파일로 옮기거나 !important를 빼기 |
<text>{count}</text> | <text>{count}</text> | {count}라는 글자를 표시 | 변수를 쓰려면 직접 {count}로 고치기 |
고정된 fill / stroke 색상 | 그대로 | 아이콘이 글자색을 따라가지 않음 | fill="currentColor" / stroke="currentColor" |
다른 아이콘과 같은 클래스 이름을 쓰는 <style> | CSS 문자열 | 규칙이 페이지 전체에 적용됨 | 클래스 이름을 바꾸거나 Presentation Attributes로 내보내기 |
제한 사항
- XML 파서가 아니라 정규식으로 처리합니다. 주석,
<style>블록, CDATA를 먼저 읽으므로<!-- ... -->안에 쓴 태그는 변환되지 않습니다. 따옴표로 감싼 속성값에>나/가 있어도 괜찮습니다. 닫히지 않은 태그는 보완하지 않습니다. - 값은 그대로 옮깁니다. 바뀌는 것은 속성 이름뿐이라
aria-label="class schedule"은aria-label="class schedule"그대로입니다. 예외는style(객체가 됨)과 텍스트로, 텍스트의{,},<,>는{,},<,>로 써서 React에는 원래 글자가 표시됩니다. - React 객체로 보존할 수 없는 스타일은 변환하지 않습니다.
style속성에!important, 같은 속성 중복(CSS 대체 값), CSS 주석, 이스케이프가 들어간 속성 이름, 닫히지 않은 따옴표나 괄호가 있으면 변환을 멈추고, 입력을 고칠 때까지 출력을 지우고 복사를 끕니다. - 한 번에 컴포넌트 하나.
{...props}는 첫 번째<svg>에만 붙습니다. 스프라이트는 아이콘 하나씩 붙여넣으세요. - 컴포넌트 이름: 영문자, 숫자,
_,$외의 문자는 지워지고 첫 글자는 대문자가 됩니다(plus-icon→Plusicon). 한글 이름은 모두 지워져MyIcon이 됩니다. data-*와aria-*속성은 하이픈을 유지합니다. React가 요구하는 방식입니다.
FAQ
SVG to JSX 변환기는 무엇을 하나요?
원시 SVG 파일을 재사용 가능한 React 컴포넌트로 변환합니다. 주요 변환 내용: 하이픈 속성을 카멜케이스로 변환(stroke-width → strokeWidth), class를 className으로 변경, xmlns 선언 제거, SVG 마크업을 함수 컴포넌트로 감쌉니다.
SVG 속성을 왜 변환하나요?
JSX는 JavaScript로 컴파일되며, 하이픈 속성명은 유효한 JS 식별자가 아닙니다. React는 strokeWidth, fillRule, clipPath 등 카멜케이스 형식을 요구합니다.
TypeScript 옵션은 무엇을 하나요?
활성화하면 React.FC<React.SVGProps<SVGSVGElement>> 타입이 적용되어 className, style, onClick 등 SVG 속성의 자동완성을 포함한 완전한 TypeScript 지원을 제공합니다.
forwardRef는 무엇에 사용하나요?
forwardRef를 사용하면 부모 컴포넌트가 SVG 요소에 ref를 전달할 수 있습니다. DOM 노드에 프로그래밍 방식으로 접근해야 할 때(크기 측정, 애니메이션 등) 유용합니다.
memo 래핑의 효과는 무엇인가요?
React.memo로 컴포넌트를 감싸면 props가 변경될 때만 리렌더링됩니다. 대부분의 렌더링에서 동일한 props를 받는 아이콘 컴포넌트의 성능 최적화에 효과적입니다.
서버로 데이터가 전송되나요?
아니요. 변환은 전적으로 브라우저의 JavaScript로 처리됩니다. SVG 데이터는 전송되지 않습니다.