[React] CRA에서 Vite 마이그레이션 : 트러블슈팅

 

지난 포스팅에서 CRA에서 Vite로 마이그레이션 하는 방법을 다루었다.

이번 포스팅에서는 마이그레이션 하는 과정에서 발생한 문제와 이를 해결한 방법에 대해 소개하고자 한다.

 

01. SVG 컴포넌트 불러오기 실패

환경 설정을 완료하고 npm run dev로 프로젝트를 수행한 결과, 아무 화면 출력되지 않는 문제가 발생하였다.

개발자 도구에서 Network에는 필요한 파일들을 불러오고는 있었지만, 화면에는 아무것도 출력되지 않았다.

처음에 src/router 경로에 있는 라우터 파일의 경로가 잘못되었나 생각해서 같은 경로에 다른 파일을 생성해 <h1>Hello World</h1>와 같이 간단한 텍스트를 출력하도록 테스트 해보았는데, 텍스트는 정상적으로 출력되었다. 따라서 경로 문제는 아니었다.

 

이때 개발자 도구의 console에 다음과 같은 에러가 출력되었다.

HomeSearch.tsx:1 Uncaught SyntaxError: The requested module '/src/assets/icon/search.svg?import' does not provide an export named 'ReactComponent

 

SVG 파일을 ReactComponent로 불러오는 과정에서 오류가 발생한 것이다.

이 문제는 주로 SVG 파일을 React 컴포넌트로 사용하기 위한 설정이 제대로 되어있지 않아서 발생한다.

따라서 SVG를 React 컴포넌트로 사용하기 위해 올바른 방법으로 SVG를 불러오는 설정을 해줘야 한다.

 

npm install --save-dev vite-plugin-svgr

해당 명령어를 통해 vite-plugin-svgr은 설치를 완료한 상태였다.

import svgrPlugin from "vite-plugin-svgr";

export default defineConfig({
  plugins: [react(), tsconfigPaths(), svgrPlugin()],
});

또한 vite.config.ts에서 plugins에 svgrPlugin() 코드도 추가하여 설정을 완료하였지만 여전히 같은 오류가 발생하였다.

 

 

이전 CRA를 사용하였을 때 SVG 파일을 컴포넌트로 사용하기 위해 다음과 같이 코드를 작성하였었다.

import { ReactComponent as Logo } from "@/assets/icon/logo.svg";

<Logo />

하지만 이 방법은 vite-plugin-svgr의 버전 v4.0.0 이전에 사용하던 방식이었으며, 해당 프로젝트에서 vite-plugin-svgr 버전은 v4.2.0 이었다. 

 

 

✅ vite-plugin-svgr v4.0.0 이후에 맞게 변경하여 해결

import Logo from "@/assets/icon/logo.svg?react";

<Logo />

v4.0.0 이후 버전에 맞게 ReactComponent as를 제외하고 ?react를 추가하도록 svg 파일 import 방식을 모두 수정하였다.

그 후 프로젝트를 수행한 결과 웹브라우저에 화면이 정상적으로 출력되는 것을 확인할 수 있었다.

 

 

 

 

 

02. Vite에서 require 사용 안되는 문제

CRA에서 assets에 있는 .png, .jpg와 같은 이미지를 불러올 때 다음과 같이 require를 이용하였다.

<img src={require("../../assets/img/Group 79.png")} alt="img" />

 

하지만, require는 CommonJS 모듈 시스템에서 사용되며, 이는 주로 Node.js 환경에서 사용되었다. 하지만 브라우저에서는 ES Modules (ESM)을 사용하기 때문에 require를 사용할 수 없었다.

 

 

✅ require 대신 import를 사용해 해결

import Group79 from "../../assets/img/Group 79.png";

const HomeIntroduce = () => {
  return (
    <>
      <img src={Group79} alt="Group 79" />
    </>
  );
};

export default HomeIntroduce;

위 코드와 같이 require 대신 import로 이미지를 불러오는 방법을 통해 해결할 수 있었다.

 

 

 

 

 

03. process.env 작동 안됨

이전 CRA에서 api 주소를 .env 파일에 두고 process.env로 호출하여 관리하였다.

