λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Lect & Tip/node, Angular, React

λ¦¬μ•‘νŠΈμ—μ„œμ˜ SVG 및 μ•„μ΄μ½˜ μ»΄ν¬λ„ŒνŠΈ λ³€ν™˜

by κΉ€λ¬΄μ•Όν˜Έ3호 2025. 9. 4.
λ°˜μ‘ν˜•

λ¦¬μ•‘νŠΈμ—μ„œμ˜ SVG 및 μ•„μ΄μ½˜ μ»΄ν¬λ„ŒνŠΈ λ³€ν™˜

ν˜„λŒ€ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œλŠ” 해상도에 ꡬ애받지 μ•Šκ³  μ„ λͺ…ν•œ κ·Έλž˜ν”½μ„ μ œκ³΅ν•˜λŠ” 벑터 이미지, 특히 SVG(Scalable Vector Graphics)와 μ•„μ΄μ½˜μ˜ ν™œμš©μ΄ 점점 더 μ€‘μš”ν•΄μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€. SVGλŠ” ν”½μ…€ 기반이 μ•„λ‹Œ μˆ˜ν•™μ  μ’Œν‘œλ‘œ 그림을 ν‘œν˜„ν•˜κΈ° λ•Œλ¬Έμ—, μ–΄λ–€ λ””λ°”μ΄μŠ€μ—μ„œλ„ κΉ¨μ§€μ§€ μ•Šκ³  μ„ λͺ…ν•˜κ²Œ λ Œλ”λ§λ©λ‹ˆλ‹€. μ΄λŸ¬ν•œ νŠΉμ„±μ€ λ°˜μ‘ν˜• μ›Ή λ””μžμΈκ³Ό 고해상도 λ””μŠ€ν”Œλ ˆμ΄μ—μ„œ 맀우 μœ μš©ν•˜λ©°, λ¦¬μ•‘νŠΈμ™€ κ²°ν•©ν•˜λ©΄ ν™•μž₯μ„±κ³Ό μž¬μ‚¬μš©μ„±μ„ λ†’μ—¬ UI/UXλ₯Ό κ·ΉλŒ€ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이번 ν¬μŠ€νŒ…μ—μ„œλŠ” SVG 이미지와 μ•„μ΄μ½˜μ„ λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈλ‘œ λ³€ν™˜ν•˜λŠ” 방법, 이λ₯Ό 톡해 μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±κ³Ό μœ μ§€λ³΄μˆ˜μ„±μ„ ν–₯μƒμ‹œν‚€λŠ” 방법, 그리고 벑터 기반 κ·Έλž˜ν”½μ˜ μž₯점을 ν™œμš©ν•˜μ—¬ μ‚¬μš©μž κ²½ν—˜μ„ κ°œμ„ ν•˜λŠ” μ „λž΅μ— λŒ€ν•΄ ꡬ체적으둜 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

SVG와 μ•„μ΄μ½˜μ˜ μž₯점

SVGλŠ” λ‹€μŒκ³Ό 같은 μ—¬λŸ¬ κ°€μ§€ μž₯점을 μ œκ³΅ν•©λ‹ˆλ‹€.

  • 해상도 독립성: SVGλŠ” 벑터 기반으둜 κ·Έλ €μ§€λ―€λ‘œ, ν™•λŒ€ν•˜κ±°λ‚˜ μΆ•μ†Œν•΄λ„ ν’ˆμ§ˆμ΄ μ €ν•˜λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ΄λŠ” λ‹€μ–‘ν•œ ν™”λ©΄ 크기와 해상도에 λŒ€μ‘ν•  λ•Œ 맀우 μœ μš©ν•©λ‹ˆλ‹€.
  • 파일 크기 μ΅œμ ν™”: λ³΅μž‘ν•œ 이미지가 μ•„λ‹Œ λ‹¨μˆœν•œ λ„ν˜•κ³Ό 경둜둜 이루어진 경우, SVG 파일의 μš©λŸ‰μ΄ 맀우 μž‘μ•„ λ‘œλ”© 속도λ₯Ό κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • μŠ€νƒ€μΌ 및 μ• λ‹ˆλ©”μ΄μ…˜ μ œμ–΄ 용이: CSSλ‚˜ μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό 톡해 SVG λ‚΄λΆ€μ˜ κ°œλ³„ μš”μ†Œλ₯Ό μ‰½κ²Œ μ‘°μž‘ν•  수 있으며, μ• λ‹ˆλ©”μ΄μ…˜ 효과λ₯Ό μ μš©ν•˜λŠ” 것도 비ꡐ적 κ°„λ‹¨ν•©λ‹ˆλ‹€.
  • SEO와 μ ‘κ·Όμ„± ν–₯상: SVGλŠ” XML 기반의 포맷이기 λ•Œλ¬Έμ—, 검색 엔진이 λ‚΄μš©μ„ μ‰½κ²Œ 인식할 수 있고, ARIA 속성을 ν™œμš©ν•˜μ—¬ 접근성을 κ°•ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈλ‘œ SVG λ³€ν™˜μ˜ ν•„μš”μ„±

