개발/오늘 배운 지식

[React Native, TypeScript] svg 파일을 타입스크립트에서 사용하기

Woogie2 2021. 10. 24. 01:54
반응형

react-native-svg

오늘 리액트 네이티브 개발을 하던 중, 아이콘을 앱에 넣어야하는 상황이 있었다.

앱 디자인은 이미 피그마로 해두었기에, 피그마에서 svg로 export한 아이콘을 앱에 넣는 방법을 알아보았다.

아직 프로젝트 초창기이기 때문에, 관련 세팅이 필요했다.

이번 프로젝트에서는 react-native-svg를 사용하였다.

react-native-svg 설치

1. npm 혹은 yarn으로 라이브러리 설치

yarn add react-native-svg

2. React native와 autolink하기(RN 버전 0.60 이상부터 가능)

cd ios && pod install

0.60 이하의 버전인 경우
react-native link react-native-svg 커멘드를 터미널에 입력하면 된다.

3. react-native-svg-transformer 설치하기

yarn add --dev react-native-svg-transformer

react-native-svg-transformer

4. 리액트 네이티브 packer 관련 설정하기.

metro.config.js 파일을 아래와 같이 변경한다.

엑스포(expo)를 사용하는 경우

// expo v40:
const { getDefaultConfig } = require("@expo/metro-config");

// expo v41: 
// remove the @ (see: https://blog.expo.io/expo-sdk-41-12cc5232f2ef)
const { getDefaultConfig } = require("expo/metro-config");

module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts }
  } = await getDefaultConfig(__dirname);
  return {
    transformer: {
      babelTransformerPath: require.resolve("react-native-svg-transformer")
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== "svg"),
      sourceExts: [...sourceExts, "svg"]
    }
  };
})();

react-native CLI를 이용하는 경우(0.57+) / Expo SDK v31+

metro.config.js 파일을 아래와 같이 변경한다.

const { getDefaultConfig } = require("metro-config");

module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts }
  } = await getDefaultConfig();
  return {
    transformer: {
      babelTransformerPath: require.resolve("react-native-svg-transformer")
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== "svg"),
      sourceExts: [...sourceExts, "svg"]
    }
  };
})();

엑스포를 사용하는 경우 app.json도 아래와 같이 바꾼다.

{
  "expo": {
    "packagerOpts": {
      "config": "metro.config.js",
      "sourceExts": [
        "expo.ts",
        "expo.tsx",
        "expo.js",
        "expo.jsx",
        "ts",
        "tsx",
        "js",
        "jsx",
        "json",
        "wasm",
        "svg"
      ]
    }
  }
}

이외에 RN버전이 0.56아래인 경우 링크 참조

5. 타입스크립트 관련 설정

프로젝트 루트 경로에 declarations.d.ts파일을 만들고 아래의 코드를 저장하기.'

declare module "*.svg" {
  import React from 'react';
  import { SvgProps } from "react-native-svg";
  const content: React.FC<SvgProps>;
  export default content;
}

6. Figma(피그마)에서 copy as SVG로 아이콘 복사

복사한 svg 코드

<svg width="24" height="20" viewBox="0 0 24 20" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M22.5262 1.05885L1.79837 0.921692L10.7872 7.83638M22.5262 1.05885L10.7872 7.83638M22.5262 1.05885L12.2811 19.0783L10.7872 7.83638" stroke="black" stroke-width="1.80155" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

7. 복사한 svg파일의 코드를 tsx 바꿔서 저장하기.

tsx로 변환한 코드. svg, path 등의 태그를 react-native-svg의 대문자로 시작하는 컴포넌트로 바꿔주는 것이 핵심이다.

darkMode는 임의로 추가한 부분입니다.

import React from 'react'
import Svg, { Path } from 'react-native-svg'
interface Props {
  darkMode: boolean
}
function PaperPlane({ darkMode }: Props) {
  return (
    <Svg width="24" height="24" viewBox="0 0 24 20" fill="none">
      <Path
        d="M22.5262 1.05885L1.79837 0.921692L10.7872 7.83638M22.5262 1.05885L10.7872 7.83638M22.5262 1.05885L12.2811 19.0783L10.7872 7.83638"
        stroke={darkMode ? '#fff' : '#000'}
        stroke-width="2"
        stroke-linecap="round"
        stroke-linejoin="round"
      />
    </Svg>
  )
}

export default PaperPlane

8. svg 파일을 사용할 곳에서 아래와 같이 임포트하여 사용하면 된다.

import PaperPlane from './PaperPlane'

...
<PaperPlane darkmode={false} />
...

 

반응형