[React-Native] react-native-svg를 활용한 아이콘 컴포넌트 사용 및 관리
프론트 개발을 할 때 마다 늘 아이콘을 어떻게 관리해야 할 지 고민이 되었다.
아이콘 파일이 한두개도 아니고, 또 아이콘마다 사이즈도 다 다르고,
같은 아이콘인데 상태별로 컬러도 다르다보니
어떻게 하면 아이콘을 좀 더 효율적으로 관리할 수 있을지 여러 방법을 찾아보고 시도도 해보았다.
리액트 네이티브 프로젝트를 개발하면서 아이콘을 어떻게 관리할 지 고민하다가,
react-native-svg를 통해 svg 파일로 아이콘 컴포넌트를 만들어 사용해보기로 했다.
1. react-native-svg 설치
npm install react-native-svg
2. 아이콘 파일 저장
/assets/icons 하위에 사용할 아이콘 파일들을 svg 형태로 저장해준다.
3. index.ts 파일에 아이콘 관리
그리고 아이콘을 저장해둔 위치에, index.ts 파일을 생성하여 여기서 아이콘 이름들을 설정하고 관리해준다.
export { default as CheckboxIcon } from './icon-checkbox.svg';
export { default as CheckboxActiveIcon } from './icon-checkbox-active.svg';
export { default as SubmitIcon } from './icon-submit.svg';
export { default as AdminIcon } from './icon-admin.svg';
export { default as ArrowDownIcon } from './icon-arrow-down.svg';
export { default as ArrowDownDisabledIcon } from './icon-arrow-down-disabled.svg';
....
4. 아이콘 컴포넌트 생성
import { theme } from '@styles';
import * as Icons from '@assets/icons';
type IconName = keyof typeof Icons;
export type ThemeColorKey = keyof typeof theme.color;
type Props = {
name?: IconName;
width?: number;
height?: number;
color?: ThemeColorKey | string;
};
const Icon: React.FC<Props> = ({ name, width, height, color }: Props) => {
if (!name) return null;
const IconComponent = Icons[name];
if (!IconComponent) {
return null;
}
return <IconComponent width={width} height={height} color={color} />;
};
export default Icon;
react-native-svg는 svg파일을 리액트 컴포넌트처럼 사용할 수 있도록 해주기 때문에,
예를 들어 icon-checkbox.svg를 <CheckboxIcon /> 와 같은 형식으로 바로 사용할 수 있다.
이렇게 사용해도 됐겠지만, 통일성을 위해서 <Icon /> 이라는 컴포넌트를 별도로 만들었다.
그리고 Icons로 저장해둔 모든 아이콘들을 import 했고,
IconComponent라는걸 만들고 아이콘의 이름을 넣어주면, 그 이름을 받아와서 컴포넌트가 될 수 있도록 해주었다.
width, height, color props를 만들어서 각각 사이즈와 컬러도 변경할 수 있도록 했다.
color를 props로 사용 가능하려면, svg 파일을 열어서 svg, path 등에 있는 fill의 컬러를 지우고 currentColor로 변경해주어야 한다.
(예: <svg width=".." height=".." fill="currentColor"......>
5. 아이콘 컴포넌트 사용
실제 개별 페이지에서 사용할 때는 다음과 같이 사용해주면 된다.
<Icon name="CheckboxIcon" width={20} height={20} />
조건문으로 사용하는 것도 가능하다.
<Icon name={ checked ? 'CheckboxActiveIcon' : 'CheckboxIcon' } width={20} height={20} />
최선의 방법인지는 잘 모르겠지만,
우선은 같은 아이콘일때 상태별로 컬러만 달라서 그 컬러가 다른 아이콘들을 일일이 저장하는 수고는 덜어졌다.
그리고 <View> 같은 컴포넌트에 ImageBackground 등으로 일일이 이미지를 넣어주거나,
웹에서 style에 background-image 등으로 넣는 방법보다는 훨씬 나은 것 같다.
더 나은 방법이 있는 지 좀 더 고민해봐야 할 것 같다.