λ¦¬μ•‘νŠΈ ν”„λ‘œμ νŠΈμ—μ„œ SVGλ₯Ό λ‹¨μˆœ 이미지 파일둜 μ‚¬μš©ν•˜κ²Œ 되면, μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±μ΄ λ–¨μ–΄μ§€κ³  μŠ€νƒ€μΌμ„ λ™μ μœΌλ‘œ μ μš©ν•˜κΈ° μ–΄λ ΅μŠ΅λ‹ˆλ‹€. 반면, SVGλ₯Ό λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈλ‘œ λ³€ν™˜ν•˜λ©΄ λ‹€μŒκ³Ό 같은 μž₯점이 μžˆμŠ΅λ‹ˆλ‹€.

  • μž¬μ‚¬μš©μ„±: SVG μ»΄ν¬λ„ŒνŠΈλ₯Ό λ³„λ„μ˜ λͺ¨λ“ˆλ‘œ λΆ„λ¦¬ν•˜μ—¬ μ—¬λŸ¬ κ³³μ—μ„œ μ‰½κ²Œ μž¬μ‚¬μš©ν•  수 있으며, ν•„μš”ν•œ 경우 propsλ₯Ό 톡해 색상, 크기, μ• λ‹ˆλ©”μ΄μ…˜ 등을 λ™μ μœΌλ‘œ μ‘°μ ˆν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • μœ μ§€λ³΄μˆ˜ μš©μ΄μ„±: SVG μ»΄ν¬λ„ŒνŠΈ λ‚΄λΆ€μ˜ μ½”λ“œλ₯Ό λΆ„λ¦¬ν•˜μ—¬ κ΄€λ¦¬ν•˜λ©΄, λ””μžμΈ λ³€κ²½ μ‹œ ν•΄λ‹Ή μ»΄ν¬λ„ŒνŠΈλ§Œ μˆ˜μ •ν•˜λ©΄ λ˜μ–΄ 전체 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— λ―ΈμΉ˜λŠ” 영ν–₯을 μ΅œμ†Œν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • ν†΅ν•©λœ μŠ€νƒ€μΌλ§: λ¦¬μ•‘νŠΈμ˜ μŠ€νƒ€μΌλ§ 도ꡬ(Styled Components, Emotion, CSS Modules λ“±)와 ν•¨κ»˜ μ‚¬μš©ν•˜λ©΄, SVG에 μΌκ΄€λœ ν…Œλ§ˆμ™€ μŠ€νƒ€μΌμ„ μ μš©ν•  수 μžˆμ–΄, UI/UX 톡일성이 ν–₯μƒλ©λ‹ˆλ‹€.

SVG μ»΄ν¬λ„ŒνŠΈ λ³€ν™˜ 방법

1. SVGR μ‚¬μš©ν•˜κΈ°

SVGR은 SVG νŒŒμΌμ„ λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈλ‘œ λ³€ν™˜ν•΄μ£ΌλŠ” λ„κ΅¬μž…λ‹ˆλ‹€. CLI 도ꡬ λ˜λŠ” 온라인 λ³€ν™˜κΈ°λ₯Ό μ‚¬μš©ν•˜λ©΄, 기쑴의 SVG νŒŒμΌμ„ μ†μ‰½κ²Œ μ»΄ν¬λ„ŒνŠΈλ‘œ λ³€ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μ•„λž˜μ™€ 같이 SVG νŒŒμΌμ„ λ³€ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

npx @svgr/cli --icon --replace-attr-values "#000=currentColor" icon.svg --out-dir src/icons

