SVG(Scalable Vector Graphics)๋ ์น์์ ๋ฒกํฐ ๊ธฐ๋ฐ์ ๊ทธ๋ํฝ์ ํํํ๋ ๋ฐ ์ฌ์ฉ๋๋ XML ๊ธฐ๋ฐ์ ๋งํฌ์ ์ธ์ด์ ๋๋ค.
์ ํฌํ NDD๋ ๊ณฐํฐ๋ทฐ ์๋น์ค๋ฅผ ๊ฐ๋ฐ์ค์ ๋๋ค!
SVG(Scalable Vector Graphics)๋ ์น์์ ๋ฒกํฐ ๊ธฐ๋ฐ์ ๊ทธ๋ํฝ์ ํํํ๋ ๋ฐ ์ฌ์ฉ๋๋ XML ๊ธฐ๋ฐ์ ๋งํฌ์ ์ธ์ด์ ๋๋ค. ๊ทธ๋ฌ๋ ์ง๊ธ๊น์ง ์ฌ๋ฌ๊ฐ์ง ์ด์ ๋ก SVG ํ์ผ์ ๊ด๋ฆฌํ๋๊ฒ์ ์ ์๊ฒ ๋ฌํ๊ฒ ๊ฝค๋ ๊ท์ฐฎ์ ์ผ์ด์์ต๋๋ค. ์ด๋ฌํ ๊ท์ฐฎ์์ ํด๊ฒฐ ํ๊ธฐ ์ํด์๋ SVG์ ๊ธฐ๋ณธ์ ์ธ ํน์ฑ๊ณผ FE์ธก๋ฉด์์ SVG ํ์ผ์ ๊ธฐ๋ณธ์ ์ธ ์ด๋ ค์์ ๋ํด์ ์ดํดํ ํ์๊ฐ ์์์ต๋๋ค.
๋ค์์ ํ์ผ ๊ด๋ฆฌ ๊ธฐ์กด์ SVG ๊ด๋ฆฌ ๋ฐฉ์์์๋ ๊ฐ๊ฐ์ SVG ์ด๋ฏธ์ง๊ฐ ๋ณ๋์ ํ์ผ๋ก ์กด์ฌํ์ต๋๋ค. ์น์ฌ์ดํธ์ ๋ค์์ ์์ด์ฝ ๋๋ ๊ทธ๋ํฝ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ์ด๋ค ๊ฐ๊ฐ์ ๋ณ๋์ ํ์ผ๋ก ๊ด๋ฆฌํด์ผ ํ์ต๋๋ค. ์ด๋ก ์ธํด ํ์ผ ์๊ฐ ๋ง์์ง๊ณ , ์ด๋ค์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ๊ฐ ์ด๋ ค์ ์ต๋๋ค.
๋คํธ์ํฌ ์ค๋ฒํค๋ ์น ํ์ด์ง๊ฐ ๋ก๋๋ ๋๋ง๋ค, ๊ฐ๊ฐ์ SVG ํ์ผ์ ๋ํ ๋ณ๋์ HTTP ์์ฒญ์ด ํ์ํ์ต๋๋ค. ์ด๋ ํนํ ๋ง์ ์์ ๊ทธ๋ํฝ ์์๊ฐ ์๋ ํ์ด์ง์์ ๋คํธ์ํฌ ์ค๋ฒํค๋๋ฅผ ์ฆ๊ฐ์์ผ ์น์ฌ์ดํธ์ ๋ก๋ฉ ์๊ฐ์ ์ํฅ์ ๋ฏธ์ณค์ต๋๋ค.
์บ์ฑ์ ๋ณต์ก์ฑ ๊ฐ๊ฐ์ SVG ํ์ผ์ ๋ ๋ฆฝ์ ์ผ๋ก ์บ์๋์ด์ผ ํ์ต๋๋ค. ์ด๋ ์น์ฌ์ดํธ์ ์บ์ฑ ์ ๋ต์ ๋ณต์กํ๊ฒ ๋ง๋ค๊ณ , ํจ์จ์ ์ธ ์บ์ ๊ด๋ฆฌ๋ฅผ ์ด๋ ต๊ฒ ํ์ต๋๋ค.
ํ์ฅ์ฑ๊ณผ ์ ์ง๋ณด์์ ๋ฌธ์ (ํนํ๋ ์ค์ํ...) ํ๋ก์ ํธ๊ฐ ์ฑ์ฅํ๋ฉด์ ์๋ก์ด ๊ทธ๋ํฝ ์์๊ฐ ์ถ๊ฐ๋๊ฑฐ๋ ๊ธฐ์กด์ ๊ฒ๋ค์ด ๋ณ๊ฒฝ๋ ๋, ์ด๋ฌํ ๋ณ๊ฒฝ ์ฌํญ์ ๊ด๋ฆฌํ๋ ๊ฒ์ ์๊ฐ์ด ๋ง์ด ์์๋๋ ์์ ์ด์์ต๋๋ค. ๋ํ, ๊ฐ๊ฐ์ ํ์ผ์ ์ถ์ ํ๊ณ ๊ด๋ฆฌํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ ์ง๋ณด์์ ๋ถ๋ด์ด ์ปธ์ต๋๋ค.
์ ํฌ ํ๋ก์ ํธ๋ webpack ๊ธฐ๋ฐ์ผ๋ก ๋์์ ํ๊ณ ์์๊ณ , ์๋ฏผ๋์ ํด๋น์ปค๋ฐ์์ svgr์ ์ถ๊ฐํ๋์ react์ฒ๋ผ ์์ฝ๊ฒ import ๋ฐ์์ svg ๋ฅผ ์ฌ์ฉํ ์ ์์์ต๋๋ค. ์๋์ ๊ฐ์ ๋ฐฉ์์ด์์ต๋๋ค. ๋ค์์ฒ๋ผ ์๋จ์์ import ๋ฐ์ ํ
๋ค์ ์ฌ์ง์ฒ๋ผ ์์ฝ๊ฒ react ํ๋ก์ ํธ์์ ์ฌ์ฉํ ์ ์์์ต๋๋ค.
ํ์ง๋ง ํ๋ก์ ํธ์ ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด์ ์ด๋ฌํ ๋ฐฉ์์ ์ฌ๋ฌ๊ฐ์ง ๋จ์ ์ ๊ฐ์ง๊ฒ ๋์์ต๋๋ค..
ํ๋ก์ ํธ์ ์ด๊ธฐ ๋จ๊ณ์์๋ ๋ถ๊ตฌํ๊ณ assets ๋ด๋ถ์ svg๊ฐ ๋ง์ด ์ถ๊ฐ๊ฐ ๋์์ต๋๋ค. ํ์ง๋ง ์ด๋ ํ๋ก์ ํธ์ ํฌ๊ธฐ๋ฅผ ์ฆ๊ฐ์ํฌ ๋ฟ ์๋๋ผ ํ์ด์ง๋ฅผ ๋ฐฉ๋ฌธํ ๋๋ง๋ค ๊ฐ๊ธฐ๋ค๋ฅธ svgํ์ผ์ load ํ๊ฒ ๋ฉ๋๋ค.
๋ค์ ์ฌ์ง๊ณผ ๊ฐ์ด ํ ํ์ผ์์ load ํด์ผํ svg ํ์ผ์ด ์ฆ๊ฐํจ์ ๋ฐ๋ผ ํ์ผ์ ์๋จ์์ import ๋ฐ๋ ์ปดํฌ๋ํธ๋ค์ด ์ฆ๊ฐํ๊ฒ ๋์์ต๋๋ค.
๋ฌผ๋ก ์ด๋ถ๋ถ์ prettier ์ค์ ์ ํตํด์ ํด์ ํ ์ ์์ต๋๋ค๋ง, ํน๋ณํ๊ฒ ๋ ๊ท์น์ ์ถ๊ฐํ๊ธฐ๋ณด๋ค๋ ์ด๋ฏธ ์๋ ๊ท์น ๋ด๋ถ์์ ์ ๋ ฌ์ ์ฌ์ฉํ๊ณ ์ถ์์ต๋๋ค.
๋ฐ๋ผ์ ์ ํฌ๋ ๋ ์ฝ๊ฒ ์ ์ง๋ณด์๊ฐ ๊ฐ๋ฅํ Icon ์ปดํฌ๋ํธ๋ฅผ ๋์ ํ๊ฒ ๋์์ต๋๋ค.
์ถ๊ฐ๋ก ์์ฆ preact ์ ๊ฐ๋ฐ์๋ก ์ ๋ช ํ์ "Jason Miller"๋์ ๋ค์๊ณผ ๊ฐ์ด ๋ง์ํ์ จ์ต๋๋ค!
SVG๋ฅผ JSX๋ก ๊ฐ์ ธ์ค์ง ๋ง์ธ์. ์ด ๋ฐฉ๋ฒ์ ์คํ๋ผ์ดํธ ์ํธ ์ค์์ ๊ฐ์ฅ ๋นํจ์จ์ ์ ๋๋ค: ๋ค๋ฅธ ๊ธฐ๋ฒ๋ค๋ณด๋ค ์ต์ 3๋ฐฐ ์ด์์ ๋น์ฉ์ด ๋ค๊ณ , ์คํ ์๊ฐ(๋ ๋๋ง) ์ฑ๋ฅ๊ณผ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์๋ ์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค. ํ ์ ๋ช ํ ์ฌ์ดํธ์ ๋ฒ๋ค์์ SVG ์์ด์ฝ์ด ๊ฑฐ์ 50% (250kb)๋ฅผ ์ฐจ์งํ๊ณ ์๋๋ฐ, ๋๋ถ๋ถ ์ฌ์ฉ๋์ง ์๊ณ ์์ต๋๋ค." from Jason Miller X
๋ค์๊ณผ ๊ฐ์ ๋ชฉ์ ์ ๊ฐ์ง๊ณ ํ๋ก์ ํธ๋ฅผ ์งํํ๊ฒ ๋์์ผ๋ฉฐ, ๊ฐ์ฅ ๋์ฌ๊ฒจ ๋ณธ ๋ถ๋ถ์ SVG ํ๊ทธ์ use ํ๊ทธ๋ฅผ ์ด์ฉํด SVG Sprite ๊ธฐ๋ฒ์ ํ์ฉํ๋ ๊ฒ ์ด์์ต๋๋ค.
ํ์ง๋ง SVG Sprite ๊ธฐ๋ฒ์ ์ฌ์ฉํ๊ธฐ์ MDN์์ ์ ๊ณตํ๋ use์ symbol์ ๋ํด์ ์ดํดํ๋ฉด ๋์ฑ ์ฝ๊ฒ ์ดํดํ์ค ์ ์์ต๋๋ค! ์๋๋ ํด๋น MDN ๋ฌธ์์ ๋ํ ๋งํฌ ์ ๋๋ค!
Mdn svg use ๋ถ๋ถ Mdn svg symbol ๋ถ๋ถ
๋ค์ ์ฌ์ง์ ๋ณด๋ฉด svg ํ๊ทธ ๋ด์ฐ๋ฒต์ myCircle์ด๋ผ๊ณ ๋ช ์ํ ํ๊ทธ๋ฅผ use href๋ฅผ ํตํด์ ์ฌ์ฌ์ฉํ๋ฉฐ, svg ํ๊ทธ์ ์ผ๋ถ๋ฅผ ์ฌ์ฌ์ฉํ๋๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ด๋ ์ข ๋ ๋ฉฑํํ๊ฒ circle ๋ฟ์๋๋ผ symbol์ด๋ผ ๋ช ์ํ ์ข ๋ ๋ฒ์ฉ์ ์ธ ๋ชฉ์ ์ ๊ฐ์ง ํ๊ทธ๋ฅผ ์ฌ์ฌ์ฉํ๋ฉฐ, ํ๋๋ก ๋ช ์ํ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
ํด๋น ๋ฐฉ์์ ํน์ง์ svg ํ๊ทธ ๋ด๋ถ์ ํน์ ๋ถ๋ถ์ ์ฌ์ฌ์ฉํ๊ธฐ ์ํ ๋ฐฉ์์ผ๋ก use๋ฅผ ์ฌ์ฉํ๋ค๋๊ฒ ์ด์์ต๋๋ค. ์ฌ๊ธฐ์ ์์ด๋์ด๋ฅผ ์ป์ด ๊ฑฐ๋ํ svg ํ๊ทธ๋ฅผ ์ฌ์ฉํด ๊ทธ ๋ด๋ถ์ ํน์ ๋ถ๋ถ(์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ icon์ด ๋ฉ๋๋ค) ์ ์ฌ์ฌ์ฉ ํ ์ ์๊ฒ ๋ฉ๋๋ค.
์ด ๋ฐฉ์์ ์ ๊ทน ์ฌ์ฉํด์ SVG Sprite ๊ธฐ๋ฒ์ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
ํด๋น ๊ธฐ์ ์ ๋ํ ๊ตฌํ์ Simple icon systems using SVG sprites ์ ์ฐธ๊ณ ํ์ต๋๋ค.
SVG ์คํ๋ผ์ดํธ ๊ธฐ๋ฒ์ ์น ๊ฐ๋ฐ์์ ์์ฃผ ์ฌ์ฉ๋๋ ๊ณ ๊ธ ๊ทธ๋ํฝ ์ฒ๋ฆฌ ๋ฐฉ์์
๋๋ค. ์ด ๋ฐฉ๋ฒ์ ํฐ SVG ํ์ผ ๋ด์ ์ฌ๋ฌ ๊ฐ์ ๊ทธ๋ํฝ ์์(์: ์์ด์ฝ)๋ฅผ ํฌํจ์ํค๊ณ , ํ์ํ ๋ถ๋ถ๋ง์ <use>
ํ๊ทธ๋ฅผ ํตํด ์ฌ์ฌ์ฉํ๋ ๊ธฐ์ ์
๋๋ค. ๊ฐ ๊ทธ๋ํฝ ์์๋ ๊ณ ์ ํ ID๋ก ์๋ณ๋๋ฉฐ, ์ด ID๋ฅผ ํตํด ํด๋น ์์๋ฅผ ํ์ด์ง์ ๋ค์ํ ์์น์์ ํธ์ถํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
SVG ์คํ๋ผ์ดํธ ๊ธฐ๋ฒ์ ํต์ฌ์ ํ๋์ ํฐ SVG ํ์ผ์ ๋ค์์ ๊ทธ๋ํฝ ์์๋ฅผ ํฌํจ์ํค๋ ๊ฒ์
๋๋ค. ์ด ํ์ผ์ ์ผ๋ฐ์ ์ผ๋ก ์น ํ์ด์ง์ ๋ณธ๋ฌธ์ด ์๋, ๋ณ๋์ ํ์ผ๋ก ์กด์ฌํ๊ฑฐ๋ <head>
์น์
์ ํฌํจ๋ฉ๋๋ค. ๊ฐ ์์๋ <symbol>
ํ๊ทธ๋ก ์ ์๋์ด ๊ณ ์ ํ ID๋ฅผ ๊ฐ์ต๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ๋ ์น ํ์ด์ง ๋ด์์ ํ์ํ SVG ์์๋ฅผ ์ ํ์ ์ผ๋ก ์ฌ์ฌ์ฉํ ์ ์๋ ์ ์ฐ์ฑ์ ์ ๊ณตํฉ๋๋ค.
ํ์ง๋ง ์ ๋ JS ๋ด๋ถ์์ ํด๊ฒฐํ๊ณ ์ถ์ด GlobalSvgProvider๋ฅผ ๋ฐ๋ก ๋์ ํ์ต๋๋ค!
<use>
ํ๊ทธ์ ์ญํ ์น ํ์ด์ง์์ ํน์ SVG ์์๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด <use>
ํ๊ทธ๋ฅผ ํ์ฉํฉ๋๋ค. ์ด ํ๊ทธ๋ xlink:href ์์ฑ์ ํตํด ์คํ๋ผ์ดํธ ๋ด์ ํน์ <symbol>
์ ์ฐธ์กฐํฉ๋๋ค. ์๋ฅผ ๋ค์ด, xlink:href="#icon1"์ ID๊ฐ "icon1"์ธ <symbol>
์ ํ์ด์ง์ ๋ถ๋ฌ์ต๋๋ค. ์ด ๋ฐฉ์์ ํตํด, ํ๋์ ํฐ SVG ํ์ผ ๋ด์์ ํ์ํ ๋ถ๋ถ๋ง์ ์ ํ์ ์ผ๋ก ๋ ๋๋งํ ์ ์๊ฒ ๋ฉ๋๋ค.
๋น์ฐํ ๊ฐ๋ณ์ ์ธ ์ด๋ฏธ์ง๋ฅผ ์ต์ด์ ๋ก๋ฉ์ ํฌํจ์ํค๊ธฐ ๋๋ฌธ์, ์ด๊ธฐ ๋ก๋ฉ์๋๊ฐ "์๋์ " ์ผ๋ก ๋ ๋๋ ค์ง ์ ์์ต๋๋ค๋ง, ์ ์๋ฏธํ ์ฐจ์ด๊ฐ ๋ ์ ๋๋ก ์ด๊ธฐ ๋ก๋ฉ์๋๊ฐ ๋๋ ค์ง์ง ์์ต๋๋ค.
import { css } from "@emotion/react";
import { createPortal } from "react-dom";
const spliteSvgCode = (
<svg
xmlns="http://www.w3.org/2000/svg"
css={css`
display: none;
`}
>
<symbol id="close-circle" viewBox="0 0 40 40">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M20 40C31.0457 40 40 31.0457 40 20C40 8.9543 31.0457 0 20 0C8.9543 0 0 8.9543 0 20C0 31.0457 8.9543 40 20 40ZM13.0808 13.0642C14.2525 11.8928 16.152 11.893 17.3234 13.0647L19.9982 15.74L22.6696 13.0686C23.8412 11.897 25.7407 11.897 26.9122 13.0686C28.0838 14.2402 28.0838 16.1397 26.9122 17.3113L24.2404 19.9831L26.9154 22.6587C28.0869 23.8304 28.0867 25.7299 26.915 26.9013C25.7433 28.0728 23.8438 28.0726 22.6724 26.9009L19.9978 24.2257L17.3282 26.8953C16.1567 28.0668 14.2572 28.0668 13.0856 26.8953C11.914 25.7237 11.914 23.8242 13.0856 22.6526L15.7556 19.9826L13.0804 17.3069C11.9089 16.1352 11.9091 14.2357 13.0808 13.0642Z"
fill="white"
/>
</symbol>
<symbol id="close" viewBox="0 0 24 25">
<g id="Frame" clipPath="url(#clip0_289_791)">
<path
id="Vector"
d="M23.4772 3.35322C24.1798 2.62789 24.0679 1.55056 23.2223 0.947888C22.3767 0.345222 21.1208 0.441222 20.4182 1.16656L11.9995 9.83322L3.58085 1.16656C2.87826 0.441222 1.62231 0.345222 0.77671 0.947888C-0.0688857 1.55056 -0.180803 2.62789 0.521788 3.35322L9.40676 12.4999L0.521788 21.6466C-0.180803 22.3719 -0.0688857 23.4492 0.77671 24.0519C1.62231 24.6546 2.87826 24.5586 3.58085 23.8332L11.9995 15.1666L20.4182 23.8332C21.1208 24.5586 22.3767 24.6546 23.2223 24.0519C24.0679 23.4492 24.1798 22.3719 23.4772 21.6466L14.5923 12.4999L23.4772 3.35322Z"
fill="white"
/>
</g>
<defs>
<clipPath id="clip0_289_791">
<rect
width="24"
height="24"
fill="white"
transform="translate(0 0.5)"
/>
</clipPath>
</defs>
</symbol>
// ๋ค๋ฅธ svg๋ฅผ ํธ์ถํ๊ธฐ ์ํด symbol์ ์ฌ์ฉํฉ๋๋ค. ์๋์ ๋ค๋ฅธ svg๋ฅผ ๋์ผํ
๋ฐฉ์์ผ๋ก ์ถ๊ฐํฉ๋๋ค.
</svg>
);
// App ๋ด๋ถ์์ ์ ์ธ๋์ด ์ต์ด ์์ฑ๋ dom์ ์ถ๊ฐ๋ฉ๋๋ค
export default function GlobalSVGProvider() {
return createPortal(spliteSvgCode, document.body);
}
๊ทธ๋ฆฌ๊ณ ์์ ๋ฐฉ์์์ ๋ฐํํ๋ GlobalSvgProvider๋ฅผ App.tsx์์ ์ฌ์ฉํด์ฃผ๋ฉด ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ Icon ์ปดํฌ๋ํธ๋ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
// foundation ๋ด๋ถ์์ ์ ์ ๋์ด ์์ต๋๋ค.
const Icon: React.FC<SvgIconProps> = ({
id,
width = "16",
height = "16",
...props
}) => {
return (
<svg width={width} height={height} {...props}>
<use href={`#${id}`} />
</svg>
);
};
// ์ฌ์ฉ๋ฐฉ๋ฒ
<Icon
id="next" // symbol ์์ ์์ฑํ id๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค.
width="2rem"
height="2rem"
css={css`
cursor: pointer;
`}
onClick={() => console.log("hihi")}
/>;
๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ก svg ํ์ผ์ ์ฝ๊ฒ ๊ด๋ฆฌ ํ ์ ์๊ฒ ๋์์ต๋๋ค. ์ด๋ก ์ธํด์ ๋ค๋ฅธ svg ํ์ผ์ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด, ๋จ์ํ Icon ์ props๋ฅผ ๋ณ๊ฒฝํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค!