๐Ÿ’ป์šฉ๋‡ฝ ๊ฐœ๋ฐœ ๋…ธํŠธ๐Ÿ’ป
article thumbnail
๋ฐ˜์‘ํ˜•

[React] CRA์—์„œ Vite๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ณผ์ • ๋ฐ ์ฝ”๋“œ ๊ฐœ์„ 

1. ๐Ÿ“–  ๋“ค์–ด๊ฐ€๋ฉฐ

์ตœ๊ทผ ํšŒ์‚ฌ์—์„œ ๋‹ด๋‹นํ•˜๋Š” ์„œ๋น„์Šค์— ๋Œ€ํ•ด์„œ CRA์—์„œ Vite๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ํ•˜๋ฉด์„œ ์•ฝ๊ฐ„์˜ ์ฝ”๋“œ ๊ฐœ์„ ๊นŒ์ง€ ์ง„ํ–‰์„ ํ•˜๋Š” ๊ฒฝํ—˜์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๊ฐ€ ์ž‘์€ ํŽธ์ด ์•„๋‹ˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ํ•˜๋ฉด์„œ webpack์— ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ๋“ฑ์˜ ์‚ฌ์ด๋“œ์ดํŽ™ํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ถ€๋ถ„์—์„œ ์ œ์ผ ๊ฑฑ์ •์„ ๋งŽ์ด ํ–ˆ๋Š”๋ฐ์š”.

 

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ํฌ๊ฒŒ ์™œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ง„ํ–‰ํ–ˆ๋Š”์ง€, CRA์™€ Vite๋Š” ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€ ์–ด๋–ป๊ฒŒ ์ง„ํ–‰ํ–ˆ๋Š”์ง€, ์–ด๋–ค ๊ฒฐ๊ณผ๊ฐ€ ์žˆ์—ˆ๋Š”์ง€ ๊ธฐ๋กํ•˜๋ ค ํ•ฉ๋‹ˆ๋‹ค.

2. โ‰๏ธ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์˜ ํ•„์š”์„ฑ

ํ˜„์žฌ ๋‹ด๋‹นํ•œ ์„œ๋น„์Šค๋Š” webpack ๊ธฐ๋ฐ˜์˜ CRA๋กœ ๊ตฌ์„ฑ๋œ ํ”„๋กœ์ ํŠธ์˜€์Šต๋‹ˆ๋‹ค.

 

์ฒซ ๋ฒˆ์งธ, ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๊ฐœ๋ฐœ ์„œ๋ฒ„ ๊ตฌ๋™์‹œ๊ฐ„์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ๋™๋˜๋Š” ์‹œ๊ฐ„๊นŒ์ง€ ํ‰๊ท  ์•ฝ 20์ดˆ๊ฐ€ ์†Œ์š”๋˜๊ณ  ์ตœ๋Œ€ ์•ฝ 30์ดˆ๊นŒ์ง€ ์†Œ์š”๋˜๋Š” ์ƒํ™ฉ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

 

๋‘ ๋ฒˆ์งธ, ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๋นŒ๋“œ ์‹œ๊ฐ„์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฐฐํฌ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด ๋นŒ๋“œ๋˜๋Š” ์‹œ๊ฐ„์€ ํ‰๊ท  ์•ฝ 26์ดˆ๊ฐ€ ์†Œ์š”๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

์„ธ ๋ฒˆ์งธ, ์œ„์™€ ๊ฐ™์€ ์ด์œ ๋กœ ์ธํ•ด์„œ React ํŒ€์—์„œ ๋” ์ด์ƒ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š” ๋ถ„์œ„๊ธฐ์ž…๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ ๊ณต์‹๋ฌธ์„œ ์ค‘ ์ผ๋ถ€ ๋ฐœ์ทŒ
๋ฆฌ์•กํŠธ ๊ณต์‹ ๊นƒํ—ˆ๋ธŒ PR ๋ฐœ์ทŒ

3. CRA(webpack) vs Vite(rollup, esbuild)

๋จผ์ € webpack, rollup, esbuild์˜ ์—ญํ• ์€ ๋ฒˆ๋“ค๋Ÿฌ์ž…๋‹ˆ๋‹ค.

 

