React SVG 아이콘 자동화 작업 도입 배경 및 경험

R정우·2025년 3월 13일
16

React

목록 보기
2/4


최근 프로젝트에서 SVG 아이콘을 지속적으로 추가하거나 수정하는 과정에서, 각 아이콘 파일의 색상 속성 관리가 번거롭다는 문제를 경험하였습니다.

디자이너와의 협업 툴로서 Figma를 활용하는데, SVG 파일들은 디자인 작업에 초점을 맞추다 보니, 고정된 색상 속성이 포함되어 있거나 태그별로 서로 다른 방식의 fill 설정이 적용되어 있었습니다. 이러한 특성 때문에 다크 모드나 테마 변경과 같은 다양한 환경에서 아이콘 색상이 상위 요소의 색상을 원활하게 상속받지 못하는 문제가 발생하였습니다.

또한, 프로젝트가 진행될수록 아이콘 파일의 수가 증가함에 따라, 매번 수동으로 아이콘을 관리하는 것이 점점 비효율적으로 느껴졌습니다. 이에 따라 SVG 파일의 fill 속성을 자동으로 수정하고, 아이콘들을 손쉽게 컴포넌트화할 수 있는 자동화 스크립트를 작성하게 되었습니다.


문제 상황

1. 고정된 색상 속성 문제

디자인 파일에서 내보낸 SVG 아이콘은 <svg> 태그 및 기타 태그에 고정된 fill 속성이 설정되어 있었습니다. 이로 인해 상위 컴포넌트의 색상 변경을 반영하지 못하고, 다크 모드나 테마 변경에 제약이 생겼습니다.

2. 다양한 태그의 fill 처리

SVG 파일 내에는 <circle>, <path> 등 여러 태그가 존재하며, 각각의 태그마다 fill 속성이 지정되어 있었습니다. 이 경우 일괄적인 색상 상속 처리가 어려워, 모든 아이콘에서 일관된 디자인을 유지하기가 힘들었습니다.

3. 수동 관리의 불편함

아이콘 파일이 지속적으로 추가되면서, 개발자가 일일이 수정해야 하는 작업이 번거로워졌습니다. 또한, 새로운 아이콘이 추가될 때마다 컴포넌트 import/export를 위한 코드를 수동으로 작성하는 것도 오류가 발생하기 쉬운 작업이었습니다.


해결 방법

1. fill 속성 자동 수정 스크립트

첫 번째 스크립트는 SVG 파일의 내용을 읽어들인 후, <svg><circle> 태그의 fill 속성을 ‘currentColor’로 변경하고, <path> 태그 내의 fill 속성을 제거하는 방식으로 작성되었습니다. 이를 통해 상위 요소의 색상이 자동으로 상속되도록 하여, 다크 모드나 테마 변경에도 유연하게 대응할 수 있게 되었습니다.

const fs = require("fs")
const path = require("path")
const svgDir = path.join(__dirname, "../../assets/icon")

const updateSvgFile = (filePath) => {
  // 파일 읽기
  const svgContent = fs.readFileSync(filePath, "utf-8")

  // <svg> 태그 내의 fill 속성을 currentColor로 변경
  let updatedContent = svgContent.replace(/<svg([^>]+)fill="[^"]*"/, '<svg$1fill="currentColor"')
  // <circle> 태그 내의 fill 속성을 currentColor로 변경
  updatedContent = updatedContent.replace(/<circle([^>]+)fill="[^"]*"/g, "<circle$1fill='currentColor'")
  
  // <path> 태그 내의 fill 속성 제거
  updatedContent = updatedContent.replace(/<path([^>]+)fill="[^"]*"/g, "<path$1")
  
  // 파일 쓰기
  fs.writeFileSync(filePath, updatedContent, "utf-8")
}

// 디렉토리 내의 모든 SVG 파일 처리
const updateAllSvgFiles = (dir) => {
  fs.readdirSync(dir).forEach((file) => {
    const filePath = path.join(dir, file)
    if (fs.statSync(filePath).isFile() && path.extname(file) === ".svg") {
      updateSvgFile(filePath)
    }
  })
}

updateAllSvgFiles(svgDir)

