프로젝트와 Storybook에 SVGR 설정하기
치스톡 프로젝트를 진행하면서 SVGR을 사용해야할 일이 생겼다.
오늘은 Next.js기반 프로젝트와 Storybook에 SVGR을 설정하는 방법을 적어보려한다.
SVGR이란?
SVG는 벡터 기반의 이미지 파일로, 용량이 작고 크기를 바꿔도 이미지가 깨지지 않기 때문에 웹에서 자주 사용되는 이미지 포맷이다.
이 SVG를 Next.js 기반 프로젝트에서 사용하기 위해서는 크게 2가지 방법을 통해 가져올 수 있다.
하나는, svg 파일의 경로를 img 파일의 src 속성에 넣어 img 태그와 함께 사용하는 방법이고,
다른 하나는 svg 파일을 JSX 형태인 리액트 컴포넌트로 바꿔서 이를 불러와 사용하는 방법이다.
두 방법 모두 장·단이 있지만, svg를 리액트 컴포넌트 형태로 불러와 사용하면
props를 통해 크기, 색상 등을 커스텀할 수 있어 svg를 보다 다루게 쉽게 만들어준다.
const AddIcon = ({ props }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
height="48"
viewBox="0 -960 960 960"
width="48"
{...props}
>
<path d="M450-450H200v-60h250v-250h60v250h250v60H510v250h-60v-250Z" />
</svg>
);
export default AddIcon;
그러나, svg 파일을 JSX로 일일이 수동으로 변환하는 것은 생각보다 귀찮은 일이다.
svg 파일 내부의 태그들을 가져와 이를 다시 감싸는 방식으로 일일이 컴포넌트를 만들어줘야하기 때문인데,
아이콘이 많아질수록 이런 작업을 모든 아이콘에 작업하는 것은 굉장히 힘들고 비효율적인 일이 된다.
더군다가 svg 내부에 미리 지정되어있는 속성들이 있다면 props를 통해 svg를 조절하기도 까다로워
컴포넌트를 통해 자유자재로 svg 파일을 다루기 위해서는 여러가지 후처리가 필요하다.
SVGR은 이런 작업을 자동으로 처리해주는 라이브러리리다.
SVGR은 여러가지 환경에서 단독으로도 사용할 수 있지만,
프로젝트에서 사용할 때는 주로 @svgr/webpack 이라는 웹팩 로더 사용하여 작업한다.
Next.js에 SVGR 설정하기
yarn add --dev @svgr/webpack
먼저, 위 명령어를 통해 @svgr/webpack을 설치해준다.
//next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack(config) {
config.module.rules.push({
test: /\.svg$/i,
use: ["@svgr/webpack"],
});
return config;
},
...
}
그 다음, next.config.js에 webpack 설정을 추가해준다.
svgr 공식 문서에서는 issuer 속성이 포함되어있기도 한데,
issuer가 있으면 svg 파일을 못 읽는 에러가 발생할 수 있으니 주의하자.
이렇게 설정해주면, svg 파일을 아래와 같이 리액트 컴포넌트처럼 사용할 수 있게 된다.
import SyncProblem from "@assets/icons/syncProblem.svg";
export default function Home() {
return (
<div>
<SyncProblem />
</div>
);
}
그런데 만약 타입스크립트를 사용하고 있다면, 추가적인 작업이 필요하다.
SyncProblem에 대한 타입이 지정되어있지 않기 때문이다.
이는 TypeScript 상에서 .svg로 불러오는 컴포넌트에 대한 타입이 지정되어있지 않기 때문에 발생하는 문제다.
global.d.ts에 .svg 파일에 대한 타입을 선언해서 이를 해결해줄 수 있다.
//global.d.ts
declare module "*.svg" {
const content: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
export default content;
}
// tsconfig.json
{
....
"include": [
"global.d.ts", // 앞에 추가
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
],
"exclude": ["node_modules"]
}
먼저, 프로젝트 최상위 폴더에서 global.d.ts 파일을 만들어 .svg로 불러오는 모듈에 대한 타입을 설정해준다.
그 후 tsconfig.json에 global.d.ts를 포함시켜 TypeScript에서 이를 인식할 수 있도록 include 앞에 추가하면 된다.
이후 확인해보면, SyncProblem의 타입이 잘 정의된 것을 확인할 수 있다.
(잘 안 될 경우, VSCode를 껏다가 켜보자)
Storybook에 SVGR 설정하기
svg 파일을 컴포넌트로 사용할 수 있도록 Next.js에서는 잘 설정했지만,
Storybook에서는 정상적으로 불러오지 못하는 모습을 볼 수 있다.
이는 Storybook이 Next.js와는 별도의 웹팩을 사용하고 있기 때문이다.
즉, Storybook에 svgr과 관련된 webpack 설정을 추가해주어야한다.
//main.ts
import type { StorybookConfig } from "@storybook/nextjs";
const config: StorybookConfig = {
...
webpackFinal: async (config) => {
const imageRule = config.module?.rules?.find((rule) => {
const test = (rule as { test: RegExp }).test;
if (!test) {
return false;
}
return test.test(".svg");
}) as { [key: string]: any };
imageRule.exclude = /\.svg$/;
config.module?.rules?.push({
test: /\.svg$/,
use: ["@svgr/webpack"],
});
return config;
},
};
export default config;
./storybook/main.ts에 위 코드를 설정해주면 된다.
이후 Storybook에서 svg 파일을 불러와 사용해보면, 정상적으로 불러와지는 것을 확인할 수 있다.
연관 글
Reference
'Frontend > 기타' 카테고리의 다른 글
prettier로 import 정렬하기 (0) | 2023.09.01 |
---|---|
husky로 git hook 만들기(with lint-staged, git-cz) (0) | 2023.08.25 |
VSCode에서 ESLint & Prettier 설정하기 (0) | 2023.07.20 |
프론트엔드 개발 환경 기초 설정 (0) | 2023.07.19 |
[Error] yarn : 이 시스템에서 스크립트를 실행할 수 없으므로 ... (0) | 2023.04.04 |