PromleeBlog
sitemapaboutMe

posting thumbnail
React Native(Expo)에서 SVG 이미지 사용하기 (react-native-svg-transformer)
Using SVG images in React Native(Expo) (react-native-svg-transformer)

📅

🚀

들어가기 전에🔗

이 글은 기본적인 Expo 프로젝트가 생성되어 있다고 가정합니다. Expo 프로젝트를 생성하는 방법은 Expo 프로젝트 생성:윈도우, Mac을 참고해주세요.

svg 이미지를 사용하는 이유🔗

이미지의 확장자는 여러가지가 있지만, SVG 이미지는 확장성이 좋아서 여러 크기로 확대해도 깨지지 않는 장점이 있습니다. 또한, SVG 이미지는 CSS로 스타일링이 가능하고, 파일 크기가 작아서 웹사이트의 성능을 향상시킬 수 있습니다. React Native에서도 SVG 이미지를 사용할 수 있습니다. 이 글에서는 React Native(Expo)에서 SVG 이미지를 사용하는 방법을 알아보겠습니다.

🚀

react-native-svg 라이브러리 설치🔗

👨‍💻
이 라이브러리는 Expo Go에 포함되어 있기 때문에 Expo 환경에서는 추가적인 설치를 진행하지 않아도 됩니다.
Expo가 아닌 React Native 프로젝트에서는 react-native-svg 라이브러리를 설치해야 합니다. 다음 명령어를 통해 라이브러리를 설치합니다.
npm install react-native-svg
react-native-svg를 사용하면 상호작용과 애니메이션을 지원하여 앱에서 SVG를 사용할 수 있습니다.

🚀

SVG 이미지 사용하기🔗

먼저 svg 이미지를 다운받습니다. svg 파일을 열면 svg 코드를 확인할 수 있습니다. svg 코드를 복사합니다. 다음 예시는 svg에서 지원하는 circle, line 태그를 사용한 코드입니다.
/assets/image/example.svg (예시 svg 파일)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
	<circle cx="12" cy="12" r="10"/>
	<line x1="12" y1="8" x2="12" y2="16"/>
	<line x1="8" y1="12" x2="16" y2="12"/>
</svg>
예시 svg 파일
예시 svg 파일
svg 코드를 복사한 후, Svg 컴포넌트를 사용하여 SVG 이미지를 사용할 수 있습니다. 이 때, Svg 컴포넌트는 react-native-svg 라이브러리에서 제공하는 컴포넌트입니다. Svg 컴포넌트 안에 Circle, Line 컴포넌트를 사용하여 svg 코드를 변환합니다. 다음은 svg 코드를 변환한 코드입니다.
/assets/image/example.tsx
import Svg, { Circle, Line } from 'react-native-svg';
 
export default function SvgComponent() {
	return (
		<Svg width="100" height="100" viewBox="0 0 24 24">
			<Circle cx="12" cy="12" r="10" fill="none" stroke="black" strokeWidth="2"/>
			<Line x1="12" y1="8" x2="12" y2="16" stroke="black" strokeWidth="2"/>
			<Line x1="8" y1="12" x2="16" y2="12" stroke="black" strokeWidth="2"/>
		</Svg>
	);
}
이제 SvgComponent 컴포넌트를 사용하여 SVG 이미지를 화면에 렌더링할 수 있습니다.
/app/index.tsx
import React from 'react';
import { View } from 'react-native';
import SvgComponent from './example';
 
export default function App() {
	return (
		<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
			<SvgComponent />
		</View>
	);
}

🚀

React SVGR 사이트에서 사용🔗

SVG 이미지를 컴포넌트로 변환해주는 사이트도 있습니다. React SVGR 사이트에서 SVG 코드를 붙여넣으면 React 컴포넌트로 변환해줍니다. 이 사이트를 사용하면 SVG 코드를 직접 작성하지 않고도 React 컴포넌트로 변환할 수 있습니다. 위 예시 코드를 React SVGR 사이트에서 변환한 코드는 다음과 같습니다.
/assets/image/example-svgr.tsx
import * as React from "react"
import Svg, { SvgProps, Circle, Path } from "react-native-svg"
const SvgComponent = (props: SvgProps) => (
  <Svg
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    stroke="currentColor"
    strokeLinecap="round"
    strokeLinejoin="round"
    strokeWidth={2}
    viewBox="0 0 24 24"
    {...props}
  >
    <Circle cx={12} cy={12} r={10} />
    <Path d="M12 8v8M8 12h8" />
  </Svg>
)
export default SvgComponent
수동 변환한 코드와 조금 다르죠???
이 사이트를 이용하여 변환 시에 SvgProps를 사용하여 props를 전달할 수 있습니다. 그렇기 때문에 저는 이 사이트를 사용하여 SVG 이미지를 컴포넌트로 변환하는 것을 추천합니다.

