๋ฐ˜์‘ํ˜•

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•


์„ค์น˜

yarn add "@svgr/cli"
yarn add -D "@svgr/webpack"

 

CLI ๋ช…๋ น์–ด

๐Ÿ’ก ๊ฒฝ๋กœ๋งŒ ์ž…๋ ฅํ•˜๋ฉด svg path๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผ. -- double dash๋Š” ์ปค๋งจ๋“œ ์˜ต์…˜์ด ๋๋‚œ๋‹ค๋Š”๊ฑธ ์˜๋ฏธํ•˜๋ฏ€๋กœ(์ฐธ๊ณ ๊ธ€) -- ๋’ค์— ๊ฒฝ๋กœ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด svg path๊ฐ€ ์ง€์ •๋จ(์˜ต์…˜์ด ์—†๋‹ค๋ฉด ๊ตณ์ด ์•ˆ๋ถ™์—ฌ๋„ ๋จ).

# config ํŒŒ์ผ์ด ์—†์„ ๋•Œ 
# svgr <svg-path> -d <output-path>
svgr ./assets/icons/raw/bulb.svg -d ./assets/icons/dist

# config ํŒŒ์ผ์ด ์žˆ์„ ๋•Œ
# svgr --config-file <config-file-path> <svg-path> -d <output-path>
svgr --config-file ./svgr.config.js ./assets/icons/raw/bulb.svg -d ./assets/icons/dist

# config ํŒŒ์ผ์— output ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ–ˆ์„ ๋•Œ
svgr --config-file ./svgr.config.js -- ./assets/icons/raw/bulb.svg

# config ํŒŒ์ผ์— output ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•˜๊ณ , ํŠน์ • ํด๋”(์•„๋ž˜์—์„  raw)์— ์žˆ๋Š” ๋ชจ๋“  svg๋ฅผ ๋ณ€ํ™˜ํ•  ๋•Œ
svgr --config-file ./svgr.config.js -- ./assets/icons/raw

 

๐Ÿ’ก package.json ํŒŒ์ผ scripts ์†์„ฑ์— ์•„๋ž˜์ฒ˜๋Ÿผ ๋“ฑ๋กํ•ด๋‘๊ณ  ์‚ฌ์šฉํ•˜๋ฉด ํŽธ๋ฆฌํ•˜๋‹ค. ์•„๋ž˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด(npm run generate) ./assets/icons/raw(svg path) ํด๋”์— ์žˆ๋Š” ๋ชจ๋“  svg ํŒŒ์ผ์„ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณ€ํ™˜ํ•œ ํ›„ svgr.config.js ์„ค์ • ํŒŒ์ผ์—(outDir ์†์„ฑ) ๋ช…์‹œํ•œ output ํด๋”์— ์ €์žฅํ•œ๋‹ค. svg path๋Š” ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ ์ ˆํ•œ output ๊ฒฝ๋กœ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค.

// package.json
{
  "scripts": {
    // ./assets/icons/raw ์— ์žˆ๋Š” ๋ชจ๋“  svg ํŒŒ์ผ์„ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณ€ํ™˜
    "generate": "svgr --config-file ./svgr.config.js -- ./assets/icons/raw"
  }
}

 

์ƒ์„ฑ ์˜ˆ์‹œ

์ง€์ •ํ•œ output ๊ฒฝ๋กœ์— SVG ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ๊ณผ export ํ•  ์ˆ˜ ์žˆ๋Š” index.ts ํŒŒ์ผ์ด ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ๋‹ค.

// ๋ณ€ํ™˜๋œ svg ์ปดํฌ๋„ŒํŠธ ์˜ˆ์‹œ — assets/icons/dist/MagnifierOutlined.tsx
import * as React from 'react';
import { SVGProps } from 'react';