이 스크립트를 실행하면, Figma에서 다운로드 받은 최신 아이콘 폴더만 교체해주면 자동으로 모든 SVG 파일의 fill 속성이 일관되게 관리되어, 개발 과정에서의 오류를 줄이고 디자인의 통일성을 확보할 수 있었습니다.

2. 자동 index 파일 생성 스크립트

두 번째 스크립트는 아이콘 폴더 내의 모든 SVG 파일을 불러와 자동으로 index.ts 파일을 생성합니다. 기존에는 새로운 아이콘이 추가될 때마다 수동으로 import 및 export 코드를 작성해야 했으며, 이 과정에서 오타나 누락이 발생할 위험이 있었습니다.

자동화 스크립트는 파일 이름을 파스칼 케이스로 변환하여 각 SVG 파일을 React 컴포넌트처럼 불러올 수 있도록 import 구문과 export 구문을 생성합니다. 이를 통해 개발자는 아이콘 추가 시 번거로운 코딩 작업에서 벗어나, 파일 교체만으로 손쉽게 최신 아이콘을 반영할 수 있게 되었습니다.

const fs = require("fs")
const path = require("path")

const svgDir = path.join(__dirname, "../../assets/icon")
const indexFile = path.join(svgDir, "index.ts")

const toPascalCase = (str) => {
  return str
    .split(/[-_]/)
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
    .join("")
}

const generateIndex = () => {
  // SVG 파일 목록 가져오기
  const svgFiles = fs.readdirSync(svgDir).filter((file) => file.endsWith(".svg"))

  // index.ts 파일 내용 생성
  let indexContent = "// This file is auto-generated. Do not edit manually\n\n"

  // 각 SVG 파일에 대한 import 구문 생성
  svgFiles.forEach((file) => {
    const componentName = toPascalCase(path.basename(file, ".svg"))
    indexContent += `import ${componentName} from './${file}?react'\n`
  })

  // export 구문 생성
  indexContent += "\nexport {\n"
  svgFiles.forEach((file) => {
    const componentName = toPascalCase(path.basename(file, ".svg"))
    indexContent += `  ${componentName},\n`
  })
  indexContent += "}\n"

  // 파일 쓰기
  fs.writeFileSync(indexFile, indexContent, "utf-8")
  console.log("Successfully generated index.ts for SVG files")
}

generateIndex()

위 스크립트를 실행했을 때 생성되는 파일의 결과입니다.

// This file is auto-generated. Do not edit manually

import IcAdd from './ic_add.svg?react'
import IcArrange from './ic_arrange.svg?react'
import IcBack from './ic_back.svg?react'
import IcBookmark from './ic_bookmark.svg?react'
...

export {
  IcAdd,
  IcArrange,
  IcBack,
  IcBookmark,
  ...
}

결과 및 소감

이와 같이 자동화 스크립트를 도입한 결과, Figma에서 최신 아이콘 폴더만 교체한 후 스크립트를 실행하면 SVG 파일의 색상 속성이 일관되게 관리되고, React 컴포넌트 형태로 손쉽게 불러올 수 있게 되었습니다. 초기에는 아이콘 파일의 속성 수정과 수동 import/export 작업으로 인해 오류와 번거로움이 잦았지만, 자동화 도구를 통해 이러한 문제를 효과적으로 해결할 수 있었습니다.

특히, 디자이너와의 긴밀한 소통을 통해 ic_some.svg와 같은 파일 형식이 단순히 자동으로 생성된 결과가 아니라, 디자인 팀과 개발 팀이 협력하여 합의한 결과물임을 다시 한 번 확인할 수 있었습니다. 또한, 자동 index 파일 생성 스크립트를 도입함으로써, 새로운 아이콘 추가 시 발생할 수 있는 코드 관리 문제를 미연에 방지할 수 있었고, 팀원 간의 협업 효율성도 크게 향상되었습니다.

이와 같은 경험을 공유드리며, 유사한 문제로 어려움을 겪고 계신 분들께 본 사례가 도움이 되기를 바랍니다.

profile
시행착오를 즐기는 프론트엔드 개발자입니다!

0개의 댓글