[React] svg ํ์ผ → ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ๋ณํํ๊ธฐ - React SVGR
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
์ค์น
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 |
์ฌ์ฉ๋ฒ ์ถ๋ ฅ |
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[React] ๋ฆฌ์กํธ ์ฟผ๋ฆฌ(React Query) staleTime์ ์ค์ ํ๋ 3๊ฐ์ง ๋ฐฉ๋ฒ
[React] ๋ฆฌ์กํธ ์ฟผ๋ฆฌ(React Query) staleTime์ ์ค์ ํ๋ 3๊ฐ์ง ๋ฐฉ๋ฒ
2024.05.12 -
[Git] ๋ณํฉ(Merge) ์ถฉ๋ ๋ฐฉ์ง๋ฅผ ์ํ ๋ฆฌ๋ฒ ์ด์ค Rebase
[Git] ๋ณํฉ(Merge) ์ถฉ๋ ๋ฐฉ์ง๋ฅผ ์ํ ๋ฆฌ๋ฒ ์ด์ค Rebase
2024.05.12 -
[React] ๋ฆฌ์กํธ Context API ๋ ๋๋ง ์ต์ ํํ๊ธฐ
[React] ๋ฆฌ์กํธ Context API ๋ ๋๋ง ์ต์ ํํ๊ธฐ
2024.05.11 -
[HTML/CSS] form ์ธ๋ถ์์ form ์ฐ๊ฒฐ / document ๊ฐ์ฒด๋ก form ์ ๊ทผํ๊ธฐ
[HTML/CSS] form ์ธ๋ถ์์ form ์ฐ๊ฒฐ / document ๊ฐ์ฒด๋ก form ์ ๊ทผํ๊ธฐ
2024.05.11