const SvgMagnifierOutlined = (props: SVGProps<SVGSVGElement>) => (
  // svg ์„ธ๋ถ€ ๋‚ด์šฉ ์ƒ๋žต
  <svg {...props}>
    <path />
  </svg>
);

export default SvgMagnifierOutlined;
// assets/icons/dist/index.ts ํŒŒ์ผ์— ๋ณ€ํ™˜ํ•œ svg ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž๋™ ์ถ”๊ฐ€๋œ๋‹ค
export { default as MagnifierOutlined } from './MagnifierOutlined';
export { default as Spinner } from './Spinner';
// ...
// ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ import ์˜ˆ์‹œ
import { MagnifierOutlined } from '@/assets/icons/dist';

 

 

config ํŒŒ์ผ ์˜ˆ์‹œ


svgr.config ํŒŒ์ผ์€ js ํ™•์žฅ์ž๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

// svgr.config.js
module.exports = {
  icon: true, // use "1em" as width and height
  typescript: true, // ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ์‹œ true
  outDir: './assets/icons/dist', // output ๊ฒฝ๋กœ
  replaceAttrValues: {
    // ์†์„ฑ ๊ฐ’์ด #282829๋ฉด ๋ชจ๋‘ currentColor๋กœ ๋ณ€๊ฒฝ๋จ
    '#282829': 'currentColor',
  },
};

 

 

NextJS์—์„œ React ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ”๋กœ import ํ•˜๊ธฐ


์œ„์—์„œ ์„ค๋ช…ํ•œ svgr ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ svgr cli ํ„ฐ๋ฏธ๋„ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•ด svg ํŒŒ์ผ์„ React ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋‘๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ํ•œํŽธ, React CRA์—์„  ๋ณ„๋‹ค๋ฅธ ์„ค์ • ์—†์ด ๊ทธ๋•Œ๊ทธ๋•Œ ํ•„์š”ํ•œ svg ํŒŒ์ผ์„ React ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถˆ๋Ÿฌ์™€์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ(๋ฏธ๋ฆฌ ๋ณ€ํ™˜ ์—†์ด), svgr์„ ์‚ฌ์šฉํ•˜๋ฉด NextJS์—์„œ๋„ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

// svg ํŒŒ์ผ → ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์˜ˆ์‹œ — React CRA
import { ReactComponent as BulbIcon } from './assets/icons/bulb.svg';

// ์ปดํฌ๋„ŒํŠธ ๋ฆฌํ„ด๋ฌธ
return <BulbIcon />;

 

NextJS์—์„œ svg ํŒŒ์ผ์„ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด next.config.js ์„ค์ • ํŒŒ์ผ์— ์•„๋ž˜ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•œ๋‹ค. config ํŒŒ์ผ ์ˆ˜์ • ํ›„์—” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์žฌ์‹œ์ž‘ํ•ด์•ผ ์ ์šฉ๋œ๋‹ค.

// NextJS ์‚ฌ์šฉ์‹œ — next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  // ...
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });

    return config;
  },
};

module.exports = nextConfig;

 

์ด ๋ฐฉ๋ฒ•์€ svgr cli๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ @svgr/cli ํŒจํ‚ค์ง€๋Š” ์„ค์น˜ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค(๋ฌผ๋ก  @svgr/webpack ํŒจํ‚ค์ง€๋Š” ์„ค์น˜ํ•ด์•ผ ๋œ๋‹ค). ์ฐธ๊ณ ๋กœ svgr.config.js ํŒŒ์ผ์„ ์‚ญ์ œํ•ด์•ผ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค.

// svg ํŒŒ์ผ → ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์˜ˆ์‹œ — NextJS
import BulbIcon from '@/assets/icons/raw/bulb.svg';

// ์ปดํฌ๋„ŒํŠธ ๋ฆฌํ„ด๋ฌธ
return <BulbIcon />;

 

 

CLI ์˜ต์…˜