μœ„ λͺ…λ Ήμ–΄λ₯Ό 톡해 μƒμ„±λœ μ»΄ν¬λ„ŒνŠΈλŠ”, λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// Icon.jsx
import React from 'react';
import { ReactComponent as IconSVG } from './icon.svg';

const Icon = ({ color = 'currentColor', width = 24, height = 24, ...props }) => {
  return <IconSVG fill={color} width={width} height={height} {...props} />;
};

export default Icon;

μ΄λ ‡κ²Œ λ³€ν™˜λœ μ»΄ν¬λ„ŒνŠΈλŠ” propsλ₯Ό 톡해 λ™μ μœΌλ‘œ μƒ‰μƒμ΄λ‚˜ 크기λ₯Ό λ³€κ²½ν•  수 μžˆμ–΄, λ‹€μ–‘ν•œ μƒν™©μ—μ„œ μž¬μ‚¬μš©ν•˜κΈ° μš©μ΄ν•©λ‹ˆλ‹€.

2. 인라인 SVG μž‘μ„±ν•˜κΈ°

직접 JSX λ‚΄μ—μ„œ SVG μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ” 방법도 μžˆμŠ΅λ‹ˆλ‹€. 이 방식은 SVG νŒŒμΌμ„ 직접 μˆ˜μ •ν•˜κ³ , λ¦¬μ•‘νŠΈ μ»΄ν¬λ„ŒνŠΈ 내에 μ‚½μž…ν•  수 μžˆμ–΄, μ™ΈλΆ€ νŒŒμΌμ„ 뢈러올 ν•„μš” 없이 μ½”λ“œ μ•ˆμ—μ„œ λ°”λ‘œ μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// InlineIcon.jsx
import React from 'react';

const InlineIcon = ({ color = '#1976d2', width = 24, height = 24 }) => (
  <svg width={width} height={height} viewBox="0 0 24 24" fill={color} xmlns="http://www.w3.org/2000/svg">
    <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>
  </svg>
);

export default InlineIcon;

이 μ˜ˆμ œμ—μ„œλŠ” JSX λ‚΄μ—μ„œ 직접 SVG νƒœκ·Έλ₯Ό μž‘μ„±ν•˜μ—¬ μ•„μ΄μ½˜μ„ κ΅¬μ„±ν–ˆμŠ΅λ‹ˆλ‹€. 이 방식은 κ°„λ‹¨ν•œ μ•„μ΄μ½˜μ΄λ‚˜ λ‘œκ³ μ— μ ν•©ν•˜λ©°, CSS둜 μŠ€νƒ€μΌμ„ μ‰½κ²Œ μ‘°μ ˆν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ¦¬μ•‘νŠΈμ—μ„œ SVG 및 μ•„μ΄μ½˜ μ»΄ν¬λ„ŒνŠΈ ν™œμš© μ „λž΅

1. μŠ€νƒ€μΌλ§ 및 ν…Œλ§ˆ 적용

SVG μ»΄ν¬λ„ŒνŠΈλ₯Ό ν™œμš©ν•  λ•Œ Styled Componentsλ‚˜ Emotion 같은 CSS-in-JS 도ꡬλ₯Ό μ‚¬μš©ν•˜λ©΄, SVG의 색상, 크기, μ• λ‹ˆλ©”μ΄μ…˜ 등을 λ™μ μœΌλ‘œ μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 닀크 λͺ¨λ“œμ™€ 라이트 λͺ¨λ“œλ₯Ό μ§€μ›ν•˜λŠ” λ””μžμΈμ—μ„œλŠ” μ•„μ΄μ½˜μ˜ 색상을 ν…Œλ§ˆμ— 따라 λ³€κ²½ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// ThemedIcon.jsx
import React from 'react';
import styled, { useTheme } from 'styled-components';
import { ReactComponent as SampleIcon } from './sample.svg';

const StyledIcon = styled(SampleIcon)`
  width: ${props => props.width || '24px'};
  height: ${props => props.height || '24px'};
  fill: ${props => props.fill};
  transition: fill 0.3s ease;
`;

const ThemedIcon = ({ width, height }) => {
  const theme = useTheme();
  return <StyledIcon width={width} height={height} fill={theme.iconColor} />;
};

export default ThemedIcon;