๋ฒˆ๋“ค๋Ÿฌ์˜ ์—ญํ• ์— ๋Œ€ํ•ด์„œ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒ์ผ๋“ค์„ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ๋ฌถ์–ด์ฃผ๋Š” ๋„๊ตฌ
  • ๋” ์ž‘์€ ์šฉ๋Ÿ‰, ๋” ์ตœ์ ํ™”๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณต
  • ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด์„œ ์ œ๊ฑฐ

๊ทธ๋ž˜์„œ, CRA๋Š” webpack์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ์ด ๋˜์—ˆ๊ณ , Vite๋Š” rollup๊ณผ esbuild๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

CRA vs Vite

3.1. CRA(webpack)

create-react-app

CRA์˜ ํŠน์ง•์€ ๊ฐ„๋‹จํ•˜๊ฒŒ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Facebook์—์„œ ๋งŒ๋“  React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ฒ˜์Œ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“  boilerplate
  • webpack ๊ธฐ๋ฐ˜: ์•ˆ์ •์ ์ด๊ณ  ๊ฒ€์ฆ๋œ ๋นŒ๋“œ ๋„๊ตฌ ์‚ฌ์šฉ
  • ์ œ๋กœ ์„ค์ •: ๋ณต์žกํ•œ ์„ค์ • ์—†์ด ๋ฐ”๋กœ ๊ฐœ๋ฐœ ์‹œ์ž‘ ๊ฐ€๋Šฅ
  • ํฐ ์ƒํƒœ๊ณ„: ๋งŽ์€ ์‚ฌ์šฉ์ž์™€ ํ’๋ถ€ํ•œ ๋ฆฌ์†Œ์Šค

์œ„์™€ ๊ฐ™์€ ํŠน์ง•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

์—ญ์‚ฌ๊ฐ€ ์ƒ๋Œ€์ ์œผ๋กœ ์˜ค๋ž˜๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฐธ๊ณ ํ•  ๋งŒํ•œ ์ž๋ฃŒ๊ฐ€ ํ’๋ถ€ํ•˜๊ณ , ๋Œ€๋ถ€๋ถ„์˜ ์„ค์ •์ด ๋˜์–ด์žˆ์–ด ํŽธํ•˜๋‹ค๋ฉด ํŽธํ•˜์ง€๋งŒ ๋ฐ˜๋Œ€๋กœ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” eject๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  CRA(webpack)์€ ๋ฒˆ๋“ค ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœ ์„œ๋ฒ„๊ฐ€ ๊ตฌ๋™์ด ๋ฉ๋‹ˆ๋‹ค.

๋ฒˆ๋“ค ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ ์„œ๋ฒ„

์ง„์ž…์ ์—์„œ ๊ฐ ๊ฒฝ๋กœ๋“ค์„ ํƒ์ƒ‰ํ•˜๊ณ  ๊ฒฝ๋กœ๋“ค์— ๋Œ€ํ•œ ๋ชจ๋“ˆ์„ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ๋ฒˆ๋“ค๋ง์ด ๋œ ๊ฒฐ๊ณผ๋ฌผ์„ ํ†ตํ•ด ๊ฐœ๋ฐœ ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘์ด ๋ฉ๋‹ˆ๋‹ค.

3.2. Vite(rollup, esbuild)

vite

Vite์˜ ํŠน์ง•์€  ๊ฐ„๋‹จํ•˜๊ฒŒ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Vue.js์˜ ์ฐฝ์‹œ์ž์ธ Evan You๊ฐ€ ๋งŒ๋“  Frontend build tool
  • native ES moules ๊ธฐ๋ฐ˜์˜ ๊ฐ•๋ ฅํ•œ ๊ฐœ๋ฐœ ์„œ๋ฒ„
  • esbuild๋กœ ์„ฑ๋Šฅ์„ ๊ทน์ ์œผ๋กœ ๋Œ์–ด์˜ค๊ณ , rollup์„ ํ†ตํ•œ ๋ฒˆ๋“ค๋ง์˜ ์œ ์—ฐ์„ฑ์„ ์ฑ™๊น€