🚀

react-native-svg-transformer 사용하기🔗

하지만 매번 SVG 코드를 컴포넌트로 변환하는 것은 파일 확장자를 변경하는 등 번거로운 작업이 필요합니다. 이 때 react-native-svg-transformer 라이브러리를 사용하면 SVG 파일을 자동으로 컴포넌트로 변환할 수 있습니다.

설치 및 설정🔗

➡️

라이브러리 설치🔗

먼저 react-native-svg-transformer 라이브러리를 설치합니다.
npm install --save-dev react-native-svg-transformer
 
  # yarn add --dev react-native-svg-transformer
➡️

metro.config.js 설정 추가🔗

그 다음, 루트 폴더에 위치한 metro.config.js 파일을 수정하여 설정을 추가합니다. 일반 React Native 프로젝트에서는 metro.config.js 파일이 없을 수 있습니다. 이 때는 루트 폴더에 metro.config.js 파일을 생성하고 다음 설정을 추가합니다. module.exports 부분의 코드를 추가합니다.
metro.config.js (Expo 프로젝트 기준)
/* eslint-env node */
const { getDefaultConfig } = require('expo/metro-config');
 
/** @type {import('expo/metro-config').MetroConfig} */
 
module.exports = (() => {
	const config = getDefaultConfig(__dirname);
 
	const { transformer, resolver } = config;
 
	config.transformer = {
		...transformer,
		babelTransformerPath: require.resolve('react-native-svg-transformer/expo'),
	};
	config.resolver = {
		...resolver,
		assetExts: resolver.assetExts.filter((ext) => ext !== 'svg'),
		sourceExts: [...resolver.sourceExts, 'svg'],
	};
 
	return config;
})();
metro.config.js (React Native 프로젝트 기준)
const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
 
const defaultConfig = getDefaultConfig(__dirname);
const { assetExts, sourceExts } = defaultConfig.resolver;
 
/**
 * Metro configuration
 * https://reactnative.dev/docs/metro
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
  transformer: {
    babelTransformerPath: require.resolve(
      "react-native-svg-transformer/react-native"
    )
  },
  resolver: {
    assetExts: assetExts.filter((ext) => ext !== "svg"),
    sourceExts: [...sourceExts, "svg"]
  }
};
 
module.exports = mergeConfig(defaultConfig, config);
➡️

Typescript 설정 추가🔗

Typescript를 사용하는 경우, declarations.d.ts 파일에 다음 설정을 추가합니다. 이 설정은 Typescript에서 svg 파일을 모듈로 인식할 수 있도록 도와줍니다.
파일이 없다면, 루트 폴더에 declarations.d.ts 파일을 생성하고 다음 설정을 추가합니다.
declarations.d.ts
declare module '*.svg' {
  import React from 'react';
  import { SvgProps } from 'react-native-svg';
  const content: React.FC<SvgProps>;
  export default content;
}

SVG 이미지 사용하기🔗

이제 SVG 이미지를 직접 Import 하여 사용할 수 있습니다. assets 폴더에 SVG 파일을 추가하고, SVG 파일을 사용할 때는 파일 경로를 require 함수로 불러옵니다. 다음은 SVG 이미지를 사용하는 예시 코드입니다.
/app/index.tsx
import React from 'react';
import { View } from 'react-native';
import SvgComponent from '@/assets/image/example.svg';
 
export default function App() {
	return (
		<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
			<SvgComponent />
		</View>
	);
}

🚀

SVG 속성 props로 전달하기🔗

SVG 이미지의 속성을 props로 전달할 수 있습니다. 예를 들어, fill, stroke, strokeWidth 등의 속성을 props로 전달하여 SVG 이미지를 스타일링할 수 있습니다. 다음은 SVG 이미지의 속성을 props로 전달하는 예시 코드입니다. svg 코드의 fill 속성은 fill props로 전달하고, stroke 속성은 stroke props로 전달됩니다. 가변적인 색상을 전달받으려면 "currentColor"를 사용합니다.
/assets/image/example.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
	<circle cx="12" cy="12" r="10"/>
	<line x1="12" y1="8" x2="12" y2="16"/>
	<line x1="8" y1="12" x2="16" y2="12"/>
</svg>
이후 SVG 이미지를 사용할 때 props로 전달할 수 있습니다.
/app/index.tsx
import { View } from 'react-native';
import SvgComponent from '@/assets/image/example.svg';
 
export default function App() {
	return (
		<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
			<SvgComponent fill={'blue'} stroke={'green'} width={100} height={100} />
		</View>
	);
}
fill, stroke 속성 변경
fill, stroke 속성 변경
이외에도 width, height, viewBox 등의 속성을 props로 전달할 수 있습니다.

🚀

결론🔗

더 생각해 보기🔗

참고🔗