Vite에서 SVG를 React 컴포넌트로 사용하기: vite-plugin-svgr

Natest·2024년 11월 26일

프로젝트를 진행하면서 SVG를 <img> 태그로 사용하는 것보다 컴포넌트화해서 사용하는 것이 더 편리하다고 생각했습니다. 이를 위해 SVG를 React 컴포넌트로 변환하는 방법을 찾았고, Vite에서 지원하는 vite-plugin-svgr라이브러리를 알게 되어 적용해 보았습니다.

설치

우선, 라이브러리를 설치합니다.

yarn add -D vite-plugin-svgr

Vite 설정 추가

설치 후, vite.config.js 파일에 플러그인을 설정합니다.

// vite.config.js
import svgr from "vite-plugin-svgr";

export default {
  // ...
  plugins: [
    svgr({
      include: "**/*.svg?react",
    }),
  ],
};

TypeScript 사용 시 추가 설정

TypeScript를 사용한다면, vite-env.d.ts 파일에 다음을 추가해야 합니다:

/// <reference types="vite-plugin-svgr/client" />

SVG 파일을 React 컴포넌트로 가져오기

React 컴포넌트로 사용하려면 아래와 같이 SVG를 import합니다:

import Logo from './logo.svg?react";

import { ReactComponent as Icon } 방식과의 차이점

리서치를 하면서 일부 문서에서 다음과 같은 방식도 추천하는 것을 보았습니다:

import { ReactComponent as Icon } from './icon.svg';

이 방식은 vite-plugin-svgr의 최신 버전 이전에 사용되던 방법입니다.
최신 버전에서는 공식 문서에 나온 대로 ?react를 붙여 사용하는 것을 권장하고 있습니다.

이 같은 과정을 마치고 이제 SVG를 컴포넌트로 사용하려고 했으나...

에러코드

[vite] Internal server error: Transform failed with 1 error:
C:/Users/Na/Desktop/Playground-Front/src/assets/svg/left-icon.svg?react:2:12: ERROR: Expected "from" but found "{"
  Expected "from" but found "{"
  1  |  import * as React from "react";
  2  |  import type { SVGProps } from "react";
     |              ^
  3  |  import { Ref, forwardRef } from "react";
  4  |  const SvgLeftIcon = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => <svg width="1em" height="1em" viewBox="0 0 9 16" fill="none" xmlns="http://www.w3.org/2000/svg" ref={ref} {...props}><path d="M8 15L1 8L8 1" stroke="#212529" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" /></svg>;

해당 화면처럼 오류가 뜨는 것이었습니다...

왜 이런 오류가 뜨는지 한참을 찾아봤는데 정말 제가 발생한 오류와는 똑같은 오류가 발생한 사람이 없는 것이었습니다.

그래서 새로운 Vite 프로젝트를 만들어 동일한 설정을 테스트했더니 SVG가 정상적으로 작동했습니다. 따라서, 현재 진행 중인 프로젝트의 설정과 관련된 문제임을 알게 되었습니다.

원인 분석

vite.config.ts에서 설정한 svgr 플러그인의 옵션 중 아래 설정이 문제가 되었습니다:

    svgr({
      svgrOptions: { icon: true, typescript: true, ref: true },
      include: '**/*.svg?react',
    }),

문제의 핵심은 typescript 옵션이었습니다. 이를 제거한 후 정상적으로 작동했습니다.

그래서 왜 이런일이 발생하였는가 찾아보았더니

typescript 옵션의 역할과 문제점

1. 역할

  • svgrOptions:{typescript: true}는 SVG를 TypeScript 컴포넌트로 변환할 때 타입 정보를 포함합니다.

2. 문제점

  • Vite는 ESM 기반 번들러로 TypeScript 타입 정보를 직접 처리하지 않습니다.
  • typescript: true는 타입 정의를 삽입하려 하지만, Vite는 이를 처리할 준비가 되어 있지 않아 에러가 발생합니다.

추가적인 원인

  • 플러그인 설정 간 충돌
    Vite의 플러그인 실행 순서에서 typescript?react 쿼리가 상호작용하며 충돌 가능성이 존재합니다.

해당 요인으로 인해 원인이 발생한 것이라고 추론할 수 있었습니다.

이 에러를 통해 프로젝트 설정을 과도하게 추가하면 충돌을 일으킬 가능성이 커진다는 것을 깨달았습니다. 앞으로는 필요한 최소한의 설정만 추가해야겠다고 생각해 볼 수 있었습니다.

profile
누군가에게 도움이 될 정보이기를

0개의 댓글