Vite๋Š” CRA์™€ ๋‹ค๋ฅด๊ฒŒ ES module์„ ํ†ตํ•œ ๊ฐœ๋ฐœ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๊ณ , ์ด๋กœ ์ธํ•ด์„œ ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹œ์ž‘ ์†๋„๊ฐ€ ์ƒ๋Œ€์ ์œผ๋กœ ๋งค์šฐ ๋น ๋ฆ…๋‹ˆ๋‹ค.

์ดˆ๊ธฐ ์„ค์ • ๋˜ํ•œ CRA์™€ ๋‹ค๋ฅด๊ฒŒ ์ตœ์†Œํ•œ์˜ ์„ค์ •์ด ๋˜์–ด ์žˆ๊ณ  ์ปค์Šคํ„ฐ๋งˆ์ด์ง•๋„ ์œ ์—ฐํ•˜์ง€๋งŒ ์ถ”๊ฐ€ ์„ค์ •์„ ํ•˜๊ธฐ ์œ„ํ•œ ์ถ”๊ฐ€์ ์ธ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํ˜„์žฌ ๋ฉ”์ด์ € 5 ๋ฒ„์ „๊นŒ์ง€ ๋‚˜์˜ฌ ์ •๋„๋กœ ๋งค์šฐ ํ™œ๋ฐœํ•˜๊ฒŒ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

Vite๋Š” ์•ž์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ESM ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ๊ตฌ๋™ํ•ฉ๋‹ˆ๋‹ค. 

ESM ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ ์„œ๋ฒ„

๋จผ์ € ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋˜๋ฉด HTTP ์š”์ฒญ์„ ๋ณด๋‚ด ์ง„์ž…์ ‘์œผ๋กœ ๋“ค์–ด๊ฐ€๊ณ , ํ•„์š”ํ•œ ๊ฒฝ๋กœ์— ๋Œ€ํ•œ ๋ชจ๋“ˆ๋“ค๋งŒ ๋ถˆ๋Ÿฌ์™€์„œ ๋น ๋ฅด๊ฒŒ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฒˆ๋“ค ๊ธฐ๋ฐ˜์€ ๋ชจ๋“  ๊ฒฝ๋กœ์— ๋Œ€ํ•ด์„œ ๋ฒˆ๋“ค์„ ํ•˜๊ณ  ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ,
ESM ๊ธฐ๋ฐ˜์€ ํ•„์š”ํ•œ ๊ฒฝ๋กœ๋“ค์— ๋Œ€ํ•ด์„œ๋งŒ  HTTP ์š”์ฒญ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

ํ‘œ๋กœ ์ •๋ฆฌํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํŠน์ง• CRA Vite
๋นŒ๋“œ ๋„๊ตฌ webpack Rollup(ํ”„๋กœ๋•์…˜)
๊ฐœ๋ฐœ ์„œ๋ฒ„ webpack Dev Server Native ESM + esbuild
์ดˆ๊ธฐ ์„ค์ • ๋ฏธ๋ฆฌ ๊ตฌ์„ฑ๋จ ์ตœ์†Œํ•œ์˜ ์„ค์ •
๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹œ์ž‘ ์†๋„ ๋Š๋ฆผ ๋งค์šฐ ๋น ๋ฆ„
์ปค์Šคํ„ฐ๋งˆ์ด์ง• eject ํ•„์š” ๋˜๋Š” ๋ณต์žก ๊ฐ„๋‹จํ•˜๊ณ  ์œ ์—ฐํ•จ
SSR ์ถ”๊ฐ€ ์„ค์ • ํ•„์š” ๊ธฐ๋ณธ ์ง€์›
๋ ˆ๊ฑฐ์‹œ ๋ธŒ๋ผ์šฐ์ € ์ง€์› ์ข‹์Œ ์ œํ•œ์ (์ถ”๊ฐ€ ์„ค์ • ํ•„์š”)

4. ๐Ÿค” ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ณผ์ •

4.1. Vite ์„ค์น˜

ํ”„๋กœ์ ํŠธ์— Vite๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

<shell />
yarn add -D vite @vitejs/plugin-react

