[React] SVG Sprite 사용법 (StyledComponent)
사파리에서 아이콘이 작게 나타나는 오류있음. 따라하지 마세요
이슈
SVG를 더 편하게 import하고 싶었다. SVG type을 미리 지정해두고, 자동완성이 되게 만드는 것이 목표였다.
기존의 방법
import arrowRight from "@/shared/icons/arrow_right.svg"
...
export const ArrowRightIcon = () =>{
return <img src={arrowRight} />
}
모든 아이콘에 설정해주기란 너무 귀찮다. sprite로 큰 이미지에서 id로 참조하는 방식으로 보다 쉽게 만들고 싶었다.
해결방법
SVG Sprite를 사용해 SVG를 묶음으로 만든 뒤 id를 참조해서 사용하는 방식으로 해결했다. 아래를 따라오면 해결할 수 있다.
1. 피그마에서 SVG를 Sprite형식으로 가져오기
1-1. 플러그인 설치
SVG를 Sprite형식으로 쉽게 가져올 수 있는 플러그인을 설치하자.
https://www.figma.com/community/plugin/814345141907543603/svg-export
1-2. 아이콘 세팅
피그마에서 아이콘을 만든 뒤 아래 1번이나 2번 처럼 계층구조를 만들어둔다. 둘 다 잘되는 것은 확인했다!
예시 1. 에셋화 안한 아이콘들
예시 2. 에셋화 된 아이콘들
1-3. Sprite로 내보내기
아이콘 그룹을 위의 예시처럼 드래그한 이후 Sprite sheet를 선택 후 Export all을 누른다.
주의: 전체가 group이 되어있으면 안됨, 개별그룹
아래 예시처럼 분리해서 내보내기 해야 id가 잘 들어간다.
1-4. 파일 확인
아래처럼 svg아래에 symbol의 id가 생성되면 성공적으로 추출되었다!
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<defs>
<symbol id="search" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path
fill="#62626D"
d="m21.85 20.151-4.608-4.607a8.53 8.53 0 0 0 1.736-5.156c0-4.736-3.854-8.589-8.589-8.589C5.653 1.8 1.8 5.653 1.8 10.389c0 4.735 3.853 8.589 8.589 8.589a8.533 8.533 0 0 0 5.156-1.736l4.607 4.607a1.197 1.197 0 0 0 1.697-.001 1.201 1.201 0 0 0 0-1.697ZM4.2 10.389A6.196 6.196 0 0 1 10.39 4.2a6.195 6.195 0 0 1 6.188 6.188 6.195 6.195 0 0 1-6.188 6.188 6.194 6.194 0 0 1-6.19-6.187Z"
/>
</symbol>
...
</defs>
</svg>
1-5. fill 변경
fill속성이 들어있는 경우 덮어씌우려고 해도, svg에 지정되어있는 색이 우선순위가 된다. 다음처럼 fill="currentColor"
로 바꿔주자.
...
<symbol id="search" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
<path fill="currentColor" d="m21.85 20.151-4.608-4.607a8.53 8.53 0 0 0 1.736-5.156c0-4.736-3.854-8.589-8.589-8.589C5.653 1.8 1.8 5.653 1.8 10.389c0 4.735 3.853 8.589 8.589 8.589a8.533 8.533 0 0 0 5.156-1.736l4.607 4.607a1.197 1.197 0 0 0 1.697-.001 1.201 1.201 0 0 0 0-1.697ZM4.2 10.389A6.196 6.196 0 0 1 10.39 4.2a6.195 6.195 0 0 1 6.188 6.188 6.195 6.195 0 0 1-6.188 6.188 6.194 6.194 0 0 1-6.19-6.187Z"/>
</symbol>
...
2. React에서 사용하기
아래는 내가 사용한 SvgIcon 전문이다.
import Svgs from "@/shared/svgs/sprites.svg";
import { HTMLAttributes } from "react";
import styled from "styled-components";
export type SVGIconType =
| "search"
| "home"
| "benefit"
| "pay"
| "stock"
| "line_three"
| "heart"
| "arrow_right"
| "rocket"
| "increase"
| "pot"
| "korea"
| "usa"
| "graduate"
| "factory"
| "vehicle"
| "meat"
| "clothes"
| "cosmetic"
| "fire"
| "toss"
| "default_profile";
export interface SVGIconProps extends HTMLAttributes<SVGElement> {
iconId: SVGIconType;
size?: string;
color?: string;
}
const Svg = styled.svg`
position: relative;
`;
const Use = styled.use`
position: absolute;
bottom: 0;
right: 0;
`;
export const SvgIcon = ({
iconId,
size = "100%",
color,
...props
}: SVGIconProps) => (
<Svg color={color} width={size} height={size} {...props}>
<Use href={`${Svgs}#${iconId}`} width={size} height={size} />
</Svg>
);
2-1. 주의해서 봐야할 곳 1
svg안에 use라는 계층구조에서 href id값을 참조해서 해결하는 것을 파악할 수 있다.
<svg color={color} width={size} height={size} {...props}>
<use href={`${Svgs}#${iconId}`} width={size} height={size} />
</svg>
2-1. 주의해서 봐야할 곳 2
id들을 미리 type으로 지정해두고 사용하면 typescript의 자동완성을 사용할 수 있다.
export type SVGIconType =
| "search"
| "home"
| "benefit"
| "pay"
| "stock"
| "line_three"
| "heart"
| "arrow_right"
| "rocket"
| "increase"
| "pot"
| "korea"
| "usa"
| "graduate"
| "factory"
| "vehicle"
| "meat"
| "clothes"
| "cosmetic"
| "fire"
| "toss"
| "default_profile";