μœ„ μ˜ˆμ œλŠ” ν…Œλ§ˆ 값을 μ‚¬μš©ν•˜μ—¬ μ•„μ΄μ½˜μ˜ 색상을 λ™μ μœΌλ‘œ λ³€κ²½ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 μΌκ΄€λœ λ””μžμΈ μ‹œμŠ€ν…œμ„ μœ μ§€ν•˜λ©΄μ„œ μ‚¬μš©μž κ²½ν—˜μ„ κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

2. μ ‘κ·Όμ„±κ³Ό SEO κ³ λ €

SVGλŠ” XML κΈ°λ°˜μ΄λ―€λ‘œ, μ μ ˆν•œ ARIA 속성을 μΆ”κ°€ν•˜λ©΄ 슀크린 리더와 같은 보쑰 기술이 μ•„μ΄μ½˜μ˜ 의미λ₯Ό 인식할 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, aria-labelμ΄λ‚˜ role="img" 속성을 μΆ”κ°€ν•˜μ—¬ μ•„μ΄μ½˜μ˜ 역할을 λͺ…ν™•νžˆ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// AccessibleIcon.jsx
import React from 'react';
import { ReactComponent as InfoIcon } from './info.svg';

const AccessibleIcon = ({ label = '정보 μ•„μ΄μ½˜', width = 24, height = 24 }) => (
  <InfoIcon width={width} height={height} role="img" aria-label={label} />
);

export default AccessibleIcon;

이와 같이 μ ‘κ·Όμ„± 속성을 μΆ”κ°€ν•˜λ©΄, λͺ¨λ“  μ‚¬μš©μžμ—κ²Œ μΉœν™”μ μΈ UIλ₯Ό κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

3. μ„±λŠ₯ μ΅œμ ν™”

SVGλŠ” 벑터 κ·Έλž˜ν”½μ΄κΈ° λ•Œλ¬Έμ—, ν”½μ…€ 기반 이미지에 λΉ„ν•΄ 파일 크기가 μž‘κ³ , λΈŒλΌμš°μ €μ—μ„œ λΉ λ₯΄κ²Œ λ Œλ”λ§λ©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ³΅μž‘ν•œ SVGλ₯Ό μ‚¬μš©ν•  경우, λΆˆν•„μš”ν•œ DOM μš”μ†Œκ°€ λ§Žμ•„μ§ˆ 수 μžˆμœΌλ―€λ‘œ, μ½”λ“œ μŠ€ν”Œλ¦¬νŒ…μ΄λ‚˜ 인라인 μ΅œμ ν™”λ₯Ό 톡해 μ„±λŠ₯을 κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, λΆˆν•„μš”ν•œ 메타데이터λ₯Ό μ œκ±°ν•˜κ±°λ‚˜, μ΅œμ ν™”λœ SVG μ½”λ“œλ‘œ λ³€ν™˜ν•˜λŠ” μž‘μ—…μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

벑터 기반 κ·Έλž˜ν”½μ˜ UI/UX κ°œμ„  효과

벑터 기반 κ·Έλž˜ν”½μ˜ κ°€μž₯ 큰 μž₯점은 해상도에 λ…λ¦½μ μ΄λΌλŠ” μ μž…λ‹ˆλ‹€. μ΄λŠ” λ‹€μŒκ³Ό 같은 UI/UX κ°œμ„  효과λ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€.

  • λ°˜μ‘ν˜• λ””μžμΈ: SVG μ•„μ΄μ½˜μ€ ν™”λ©΄ 크기에 상관없이 μ„ λͺ…ν•˜κ²Œ λ Œλ”λ§λ˜λ―€λ‘œ, λͺ¨λ°”일, νƒœλΈ”λ¦Ώ, λ°μŠ€ν¬νƒ‘ λ“± λ‹€μ–‘ν•œ λ””λ°”μ΄μŠ€μ—μ„œ μΌκ΄€λœ κ²½ν—˜μ„ μ œκ³΅ν•©λ‹ˆλ‹€.
  • μ• λ‹ˆλ©”μ΄μ…˜ 및 μΈν„°λž™μ…˜: SVG λ‚΄λΆ€μ˜ 각 μš”μ†Œλ₯Ό κ°œλ³„μ μœΌλ‘œ μ œμ–΄ν•  수 있기 λ•Œλ¬Έμ—, μ„Έλ°€ν•œ μ• λ‹ˆλ©”μ΄μ…˜ νš¨κ³Όλ‚˜ μΈν„°λž™μ…˜μ„ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 μ‚¬μš©μžμ—κ²Œ 동적인 ν”Όλ“œλ°±μ„ μ œκ³΅ν•˜κ³ , μΈν„°λž™μ…˜μ˜ 즐거움을 더할 수 μžˆμŠ΅λ‹ˆλ‹€.
  • λΈŒλžœλ“œ 일관성 μœ μ§€: SVGλ₯Ό ν™œμš©ν•˜λ©΄, λ‘œκ³ λ‚˜ μ•„μ΄μ½˜μ˜ λ””μžμΈμ„ μ€‘μ•™μ—μ„œ 관리할 수 μžˆμ–΄, λΈŒλžœλ“œ 아이덴티티λ₯Ό μΌκ΄€λ˜κ²Œ μœ μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ²°λ‘ 