하지만 Vite로 마이그레이션 한 이후 다음과 같은 오류가 발생하였다.

postData.tsx:3 Uncaught ReferenceError: process is not defined
    at postData.tsx:3:22

 

process 변수를 사용하려고 했지만, 브라우저 환경에서 process가 정의되지 않았기 때문에 발생하는 오류였다. process는 Node.js 환경에서만 기본적으로 제공되는 전역 변수이며, 브라우저 환경에서는 사용할 수 없었다. 즉, Vite에서는 process.env를 사용할 수 없었다.

 

 

✅ import.meta.env를 사용하여 해결(모든 환경 변수는 VITE_ 접두사 붙여야 함)

Vite에서는 환경 변수를 사용하기 위해 import.meta.env를 사용한다.

process.env 대신 import.meta.env로 변경하면 이 문제를 해결할 수 있었다.

const apiUrl = process.env.API_URL;

CRA에서 위와 같이 코드가 작성되어 있었다. Vite에서는 아래와 같이 변경해야 한다.

const apiUrl = import.meta.env.VITE_API_URL;

 

Vite에서 환경 변수를 사용하려면 .env 파일에 변수를 설정하고, 모든 환경 변수는 VITE_ 접두사를 붙여야 브라우저에서 접근할 수 있다.

예를 들어, .env 파일에 다음과 같이 환경 변수를 정의해야 한다.

VITE_API_URL=https://api.example.com

 

 

 

 

 

04. Github Actions Deploy 실패

앞선 오류를 모두 해결하고 배포를 위해 github repository에 merge를 하였다.

하지만 GitHub Actions에서 AWS S3로 파일을 업로드하려고 할 때, build 경로가 존재하지 않아서 다음과 같은 문제가 발생하며 배포되지 않았다.

Run aws s3 cp \

The user-provided path build does not exist.
Error: Process completed with exit code 255.

 

문제는 현재 작성된 GitHub Actions에서 잘못된 부분은 CRA에서 Vite로 변경된 후에도 여전히 build 폴더를 참조하고 있어서 문제가 발생하였다. Vite는 기본적으로 빌드 결과물을 dist 폴더에 생성하므로, 경로를 수정 및 workflow를 수정해야 했다.

 

 

✅ build를 dist로 변경하여 해결

현재 aws s3 cp 명령어에서 build를 참조하고 있는데, Vite에서는 기본적으로 dist 폴더에 빌드 결과물이 생성된다.

따라서, build를 dist로 변경해야 한다.

 

.github/workflows의 .yml은 아래와 같이 수정하여 해결하였다. 

name: MajorIn

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source code. # 레포지토리 체크아웃
        uses: actions/checkout@v4

      - name: Cache node modules # node modules 캐싱
        uses: actions/cache@v4
        with:
          path: node_modules
          key: ${{ runner.OS }}-build-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.OS }}-build-
            ${{ runner.OS }}-

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: "18.20.4"

      - name: .env setting
        run: |
          echo "VITE_APP_SERVER_URL=${{ secrets.VITE_APP_SERVER_URL }}" >> .env
          echo "VITE_APP_AI_URL=${{ secrets.VITE_APP_AI_URL }}" >> .env

      - name: Install Dependencies # 의존 파일 설치
        run: npm install

      - name: Update Browserslist DB
        run: npx update-browserslist-db@latest

      - name: Build # Vite Build
        env:
          CI: false # 경고를 오류로 처리하지 않도록 설정
        run: npm run build

      - name: Deploy # S3에 배포하기
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        run: |
          aws s3 sync \
            --delete \
            --region ap-northeast-2 \
            dist/ s3://majorin

 

수정사항은 다음과 같다.

 

  • aws s3 sync 사용: aws s3 cp 대신 aws s3 sync를 사용하여 로컬 dist 폴더와 S3 버킷 간의 동기화를 처리. --delete 플래그는 S3 버킷에서 로컬 디렉토리와 동기화되지 않은 파일을 삭제.
  • dist 폴더 참조: build를 dist로 수정하여 Vite의 빌드 출력 경로에 맞게 설정.

 

반응형