4.2. package.json ์ˆ˜์ •

์ด์ œ๋Š” vite๋กœ ๊ตฌ๋™๋  ์ˆ˜ ์žˆ๊ฒŒ๋” ๋งž๊ฒŒ ์ˆ˜์ •ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด์ „
ํ›„

4.3. vite.config.ts ์ถ”๊ฐ€

์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ํ•„์š”ํ•œ ์ฝ”๋“œ๋“ค์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ๋Š” ๋” ๋งŽ์€ ์„ค์ •์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. (svg, md, ๋นŒ๋“œ ํŒŒ์ผ ํ•ด์‹œ, ํด๋ฆฌํ•„ ๋“ฑ)

<javascript />
import react from '@vitejs/plugin-react'; import fs from 'fs'; import path from 'path'; import { defineConfig } from 'vite'; // https://vitejs.dev/config/ export default defineConfig(({ mode }) => { return { plugins: [ react(), ], ... });

4.4. tsconfig.json ์ถ”๊ฐ€

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ vite์— ๋Œ€ํ•ด์„œ ์ธ์‹ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

4.5. index.html ์ˆ˜์ • ๋ฐ %PUBLIC_URL% ์ œ๊ฑฐ

์ถ”๊ฐ€์ ์ธ ๋ฒˆ๋“ค๋ง ๊ณผ์ • ์—†์ด index.html ํŒŒ์ผ์ด ์•ฑ์˜ ์ง„์ž…์ ์ด ๋˜๊ฒŒ๋” ํ•˜๊ธฐ ์œ„ํ•œ ์ž‘์—…์ž…๋‹ˆ๋‹ค.

4.6. EVN ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •

vite-env.d.ts ํŒŒ์ผ์— ํ•„์š”ํ•œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ํƒ€์ž…์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

<typescript />
/// <reference types="vite/client" /> /// <referencetypes="vite-plugin-svgr/client" /> interface ImportMetaEnv { readonly VITE_SKIP_PREFLIGHT_CHECK: string; readonly VITE_REACT_APP_VERSION: string; readonly VITE_ALPHA_PUBLIC_KEY: string; readonly VITE_PROD_PUBLIC_KEY: string; } interface ImportMeta { readonly env: ImportMetaEnv; }

4.7. CommonJS -> ES Module

๊ธฐ์กด ์ฝ”๋“œ์—์„œ CJS ๋ฌธ๋ฒ•์œผ๋กœ ๋˜์–ด์žˆ๋Š” ๋ถ€๋ถ„๋“ค์„ ์ฐพ์•„์„œ ESM ๋ฌธ๋ฒ•์œผ๋กœ ๋ณ€๊ฒฝํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

CJS
ESM
ESM

5. ๐Ÿ’ก ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

Vite์— ํ•„์š”ํ•œ ์„ค์น˜ ๋ฐ ์„ค์ •์„ ํ•ด์ค€ ๋’ค์— CRA ํ™˜๊ฒฝ์—์„œ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์ง€๋งŒ Vite ํ™˜๊ฒฝ์—์„œ๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ๋“ค์ด์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ฃผ์š” ์ƒํ™ฉ๋“ค์— ๋Œ€ํ•ด์„œ ์ƒํ™ฉ, ์›์ธ, ํ•ด๊ฒฐ 3๊ฐ€์ง€ ์„น์…˜์œผ๋กœ ์ •๋ฆฌํ•ด ๋ดค์Šต๋‹ˆ๋‹ค.

5.1. ๋งˆํฌ๋‹ค์šด(.md)ํŒŒ์ผ import ์ด์Šˆ ๋ฐœ์ƒ

5.1.1. ์ƒํ™ฉ

.mdํŒŒ์ผ์— ๋Œ€ํ•ด์„œ import ํ•˜๋Š”๋ฐ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜์—ฌ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

5.1.2. ์›์ธ

Vite๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ตœ์†Œํ•œ์˜ ํŒŒ์ผ๋งŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

CRA์—์„œ๋Š” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „์— ๋ณ„๋‹ค๋ฅธ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

5.1.3. ํ•ด๊ฒฐ

