SVG를 React 컴포넌트로 변환, 뭐가 바뀌나

디자인 툴이나 아이콘 사이트에서 복사한 SVG 코드를 React·Next.js 컴포넌트 안에 그대로 붙여넣으면, 아이콘은 화면에 떠도 콘솔에는 stroke-widthclass 같은 속성에 대한 경고가 줄줄이 올라옵니다. 코드가 틀려서가 아니라, JSX가 속성 이름을 HTML·XML과 다른 규칙(카멜케이스)으로 읽기 때문입니다. 이 글은 그 차이를 규칙 표로 정리하고, 변환기가 실제로 무엇을 바꾸는지를 확인 가능한 사실만으로 설명합니다.

요약 ① JSX는 속성 이름을 카멜케이스로 읽어 classclassName, stroke-widthstrokeWidth처럼 바꿔야 경고가 사라집니다. ② 변환기는 여는 <svg> 태그 끝에 {...props}를 넣어, 호출부에서 className·fill·width·height를 넘겨 스타일을 제어하게 합니다. ③ 컴포넌트 이름은 영숫자가 아닌 문자가 전부 삭제되므로, '하트 아이콘'이 아니라 HeartIcon 같은 영문 파스칼케이스로 넣어야 합니다.

붙여넣으면 아이콘은 뜨는데 콘솔이 경고로 가득 찹니다

Figma에서 아이콘을 복사하거나 아이콘 사이트에서 SVG를 받아 .tsx 파일의 return 안에 그대로 붙여넣는 상황을 떠올려 보겠습니다. 화면에는 아이콘이 정상적으로 보입니다. 문제는 개발자 도구 콘솔입니다.

React 개발 모드는 이럴 때 대략 이런 형태의 경고를 냅니다.

Warning: Invalid DOM property `stroke-width`. Did you mean `strokeWidth`?
Warning: Invalid DOM property `class`. Did you mean `className`?

즉 React는 "이 속성 이름은 JSX에서 쓰는 이름이 아니다"라고 알려주면서 올바른 카멜케이스 이름까지 함께 제안합니다. 특히 CSS 클래스는 JSX에서 class가 아니라 className으로 지정하는 것이 표준이라, class="icon-heart"를 그대로 두면 경고와 함께 스타일이 의도대로 걸리지 않을 수 있습니다.

이 경고들은 하나씩 손으로 고칠 수 있습니다. 다만 아이콘 하나에 path가 여러 개이고 속성이 수십 개면, 어느 것이 카멜케이스 대상인지 매번 눈으로 찾는 일이 번거롭습니다. 규칙 자체는 단순하니 먼저 그 규칙부터 정리하겠습니다.

도구 없이 직접 변환하는 방법

이 변환은 전부 손으로 할 수 있습니다. 순서는 이렇습니다.

1단계 — 컴포넌트로 감쌉니다. SVG 마크업을 함수 컴포넌트가 반환(return)하도록 감쌉니다. 함수 이름은 반드시 대문자로 시작해야 합니다. JSX는 소문자로 시작하는 태그를 HTML 요소로, 대문자로 시작하는 태그를 컴포넌트로 구분하기 때문입니다.

2단계 — 하이픈 속성을 카멜케이스로 바꿉니다. 아래 표의 왼쪽을 오른쪽으로 바꿉니다. React가 콘솔에서 "Did you mean …?"으로 제안하는 이름이 바로 오른쪽입니다.

원본 SVG 속성JSX(React) 속성
classclassName
stroke-widthstrokeWidth
stroke-linecapstrokeLinecap
stroke-linejoinstrokeLinejoin
stroke-miterlimitstrokeMiterlimit
stroke-dasharraystrokeDasharray
stroke-dashoffsetstrokeDashoffset
stroke-opacitystrokeOpacity
fill-rulefillRule
fill-opacityfillOpacity
clip-ruleclipRule
stop-colorstopColor
stop-opacitystopOpacity
font-familyfontFamily
font-sizefontSize
font-weightfontWeight
xmlns:xlinkxmlnsXlink
xlink:hrefxlinkHref

3단계 — <?xml … ?> 선언과 주석을 지웁니다. SVG 파일 맨 앞의 XML 선언과 <!-- … --> 주석은 JSX 문법에서 그대로 쓸 수 없습니다. JSX 주석은 {/* … */} 형태라, HTML 주석을 남겨 두면 문법 오류가 납니다. 그래서 아예 지우는 편이 안전합니다.

4단계 — 인라인 style 문자열을 객체로 바꿉니다. style="color:red" 같은 문자열은 React에서 객체(style={{ color: "red" }})여야 합니다. 이건 이름만 바꾸는 게 아니라 형태 자체를 바꿔야 하는 부분입니다.

5단계 — 필요하면 {...props}를 답니다. 여는 <svg> 태그 끝에 {...props}를 넣으면, 이 컴포넌트를 쓸 때 className·fill·width·height 같은 값을 넘겨 바깥에서 스타일을 제어할 수 있습니다.

핵심 규칙은 2단계의 표 하나로 끝납니다. 다만 path가 많은 복잡한 아이콘일수록 손으로 빠뜨리기 쉽고, 그때마다 콘솔 경고를 보고 되돌아오는 일이 반복됩니다. 아래 변환기에 붙여넣으면 이 과정을 한 번에 확인할 수 있습니다.

SVG 아이콘을 React 컴포넌트(JSX)로 변환

회원가입 없이 브라우저에서 SVG를 붙여넣어 TypeScript React 컴포넌트로 변환합니다. 입력은 서버로 전송되지 않고 화면에서 바로 처리됩니다.