λ¦¬μ•‘νŠΈμ—μ„œ SVG와 μ•„μ΄μ½˜ μ»΄ν¬λ„ŒνŠΈλ₯Ό ν™œμš©ν•˜λŠ” 것은 ν™•μž₯μ„±κ³Ό μž¬μ‚¬μš©μ„±μ„ κ·ΉλŒ€ν™”ν•˜λŠ” λ™μ‹œμ—, 해상도 독립적인 UIλ₯Ό κ΅¬ν˜„ν•˜λŠ” 데 맀우 효과적인 μ „λž΅μž…λ‹ˆλ‹€. SVGR을 μ‚¬μš©ν•œ μžλ™ λ³€ν™˜, 인라인 SVG μž‘μ„±, 그리고 Styled Componentsλ‚˜ Emotionκ³Ό κ²°ν•©ν•˜μ—¬ 동적 ν…Œλ§ˆ 적용, μ ‘κ·Όμ„± κ°•ν™”, μ„±λŠ₯ μ΅œμ ν™” λ“±μ˜ λ‹€μ–‘ν•œ 이점을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ μ ‘κ·Ό 방식은 μ‚¬μš©μž κ²½ν—˜(UX) κ°œμ„ κ³Ό ν•¨κ»˜, μœ μ§€λ³΄μˆ˜μ„±μ΄ λ›°μ–΄λ‚œ μ½”λ“œλ² μ΄μŠ€λ₯Ό κ΅¬μΆ•ν•˜λŠ” 데 크게 κΈ°μ—¬ν•©λ‹ˆλ‹€.

μ‹€μ œ ν”„λ‘œμ νŠΈμ—μ„œλŠ” λ””μžμΈ μ‹œμŠ€ν…œκ³Ό μ—°κ³„ν•˜μ—¬, μ•„μ΄μ½˜ 및 SVG μ»΄ν¬λ„ŒνŠΈλ₯Ό μ€‘μ•™μ—μ„œ κ΄€λ¦¬ν•˜κ³  μΌκ΄€λœ μŠ€νƒ€μΌμ„ μ μš©ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€. λ˜ν•œ, μ‚¬μš©μž ν”Όλ“œλ°±κ³Ό μ ‘κ·Όμ„± ν…ŒμŠ€νŠΈλ₯Ό 톡해 μ§€μ†μ μœΌλ‘œ κ°œμ„ ν•΄ λ‚˜κ°€λ©΄, λͺ¨λ“  λ””λ°”μ΄μŠ€μ—μ„œ μš°μˆ˜ν•œ ν’ˆμ§ˆμ˜ UIλ₯Ό μ œκ³΅ν•  수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

λ¦¬μ•‘νŠΈ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 개발 μ‹œ, SVG와 μ•„μ΄μ½˜ μ»΄ν¬λ„ŒνŠΈ ν™œμš©λ²•μ„ 적극 λ„μž…ν•˜μ—¬, 벑터 기반 κ·Έλž˜ν”½μ˜ μž₯점을 μ΅œλŒ€ν•œ ν™œμš©ν•˜μ‹œκΈΈ λ°”λžλ‹ˆλ‹€. 이λ₯Ό 톡해 고해상도 λ””μŠ€ν”Œλ ˆμ΄μ—μ„œλ„ μ„ λͺ…ν•œ UIλ₯Ό μœ μ§€ν•˜κ³ , μ‚¬μš©μžμ™€μ˜ μΈν„°λž™μ…˜μ„ λ”μš± ν’λΆ€ν•˜κ²Œ λ§Œλ“€μ–΄ λ³΄μ„Έμš”.

λ°˜μ‘ν˜•

λŒ“κΈ€