vite.config.ts ํŒŒ์ผ์— ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

.md ํ™•์žฅ์ž๋ฅผ ๊ฐ€์ง„ ๋ชจ๋“  ํŒŒ์ผ์„ ์ •์  ์ž์‚ฐ(static asset)์œผ๋กœ ์ฒ˜๋ฆฌ ํ•˜๋ ค๊ณ  ์ง€์‹œํ•˜๋Š” ๋ฌธ๋ฒ•์ž…๋‹ˆ๋‹ค.

.md ํŒŒ์ผ์„ import ํ•  ๋•Œ Vite๊ฐ€ ์ด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

https://stackoverflow.com/questions/73459654/import-markdown-files-dynamically-with-vite

 

Import markdown files dynamically with Vite

I'm looking for a solution that lets me render markdown dynamically, based on the query string. At the moment I render markdown like this, in React + Vite: import some other stuff... import { usePa...

stackoverflow.com

5.2. pdfjs-dist ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ด€๋ จ ์ด์Šˆ ๋ฐœ์ƒ

5.2.1. ์ƒํ™ฉ

์ €ํฌ ์„œ๋น„์Šค์—๋Š” ์ƒ๋Œ€๋ฐฉ์—๊ฒŒ ๋ฌธ์„œ์— ๋Œ€ํ•œ ํ™”๋ฉด ๊ณต์œ ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ Vite๋กœ ์ „ํ™˜ํ•œ ๋’ค PDF ๋ฌธ์„œ์— ๋Œ€ํ•ด์„œ ํ™”๋ฉด์„ ๊ณต์œ ๋ฅผ ์‹œ์ž‘ํ•  ์‹œ ์œ„์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. 

5.2.2. ์›์ธ

CRA๋Š” ์›นํŒฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ์›นํŒฉ์€ PDF.js์˜ worker ํŒŒ์ผ์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋ฒˆ๋“ค๋ง ํ•ฉ๋‹ˆ๋‹ค.

Vite๋Š” ESM์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ํ”„๋กœ์„ธ์Šค๊ฐ€ CRA/webpack๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

5.2.3. ํ•ด๊ฒฐ

GlobalWorkerOption์— ๋Œ€ํ•ด ๋ช…์‹œ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

https://github.com/mozilla/pdf.js/issues/10478

 

No "GlobalWorkerOptions.workerSrc" specified. ยท Issue #10478 ยท mozilla/pdf.js