๊ตฌ๋ฌธ: svgr [options] <file|directory>
์˜ˆ์‹œ: svgr --replace-attr-values "#fff=currentColor" icon.svg

 

์˜ต์…˜ ํ”Œ๋ž˜๊ทธ ์„ค๋ช…
-V, --version ๋ฒ„์ „ ๋ฒˆํ˜ธ ์ถœ๋ ฅ
--config-file <file> SVGR ์„ค์ • ํŒŒ์ผ ๊ฒฝ๋กœ ์ง€์ •
--no-runtime-config ๋Ÿฐํƒ€์ž„ ์„ค์ • ํŒŒ์ผ(.svgrrc, .svgo.yml, .prettierrc) ๋น„ํ™œ์„ฑํ™”
-d, --out-dir <dirname> ์ถœ๋ ฅ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ง€์ •
--ignore-existing --out-dir ์‚ฌ์šฉ ์‹œ ๊ธฐ์กด ํŒŒ์ผ ๋ฌด์‹œ
--ext <ext> ์‚ฌ์šฉ์ž ์ง€์ • ํ™•์žฅ์ž ์ง€์ • (๊ธฐ๋ณธ๊ฐ’: js)
--filename-case <case> ํŒŒ์ผ๋ช… ํ˜•์‹ ์ง€์ • (pascal, kebab, camel, ๊ธฐ๋ณธ๊ฐ’: pascal)
--icon ๋„ˆ๋น„์™€ ๋†’์ด๋ฅผ 1em์œผ๋กœ ์„ค์ •
--native react-native-svg ๊ธฐ๋ฐ˜ React Native ์ง€์› ์ถ”๊ฐ€
--memo ๊ฒฐ๊ณผ ์ปดํฌ๋„ŒํŠธ์— React.memo ์ถ”๊ฐ€
--ref SVG ๋ฃจํŠธ ์š”์†Œ์— ref ์ „๋‹ฌ
--no-dimensions ๋ฃจํŠธ SVG์˜ width, height ์ œ๊ฑฐ
--expand-props [position] props ํ™•์žฅ ์œ„์น˜ ์ง€์ • ๋˜๋Š” ๋น„ํ™œ์„ฑํ™” (start, end, none, ๊ธฐ๋ณธ๊ฐ’: end)
--svg-props <property=value> SVG ์š”์†Œ์— props ์ถ”๊ฐ€
--replace-attr-values <old=new> ์†์„ฑ๊ฐ’ ์น˜ํ™˜
--template <file> ์‚ฌ์šฉ์ž ์ง€์ • ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ ์ง€์ •
--index-template <file> ์‚ฌ์šฉ์ž ์ง€์ • index.js ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ ์ง€์ •
--no-index index ํŒŒ์ผ ์ƒ์„ฑ ๋น„ํ™œ์„ฑํ™”
--title-prop props์™€ ์—ฐ๊ฒฐ๋œ title ์š”์†Œ ์ƒ์„ฑ
--prettier-config <fileOrJson> Prettier ์„ค์ • ์ง€์ •
--no-prettier Prettier ๋น„ํ™œ์„ฑํ™”
--svgo-config <fileOrJson> SVGO ์„ค์ • ์ง€์ •
--no-svgo SVGO ๋น„ํ™œ์„ฑํ™”
--silent ์ถœ๋ ฅ ๋ฉ”์‹œ์ง€ ์ˆจ๊น€
--stdin ํ‘œ์ค€ ์ž…๋ ฅ(stdin)์—์„œ ๊ฐ•์ œ๋กœ ์ฝ๊ธฐ
--stdin-filepath stdin ์ž…๋ ฅ์˜ ํŒŒ์ผ ๊ฒฝ๋กœ์ธ ๊ฒƒ์ฒ˜๋Ÿผ ์ง€์ •
-h, --help ์‚ฌ์šฉ๋ฒ• ์ถœ๋ ฅ
๋ฐ˜์‘ํ˜•