흔히 헷갈리는 부분

변환하지 않고 그냥 붙여넣기. 가장 흔한 경우입니다. 앞서 본 대로 stroke-width, class 같은 속성이 콘솔 경고를 부르고, 카멜케이스로 바꾸면 사라집니다. 이 변환기는 위 표의 18개 속성을 한 번에 바꿔 줍니다.

컴포넌트 이름 규칙. 변환기는 이름에서 영숫자가 아닌 문자를 전부 지웁니다(공백·하이픈·언더스코어·한글 모두 삭제). 그리고 첫 글자를 대문자로 바꿔 주지는 않습니다. 그래서 대문자로 시작하는 영문 파스칼케이스를 직접 넣어야 합니다.

입력한 이름실제 생성되는 이름
HeartIconHeartIcon
heart-iconhearticon
my_icon 2myicon2
하트 아이콘IconComponent

'하트 아이콘'처럼 한글과 공백만 넣으면 남는 글자가 없어 IconComponent로 대체됩니다. heart-icon처럼 소문자로 시작하면 하이픈만 빠진 hearticon이 되는데, 이렇게 소문자로 시작하는 이름은 JSX가 컴포넌트가 아닌 HTML 태그로 취급하므로 렌더링할 때 문제가 됩니다. 그래서 HeartIcon처럼 대문자로 시작해야 합니다.

{...props}가 붙는 위치. 변환기는 {...props}를 여는 <svg> 태그의 맨 끝에 넣습니다. 즉 원본 속성이 먼저 오고 {...props}가 뒤에 옵니다. JSX에서는 같은 이름이 겹치면 뒤에 있는 값이 이깁니다. 그래서 <HeartIcon fill="red" />처럼 넘기면 원본의 fill 값을 넘긴 값이 덮어씁니다. 반대로 아무것도 넘기지 않으면 원본 속성이 기본값으로 남습니다.

한 가지 더 있습니다. className을 넘기면 원본 class에서 변환된 className과 합쳐지는 게 아니라 통째로 대체됩니다. 원본 클래스를 유지하면서 클래스를 더하고 싶다면, 넘기는 className에 원본 클래스까지 함께 적어 주어야 합니다.

인라인 style 문자열. 이 변환기가 바꾸는 건 위 표의 속성 이름까지입니다. style="…" 같은 문자열은 그대로 남습니다. React는 style에 문자열이 아니라 객체를 요구하므로, 인라인 스타일이 들어 있는 SVG라면 그 부분은 직접 객체로 바꿔야 합니다.

정리

  • JSX는 속성 이름을 카멜케이스로 읽습니다. classclassName, stroke-widthstrokeWidth처럼 바꾸지 않으면 콘솔 경고가 뜹니다.
  • 규칙은 표 하나로 끝납니다. 변환기는 그 18개 하이픈·XML 속성을 한 번에 카멜케이스로 바꿔 줍니다.
  • 여는 <svg> 태그 끝에 {...props}가 붙어, 호출부에서 className·fill·width·height를 넘겨 스타일을 제어할 수 있습니다. 넘긴 값이 원본을 덮어씁니다.
  • 컴포넌트 이름은 영숫자만 남고, 첫 글자 대문자는 직접 넣어야 합니다. 한글·공백만 넣으면 IconComponent로 대체됩니다.
  • <?xml?> 선언과 주석은 JSX에서 쓸 수 없어 제거됩니다. 인라인 style 문자열은 별도로 객체로 바꿔야 합니다.
SVG 아이콘을 React 컴포넌트(JSX)로 변환

회원가입 없이 브라우저에서 SVG를 붙여넣어 TypeScript React 컴포넌트로 변환합니다. 입력은 서버로 전송되지 않고 화면에서 바로 처리됩니다.

자주 묻는 질문

SVG를 React에 그냥 붙여넣으면 왜 경고가 뜨나요?

JSX가 속성 이름을 HTML·XML의 하이픈 방식이 아니라 카멜케이스(예: strokeWidth)로 읽기 때문입니다. React 개발 모드는 stroke-width 같은 속성을 만나면 "Did you mean strokeWidth?" 형태로 올바른 이름을 제안합니다. 이름만 카멜케이스로 바꾸면 경고는 사라집니다.

컴포넌트 이름에 한글이나 공백을 넣어도 되나요?

넣으면 그 글자들은 전부 삭제됩니다. 변환기는 이름에서 영문자와 숫자만 남기기 때문에, '하트 아이콘'처럼 한글과 공백만 넣으면 남는 글자가 없어 IconComponent로 대체됩니다. HeartIcon처럼 대문자로 시작하는 영문 파스칼케이스로 넣는 것이 안전합니다.

변환한 컴포넌트에서 색이나 크기를 바꾸려면 어떻게 하나요?

변환된 컴포넌트는 여는 <svg> 태그에 {...props}가 붙어 있어, 쓸 때 값을 넘기면 됩니다. 예를 들어 <HeartIcon fill="red" width={48} className="my-icon" />처럼 넘기면 그 값이 원본 속성을 덮어씁니다. {...props}가 태그 끝에 있어 넘긴 값이 원본보다 뒤에 놓이기 때문입니다.

붙여넣을 SVG에 주석이나 XML 선언이 있어도 되나요?

괜찮습니다. 변환기가 <?xml … ?> 선언과 <!-- … --> 주석을 자동으로 지웁니다. 이 둘은 JSX 문법에서 그대로 둘 수 없어(주석은 {/* … */} 형태여야 함) 남겨 두면 오류가 나기 때문에, 변환 과정에서 제거됩니다.

가격 보기카톡 무료 상담