if (!fallbackWorkerSrc && typeof document !== 'undefined') { var pdfjsFilePath = document.currentScript && document.currentScript.src; if (pdfjsFilePath) { fallbackWorkerSrc = pdfjsFilePath.replace...

github.com

5.3. mediapipe ํ˜ธํ™˜ ์ด์Šˆ

5.3.1. ์ƒํ™ฉ

๊ธฐ๋Šฅ ์ค‘์— ์นด๋ฉ”๋ผ ํ™”๋ฉด์— ๋Œ€ํ•ด์„œ ์‚ฌ์šฉ์ž ์–ผ๊ตด ์ค‘์•™ ๋งž์ถ”๊ธฐ ๊ธฐ๋Šฅ์ด ์กด์žฌํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์œ„์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์‹ ๊ธฐํ•˜๊ฒŒ๋„ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” ๋™์ž‘์€ ๋˜์—ˆ์œผ๋‚˜, ๋ฐฐํฌ ํ™˜๊ฒฝ(preview)์—์„œ๋งŒ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

5.3.2. ์›์ธ

์ €ํฌ ์‚ฌ๋‚ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‚ด์—์„œ mediapipe ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

mediapipe ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ชจ๋“ˆ์ด CJS ๋™์  ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ESM์˜ ์ •์  ๋ถ„์„๊ณผ ํ˜ธํ™˜์ด ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ํŒŒ์•…ํ–ˆ์Šต๋‹ˆ๋‹ค.

mediapipe ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํŠน์ • ๋‚ด๋ณด๋‚ด๊ธฐ ๋ฐฉ์‹์ด esbuild์—์„œ๋Š” ๋ฌธ์ œ์—†์ด ์ฒ˜๋ฆฌ๋˜์—ˆ์ง€๋งŒ, rollup์˜ ๋” ์—„๊ฒฉํ•œ ์ฒ˜๋ฆฌ ๊ณผ์ •์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์œผ๋กœ ๋ถ„์„ํ–ˆ์Šต๋‹ˆ๋‹ค.

5.3.3. ํ•ด๊ฒฐ

vite-plugin-mediapipe.ts ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด ์คฌ์Šต๋‹ˆ๋‹ค.

<typescript />
// vite-plugin-mediapipe.ts import { PluginOption } from 'vite'; import path from 'path'; import fs from 'fs'; /** * MediaPipe ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ESM ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ Vite ํ”Œ๋Ÿฌ๊ทธ์ธ */ export const mediapipe = (config?: Record<string, string[]>): PluginOption => ({ name: 'mediapipe', load(id) { const MEDIAPIPE_EXPORT_NAMES: Record<string, string[]> = { 'camera_utils.js': ['Camera'], 'drawing_utils.js': ['clamp', 'drawLandmarks', 'drawConnectors', 'drawRectangle', 'lerp'], 'holistic.js': [ 'Holistic', 'FACE_GEOMETRY', 'FACEMESH_LIPS', 'FACEMESH_LEFT_EYE', 'FACEMESH_LEFT_EYEBROW', 'FACEMESH_LEFT_IRIS', 'FACEMESH_RIGHT_EYE', 'FACEMESH_RIGHT_EYEBROW', 'FACEMESH_RIGHT_IRIS', 'FACEMESH_FACE_OVAL', 'FACEMESH_CONTOURS', 'FACEMESH_TESSELATION', 'HAND_CONNECTIONS', 'POSE_CONNECTIONS', 'POSE_LANDMARKS', 'POSE_LANDMARKS_LEFT', 'POSE_LANDMARKS_RIGHT', 'POSE_LANDMARKS_NEUTRAL', 'matrixDataToMatrix', 'VERSION', ], 'face_detection.js': ['VERSION', 'FaceDetection'], ...config, }; const fileName = path.basename(id); if (!(fileName in MEDIAPIPE_EXPORT_NAMES)) return null; let code = fs.readFileSync(id, 'utf-8'); for (const name of MEDIAPIPE_EXPORT_NAMES[fileName]) { code += `exports.${name} = ${name};`; } return { code }; }, });

MediaPipe ๋ชจ๋“ˆ์˜ ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” Vite ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.


1. MediaPipe ํŒŒ์ผ์„ ์ฝ์Šต๋‹ˆ๋‹ค.
2. ํ•„์š”ํ•œ ๊ฐ์ฒด์™€ ํ•จ์ˆ˜๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋‚ด๋ณด๋‚ด๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
3. ์ˆ˜์ •๋œ ์ฝ”๋“œ๋ฅผ Vite์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ ์‹œ์—๋„ MediaPipe ๋ชจ๋“ˆ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋กœ๋“œ๋˜๊ณ  ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

<typescript />
// vite.config.ts import { mediapipe } from './config/vite-plugin-mediapipe'; export default defineConfig(({ mode }) => { return { plugins: [ react(), ... mediapipe(), ...

https://github.com/google/mediapipe/issues/4120

 

Vite build is prepending undefined variables to @mediapipe deps in production /dist/index.js file ยท Issue #4120 ยท google-ai-ed

OS Platform and Distribution node:16.18-alpine official docker image Compiler version No response Programming Language and version JavaScript Installed using virtualenv? pip? Conda?(if python) No r...

github.com

6. โœจ ์ถ”๊ฐ€ ์ฝ”๋“œ ๊ฐœ์„ 

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์™ธ์— ์ด ์ฐธ์— ์ถ”๊ฐ€๋กœ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์„ ์ฐพ์•„์„œ ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

6.1. ์ƒ๋Œ€๊ฒฝ๋กœ โžก๏ธ ์ ˆ๋Œ€ ๊ฒฝ๋กœ

6.1.1. ๊ธฐ์กด ๋ฌธ์ œ์ 

์œ„์™€ ๊ฐ™์ด depth๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ๊ฐ€๋…์„ฑ์ด ๋งค์šฐ ๋–จ์–ด์ง€๋Š” ์ƒํ™ฉ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

6.1.2. ๊ฐœ์„ 

<typescript />
// vite.config.ts resolve: { alias: { '@apis': path.resolve(__dirname, 'src/apis'), '@assets': path.resolve(__dirname, 'src/assets'), '@components': path.resolve(__dirname, 'src/components'), '@constants': path.resolve(__dirname, 'src/constants'), '@hooks': path.resolve(__dirname, 'src/hooks'), '@libs': path.resolve(__dirname, 'src/libs'), '@modules': path.resolve(__dirname, 'src/modules'), '@pages': path.resolve(__dirname, 'src/pages'), '@services': path.resolve(__dirname, 'src/services'), '@styles': path.resolve(__dirname, 'src/styles'), '@templates': path.resolve(__dirname, 'src/templates'), '@utils': path.resolve(__dirname, 'src/utils'), ... }, },
<typescript />
// tsconfig.json ... "baseUrl": ".", "paths": { "react": ["./node_modules/@types/react"], // "@/*": ["src/*"], "@apis/*": ["src/apis/*"], "@assets/*": ["src/assets/*"], "@components/*": ["src/components/*"], "@constants/*": ["src/constants/*"], "@hooks/*": ["src/hooks/*"], "@libs/*": ["src/libs/*"], "@modules/*": ["src/modules/*"], "@pages/*": ["src/pages/*"], "@services/*": ["src/services/*"], "@styles/*": ["src/styles/*"], "@templates/*": ["src/templates/*"], "@utils/*": ["src/utils/*"] }

์œ„์™€ ๊ฐ™์ด ์ ˆ๋Œ€๊ฒฝ๋กœ ๊ด€๋ จ ์ฝ”๋“œ๋ฅผ ์„ค์ •ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ์„  ํ›„

์ด์   depth์™€ ์ƒ๊ด€์—†์ด src ํด๋” ๊ธฐ์ค€์œผ๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งค์šฐ ๊น”๋”ํ•ด์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ์ฝ”๋“œ๋“ค์— ๋Œ€ํ•ด์„œ ๋ณ€๊ฒฝํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

6.2. ๋ถˆํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ œ๊ฑฐ

๋ถˆํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฆฌ์ŠคํŠธ์—…

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๊ณ , ๋Œ€์ฒด ๊ฐ€๋Šฅํ•œ ๊ฒƒ๋“ค์— ๋Œ€ํ•ด์„œ ๋ฆฌ์ŠคํŠธ์—…์„ ํ•˜๊ณ  ์ œ๊ฑฐ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ด์— ๊ด€๋ จํ•ด์„œ๋Š” ํ˜น์‹œ๋‚˜ ์ž ์žฌ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๊ฑฐ๋‚˜, ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์•ˆ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์œ„์ฒ˜๋Ÿผ ๋ฆฌ์ŠคํŠธ์—…์„ ํ•˜๊ณ  ํŒ€์›๋ถ„๋“ค๊ป˜ ํ•œ ๋ฒˆ ๋” ํ™•์ธ์„ ๋ฐ›๊ณ  ์ œ๊ฑฐ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ด 27๊ฐœ์˜ ๋ถˆํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค.

7. โœ… ์„ฑ๋Šฅ ๋น„๊ต ๋ฐ ๊ฐœ์„  ๊ฒฐ๊ณผ 

์–ด๋– ํ•œ ์ž‘์—…์„ ํ–ˆ๋Š”์ง€ ๋‚˜์—ดํ•ด๋ณด์ž๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Vite ์ „ํ™˜, config ์„ค์ •
  • ๋ถˆํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ 27๊ฐœ ์ œ๊ฑฐ ๋ฐ ๋Œ€์ฒด
  • CRA ์˜์กด์„ฑ ์ œ๊ฑฐ
  • ๋ Œ๋”๋ง ๋ฌธ์ œ ์ฝ”๋“œ ์ˆ˜์ •
  • ์ƒ๋Œ€ ๊ฒฝ๋กœ โžก๏ธ ์ ˆ๋Œ€๊ฒฝ๋กœ ๋ณ€๊ฒฝ
  • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์‹คํ–‰ ์ „ ํ„ฐ๋ฏธ๋„์—์„œ proxy ์„œ๋ฒ„ ์„ ํƒ ๊ฐ€๋Šฅํ•œ ์Šคํฌ๋ฆฝํŠธ ์ถ”๊ฐ€
  • defaultProps โžก๏ธ defaultParameter ๋Œ€์ฒด
  • react-query ๋‚ด๋ถ€์— ๋ถˆํ•„์š”ํ•œ useState ์ œ๊ฑฐ ๋ฐ ๋Œ€์ฒด 

ํ˜„์žฌ ๊ธ€์— ์ž‘์„ฑ๋œ ๊ฒƒ ์™ธ์— ๋” ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์ด ์กด์žฌํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๊ฐœ์„  ๊ฒฐ๊ณผ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ธก์ • ํ•ญ๋ชฉ CRA(webpack) Vite(rollup, esbuild) ๊ฐœ์„ ์œจ
๊ฐœ๋ฐœ ํ™˜๊ฒฝ ๊ตฌ๋™ ์‹œ๊ฐ„ ์•ฝ 20์ดˆ ์•ฝ 200ms ์•ฝ 99.0%
๋นŒ๋“œ ์†Œ์š” ์‹œ๊ฐ„ ์•ฝ 26์ดˆ ์•ฝ 16์ดˆ ์•ฝ 38.5%
๋นŒ๋“œ๋œ ํฌ๊ธฐ ์•ฝ 317MB ์•ฝ 222MB ์•ฝ 30.0%

์ธก์ • ํ™˜๊ฒฝ์€ m1 pro 16G์ด๋ฉฐ, ํ‰๊ท ๊ฐ’์ž…๋‹ˆ๋‹ค.

8. ๐Ÿ“• ๋งˆ์น˜๋ฉฐ

CRA์—์„œ Vite๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ง„ํ–‰ํ•ด๋„ ๋˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ ํŒ€์›๋ถ„๋“ค์—๊ฒŒ ๋จผ์ € ์ œ์•ˆ์„ ํ–ˆ๋˜ ์ƒํ™ฉ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๋‹คํ–‰ํžˆ ๋ชจ๋‘ ์ฐฌ์„ฑ์„ ํ•ด์ฃผ์…จ๊ณ , ์ด์Šˆ๊ฐ€ ํ„ฐ์กŒ์„ ๋•Œ ๊ณต์œ ๋ฅผ ํ•˜๋ฉด ์ ๊ทน์ ์œผ๋กœ ๋„์™€์ฃผ์…”์„œ ์‰ฝ๊ฒŒ ํ•ด๊ฒฐ์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ด์ œ๋Š” ๋” ์พŒ์ ํ•œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!

 

์•ž์œผ๋กœ react-query ๋ฒ„์ „์—…, FSD ์•„ํ‚คํ…์ฒ˜, recoil์—์„œ jotai๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋“ฑ ๊ฐœ์ธ์ ์œผ๋กœ ๊ฐœ์„ ํ•˜๋ฉด ์ข‹๊ฒ ๋‹ค ํ•˜๋Š” ๋ถ€๋ถ„๋“ค์ด ์ƒ๋‹นํžˆ ๋งŽ์€๋ฐ ์‹œ๊ฐ„์ด ๋‚  ๋•Œ๋งˆ๋‹ค ์กฐ๊ธˆ์”ฉ ์ง„ํ–‰์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•
profile

๐Ÿ’ป์šฉ๋‡ฝ ๊ฐœ๋ฐœ ๋…ธํŠธ๐Ÿ’ป

@์šฉ๋‡ฝ

ํฌ์ŠคํŒ…์ด ์ข‹์•˜๋‹ค๋ฉด "์ข‹์•„์š”โค๏ธ" ๋˜๋Š” "๊ตฌ๋…๐Ÿ‘๐Ÿป" ํ•ด์ฃผ์„ธ์š”!