현재 서비스의 클라이언트 프로젝트는 에셋은 거의 모든 것을 svg 파일을 사용하고 있는데, svg를 프로젝트에 유연하게 적용시키기 위해 여러가지 도전을 해봤던 것 같다.
svg 파일을 Img 태그에 그대로 넣어 사용하기거나 svg를 임포트 해서 컴포넌트로 만들어 보기도 했었다.
컴포넌트화 시킨 svg 를 또 잘 활용할 수는 없을까 해서 current value 를 이용해 svg 프롭에 직접 접근하여 관리하는 방식도 고민했었는데 이건 디자인 쪽에서 넘어오는 에셋들이 current 를 사용해 관리하기 힘든 구조였기 때문에 사용하지는 못했다 (svg 스타일의 통일성 부족)
vscode를 통해 코드 작성을 하는데, 에셋은 자동 임포트가 또 작동되지 않아서 파일 위치 찾아서 하나하나 경로 보고 import 문 작성해야 하는 것도 번거로웠을 뿐더러 꼭 아래와 같이 네임스페이스를 지정해주어야 하는 문제가 있었다.
import { ReactComponent as Icon } from 'assets/icon.svg';
<Icon />
물론 할 수야 있지만... svg 파일 프로젝트에 집어 넣는 것도 귀찮은데 임포트까지 이렇게 섬세하게 하고 싶진 않다 라는 생각이 들었고, svg를 관리하기 좋은 방법을 찾아 다니다가 svgr (react-svgr) 라이브러리를 발견했다.
SVGR - Transforms SVG into React Components. - SVGR
Transforms SVG into React Components.
react-svgr.com
svg 에셋을 넣으면 react에서 사용 가능한 컴포넌트로 만들어주는 라이브러리라고 이해하면 쉬울 듯 하다.
프론트엔드로서는 혼자 프로젝트를 담당하게 되면서 프로젝트의 설계나 스택 구조 등을 계속 생각하고 만들어내느라 프로젝트 초반에 꽤나 골머리를 앓고 있었는데, 그때 이 라이브러리를 발견하고 꽤나 기분이 좋았던 기억이 난다 (사실 많이 좋았다)
단 한 가지 고민이었던 포인트는 기존 네이밍 컨벤션 때문이었는데,
svg를 컴포넌트로 만드는 경우 그 컴포넌트의 이름 끝에는 Icon이라는 접미사를 붙여 svg 컴포넌트와 다른 컴포넌트를 구별하고 있었으나, svgr 라이브러리의 기본 설정대로 사용 시 원하는 네이밍 방식으로 받을 수 없었다.
이 문제를 해결하기 위해 라이브러리의 configure 를 훑어보니 커스텀 템플릿을 통해 변환이 가능한 듯 하여 컨벤션에 맞는 파일을 만들 수 있도록 템플릿을 작성했다.
svgr.index.template.js
const path = require('path');
function defaultIndexTemplate(filePaths) {
const exportEntries = filePaths.map(filePath => {
function camelize(str) {
return str[0].toUpperCase() + str.slice(1);
}
const basename = path.basename(filePath, path.extname(filePath));
const exportName = /^\d/.test(basename) ? `Svg${basename}` : basename;
return `export { default as ${camelize(
exportName,
)}Icon } from './${basename}'`;
});
return exportEntries.join('\n');
}
module.exports = defaultIndexTemplate;
카멜케이스와 'Icon' 접미사가 적용된 index 파일을 만드는 템플릿이다.
카멜케이스는 간단하게 적용하고 싶었는데 config에 나와있는 방법으로는 적용이 안돼서 템플릿에 같이 구현했다.
svgr.template.js
const template = (variables, {tpl}) => {
return tpl`
${variables.imports.slice(1)};
${variables.interfaces};
const ${variables.componentName} = (${variables.props}) => (
${variables.jsx}
);
${variables.exports};
`;
};
module.exports = template;
svg 에셋을 JSX 파일로 만들어주는 템플렛이다.
그리고 package.json 에 아래 script 를 추가 해 원하는 형태의 파일을 만들어 낼 수 있었다.
{
"scripts" : {
"icons": "npx @svgr/cli --out-dir src/components/icons -- src/assets",
}
}
src/assets 경로에 svg 파일을 넣어 놓을테니 src/components/icons 에 만들어 주세요 라는 의미이다.
성공적으로 실행이 되면 아래와 같이 svg 파일이 템플렛의 요구사항대로 생성되어있음을 확인할 수 있다.
실 사용 시 아래와 같이 간단하게 사용하면 된다.
svgr을 쓰지 않았던 때를 상상하기 싫을 정도로.. 이제 만들어진 컴포넌트를 그저 임포트 해서 사용하는 것이 너무 익숙하고 또 편해져 버렸다.
그러다 svg가 아닌 다른 형식의 소스를 보여줘야 할 때 img 태그에 넣으려고 직접 경로 찾아 임포트 문을 작성하고 있을 때가 돼서야 '아..엄청 귀찮네..' 하는 생각이 들곤 한다.
그래도 제일 많이 쓰는 svg를 편하게 쓸 수 있음에 감사하다..
그러니 뜬금없지만 과거의 나를 칭찬해줘야겠다.
게으른 자가 세상을 지배한다!!!
'Code > React - Node' 카테고리의 다른 글
[React] 웹뷰 에서 브릿지 통신으로 IOS/Android 위치 권한 받기 (kotlin / swift) (0) | 2023.10.01 |
---|---|
[React] AF 플러그인으로 애니메이션 간단 구현 (lottie / bodymovin / adobe effects) (1) | 2023.09.17 |
[React/node] 하드코딩 방어하기 _ notion 문서 react 렌더링 (html-react-parser) (0) | 2023.09.10 |
[React/node] 한글 욕설 필터링 기능 구현하기 (node csv 파일 변환) (0) | 2023.09.09 |
[React / Typescript] IOS safari 상태바 색상 변경 / 커스텀 훅을 이용한 동적 처리 (0) | 2022.12.09 |