icons/*.svg, icons/*.json). 그런데 이 단순한 원본에서 React·Vue·Svelte·Angular·Solid·Preact·React Native·Astro·순수 자바스크립트·정적 SVG/폰트까지 10개가 넘는 프레임워크별 패키지가 자동으로 "찍혀 나온다." 사람이 각 프레임워크용 코드를 손으로 짜는 게 아니라, 빌드 스크립트가 SVG를 읽어 각 프레임워크에 맞는 컴포넌트 코드를 생성하는 구조다.
lucide-icons/lucide · 라이선스 ISC(Feather 유래 아이콘 일부는 MIT 병기) · 아이콘 수 1,756개(대기 중인 lab/ 후보 356개 별도) · 카테고리 42종 · pnpm 모노레포(패키지 14개) · Node ≥24.11 · 최신 커밋 4aec3f8(2026-07-25) · npm 실배포 버전 1.27.0 · 정리 기준일 2026-07-29)
Lucide는 아이콘 라이브러리다. 우리가 앱에서 매일 보는 돋보기(검색), 톱니바퀴(설정), 하트(좋아요) 같은 작은 선 그림들을 일관된 스타일로 통일해서 모아 놓고, 개발자가 코드 한 줄로 가져다 쓸 수 있게 포장해 놓은 프로젝트다. AI도 서버도 아니고, 순수하게 "그림 파일 + 그걸 각 프로그래밍 언어 코드로 바꿔주는 자동화 도구"다.
실제로 저장소를 열어 보면 핵심 폴더는 icons/ 하나뿐이다. 그 안에 아이콘 이름별로 activity.svg(그림 자체)와 activity.json(이름·태그·카테고리 같은 부가 정보)이 쌍으로 1,756벌 들어 있다. 이 폴더가 유일한 원본(source of truth)이고, packages/ 아래 있는 React용·Vue용·Svelte용 패키지들은 전부 이 원본을 재료 삼아 빌드 시점에 자동 생성된 결과물이다.
아이콘 디자이너는 선 그림 원본(도장) 하나만 정성껏 새긴다. 그 다음은 인쇄소(빌드 스크립트)의 일이다. 인쇄소는 같은 도장을 찍되, React라는 언어로 된 사용설명서, Vue라는 언어로 된 사용설명서… 이런 식으로 프레임워크별 "번역판"을 자동으로 찍어낸다.
즉 디자이너는 그림 하나만 그리면 되고, "이 그림을 리액트 컴포넌트로 바꿔라", "이 그림을 Vue 컴포넌트로 바꿔라" 같은 반복 작업은 전부 기계가 대신한다. 사람이 10번 다시 그릴 필요가 없다.
packages/ 폴더 안에 React용·Vue용 등 14개 패키지를 한 저장소에서 같이 관리한다.Lucide 자체는 신생 기술이 아니라 2020년에 시작된 포크(fork, 원본 프로젝트를 복제해 독자적으로 이어가는 것)다. 그런데도 여전히, 그리고 갈수록 더 많이 쓰이는 데는 이유가 있다.
Lucide의 LICENSE 파일에는 지금도 airplay, calendar, search 등 특정 아이콘 목록이 "Feather 프로젝트에서 유래했다"고 명시돼 있고, 그 아이콘들에는 Feather 원작자 Cole Bemis의 MIT 라이선스가 병기돼 있다. 즉 Lucide는 "Feather를 베낀 것"이 아니라 "멈춰버린 원조를 커뮤니티가 공식적으로 이어받아 계속 키운 것"이다. 이런 배경 덕에 초기부터 많은 기존 Feather 사용자가 자연스럽게 옮겨왔다.
최근 몇 년 사이 폭발적으로 쓰이는 React 컴포넌트 모음 shadcn/ui를 비롯해, 여러 스타터 템플릿·보일러플레이트가 Lucide를 기본 아이콘 세트로 지정했다. 한 인기 도구가 채택하면, 그 도구를 쓰는 수많은 프로젝트가 자동으로 Lucide도 함께 설치하게 된다 — "기본값의 힘"이다.
packages/ 폴더를 보면 React·Vue·Svelte·Angular·Solid·Preact·React Native·Astro까지 사실상 프론트엔드 생태계 전체를 커버한다. 어떤 프레임워크로 시작하든 "Lucide는 있다"는 확신을 주기 때문에, 팀이 기술 스택을 바꿔도 아이콘 세트는 그대로 유지할 수 있다.
Font Awesome처럼 상업적 색이 짙거나, Material Symbols처럼 구글이라는 한 회사에 종속된 세트와 달리, Lucide는 중립적인 커뮤니티 프로젝트다. 누구나 새 아이콘을 제안하고 병합될 수 있고, 실제로 지금도 매주 새 아이콘이 추가된다(직전 커밋도 feat(icons): add layout-freeform이었다).
아이콘 라이브러리가 없다면 개발자는 매번 아이콘을 PNG나 SVG로 하나하나 내려받아 프로젝트에 끼워 넣어야 한다. 색을 바꾸려면 SVG 코드를 열어 직접 수정해야 하고, 크기를 바꾸면 화질이 깨지거나 레이아웃이 어긋나기도 한다. 게다가 팀 안에서 어떤 사람은 동그란 스타일, 어떤 사람은 각진 스타일 아이콘을 섞어 쓰면 화면이 중구난방으로 보인다.
Lucide가 실제로 해결하는 문제는 세 가지로 요약된다.
currentColor라는 CSS 기법 덕분에, 이미지 파일을 바꾸지 않고도 코드에서 color="red", size={32}처럼 속성만 바꿔 즉시 다른 느낌의 아이콘을 낼 수 있다.레고 블록 회사가 "빨간 2x4 블록" 하나의 금형(원본)만 정교하게 만들어두면, 그 블록으로 자동차 세트에도 성 세트에도 똑같이 끼워 쓸 수 있는 것과 같다. Lucide는 아이콘이라는 블록의 "금형"을 표준화해, 어떤 프레임워크라는 "세트"에 꽂아도 모양이 어긋나지 않게 만든다.
저장소는 pnpm 워크스페이스 모노레포(packages/*, tools/*, docs)로 구성돼 있다. 전체 그림을 셋으로 나누면 이렇다.
각 패키지 폴더(packages/lucide-react/src/icons/ 등) 안의 .ts/.svelte/.vue 파일들은 사람이 직접 짜서 커밋한 코드가 아니다. package.json의 build:icons 스크립트가 매 빌드마다 icons/*.svg를 읽어 새로 찍어낸다. 즉 "코드가 있는 폴더"처럼 보이지만 실제로는 생성된 산출물이 커밋에 섞여 있을 뿐이다 — 이 구조를 모르면 "왜 아이콘 파일 코드가 다 똑같이 생겼지?"에서 헤맬 수 있다.
이 레포에서 가장 배울 만한 부분은 "디자인 원본 하나에서 코드를 자동 생성하는 파이프라인"이다. 실제 소스 파일을 순서대로 따라가 보자.
icons/activity.svg + activity.json
아이콘 하나는 SVG 파일과 JSON 메타데이터 파일이 이름이 같은 쌍으로 존재한다. 실제 icons/activity.svg를 열어보면 다음과 같다.
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36..." />
</svg>
짝을 이루는 activity.json에는 그림 정보가 아니라 이름·기여자·태그·카테고리만 들어 있다. 그림(형태)과 의미(메타데이터)를 파일 두 장으로 확실히 분리해 둔 것이다.
tools/build-icons가 SVG를 "데이터"로 바꾼다
각 패키지의 package.json에는 build:icons라는 스크립트가 있고, 실제로 lucide-react 패키지는 다음처럼 정의돼 있다(직접 확인한 원문).
"build:icons": "build-icons --output=./src
--templateSrc=./scripts/exportTemplate.mts
--renderUniqueKey --withAliases --withDynamicImports
--separateAliasesFile --iconFileExtension=.ts
--exportFileName=index.ts"
이 명령이 실행하는 tools/build-icons/cli.ts의 핵심 흐름은 이렇다. 함수 이름까지 그대로 인용한다.
readSvgDirectory(ICONS_DIR) — icons/ 폴더의 모든 SVG 파일 목록을 읽는다.renderIconsObject(svgFiles, ICONS_DIR, renderUniqueKey) — 각 SVG의 <path>·<circle> 같은 태그를 파싱해, "[태그이름, 속성객체]" 배열(IconNode)이라는 프레임워크 중립적인 데이터 구조로 바꾼다. 이 시점부터는 더 이상 텍스트 SVG가 아니라 자바스크립트 객체다.templateSrc로 지정된 패키지별 템플릿 함수(예: packages/lucide-react/scripts/exportTemplate.mts)를 불러온다. 이 템플릿이 "이 데이터를 어떤 프레임워크 문법으로 찍어낼지"를 결정하는 핵심이다.generateIconFiles(...) — 아이콘 1,756개 각각에 대해 템플릿 함수를 호출해 src/icons/activity.ts 같은 실제 소스 파일을 써낸다.withAliases·withDynamicImports 옵션이 켜져 있으면 별칭(구명·별명) 파일과 동적 import용 맵(dynamicIconImports)도 함께 생성한다.generateExportsFile(...) — 마지막으로 1,756개 아이콘을 전부 다시 내보내는 index.ts(배럴 파일)를 만든다.SVG 원본은 재료(밀가루 반죽)고, renderIconsObject는 그 반죽을 "표준 규격 데이터"로 다듬는 손질 과정이다. 그리고 templateSrc(패키지별 템플릿)는 붕어빵 틀이다. 같은 반죽이라도 어떤 틀에 넣느냐에 따라 붕어빵(React 컴포넌트)이 되기도, 크루아상(Vue 컴포넌트)이 되기도 한다. 반죽은 하나, 틀만 프레임워크마다 다르다.
exportTemplate.mts
실제로 packages/lucide-react/scripts/exportTemplate.mts는 다음과 같이 각 아이콘 파일을 위한 문자열 템플릿을 반환한다(원문 그대로).
export default defineExportTemplate(async({
componentName, iconName, children, getSvg, deprecated, deprecationReason,
}) => {
const svgContents = await getSvg();
const svgBase64 = base64SVG(svgContents);
return `
import createLucideIcon from '../createLucideIcon';
import { IconNode } from '../types';
export const __iconNode: IconNode = ${JSON.stringify(children)}
const ${componentName} = createLucideIcon('${iconName}', __iconNode);
export default ${componentName};
`;
});
즉 실제로 생성되는 src/icons/activity.ts 파일은 사람이 짠 게 아니라, 위 템플릿 함수가 children(파싱된 SVG 데이터)을 JSON.stringify로 그대로 박아 넣은 결과물이다. 그리고 그 파일이 부르는 createLucideIcon('activity', __iconNode)(packages/lucide-react/src/createLucideIcon.ts)가 진짜 React 컴포넌트를 만든다 — forwardRef로 감싸고, lucide-{kebab-case 이름} 클래스를 자동으로 붙인다.
렌더링 최종 단계인 Icon.ts에서는 size·color·strokeWidth 같은 props를 받아 진짜 <svg> 엘리먼트를 만든다. 흥미로운 디테일 하나 — absoluteStrokeWidth 옵션을 켜면 calculatedStrokeWidth = strokeWidth * 24 / size 공식으로 아이콘을 키워도 선 굵기 비율이 뭉개지지 않게 자동 보정한다.
| 패키지 | 템플릿 결과물 | 비고 |
|---|---|---|
| lucide-react | .ts — createLucideIcon() 호출 | forwardRef 기반 컴포넌트 |
| @lucide/vue | .ts — Vue용 render 함수 | renderUniqueKey 옵션(Vue의 key 요구사항 대응) |
| @lucide/svelte | .svelte 컴포넌트 파일 | 아이콘 파일 확장자 자체가 .svelte로 다름 |
| lucide-static | .ts + 순수 SVG 문자열 | 프레임워크 없이 마크업만 필요할 때 |
| @lucide/icons | 이름+노드 데이터만(컴포넌트 없음) | 다른 패키지가 이 데이터를 소비하는 기반 데이터 패키지 |
이 표에서 보듯, "SVG를 파싱해 IconNode 데이터로 만드는 공통 엔진"은 tools/build-icons 하나뿐이고, 각 패키지는 --templateSrc 인자로 자기 문법에 맞는 출력 함수만 갈아 끼운다. 새 프레임워크를 지원하고 싶다면 이론적으로 템플릿 함수 하나만 새로 짜면 된다 — 실제로 @lucide/icons는 "컴포넌트가 아니라 데이터"를 내보내, 커뮤니티가 자체적으로 지원되지 않는 프레임워크용 통합을 만들 수 있게 열어둔 것이라고 공식 문서가 밝힌다.
path, circle 등)를 [태그이름, 속성객체] 튜플 배열로 표현한, Lucide 내부의 프레임워크 중립 데이터 형식. 모든 패키지가 최종적으로 이 형식을 소비한다.
많은 사람이 "24×24 그리드, 선 굵기 2px, 둥근 끝처리" 같은 규칙이 자동 CI(지속적 통합) 검사로 딱딱 걸러질 거라고 짐작하지만, 실제 코드를 보면 다르다. docs/contribute/icon-design-guide.md에 14개 조항으로 규칙이 문서화돼 있고, 실제 자동화는 scripts/optimizeSvgs.mts(processSvg 함수)가 SVGO로 SVG를 최적화하고 기본 속성(width/height/stroke-width 등)을 강제로 덮어씌우는 것, 그리고 lint:icons(prettier로 SVG 포맷 검사)와 lint:json:icons(JSON 스키마 검증)뿐이다.
실제로는 선 굵기·라운드 캡 같은 속성값은 스크립트가 강제로 고정하지만, "옵티컬 볼륨이 원·정사각형과 비슷한가", "곡선이 매끄럽게 이어지는가" 같은 시각적 품질 규칙은 자동 검사 대상이 아니다. 이건 기여자가 Lucide Studio라는 웹 에디터로 직접 맞추고, PR 리뷰어(사람)가 눈으로 검토해서 지켜진다. "CI가 다 걸러줄 것"이라 믿고 대충 그려 올리면 리뷰에서 반려된다.
| 레이어 | 기술 / 도구 | 역할 |
|---|---|---|
| 모노레포 관리 | pnpm workspace(pnpm-workspace.yaml) | packages/*·tools/*·docs를 한 저장소에서 관리 |
| SVG 파싱/최적화 | svgson, svgo, prettier | SVG ↔ 객체 변환, 불필요한 속성 제거, 포맷 통일 |
| 코드 생성 | 자체 제작 @lucide/build-icons, @lucide/helpers | SVG → 프레임워크별 소스 파일 생성 엔진(이 저장소 고유 도구) |
| 번들링 | Rollup(대부분 패키지), Vite(문서 사이트) | 생성된 소스를 CJS/ESM 배포용으로 묶음 |
| 검증 | ajv-cli(JSON 스키마), cspell, ESLint, Vitest | 메타데이터 스키마 검증, 철자 검사, 코드 린트, 유닛 테스트 |
| 문서 사이트 | VitePress(docs/) | lucide.dev 정적 문서 생성 |
| 패키지별 런타임 | React 18/19, Vue 3, Svelte, SolidJS, Preact, Angular, Astro | 각 패키지의 peerDependencies로만 존재 — 이 저장소 자체는 특정 프레임워크에 종속되지 않음 |
주목할 점은 패키지별로 프레임워크 런타임이 peerDependencies(직접 설치하지 않고 사용자 프로젝트의 버전을 빌려 쓰는 의존성)로만 선언돼 있다는 것이다. 예를 들어 lucide-react는 react: "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"처럼 폭넓은 버전대를 허용해, React 16을 쓰는 오래된 프로젝트에서도 최신 아이콘을 그대로 쓸 수 있게 열어둔다.
일반 사용자(그냥 아이콘을 쓰고 싶은 개발자)는 이 레포를 클론할 필요조차 없다. 원하는 프레임워크 패키지 하나만 설치하면 된다.
# React 프로젝트
npm install lucide-react
# Vue 3 프로젝트 (최신 패키지명)
npm install @lucide/vue
# 프레임워크 없이 순수 SVG/폰트만
npm install lucide-static
| 항목 | 요구사항 |
|---|---|
| 일반 사용(패키지 설치) | 해당 프레임워크가 요구하는 Node 버전 이상이면 충분. 특별한 하드웨어 요구 없음 |
| 이 저장소 자체를 빌드할 때 | Node ≥24.11.1, pnpm 11.16.0(packageManager 필드로 고정) 필요 |
| 클론 후 준비 | pnpm install → pnpm build(전 패키지) 또는 pnpm lucide-react build(개별 패키지) |
| 아이콘 기여(디자인) | Figma / Illustrator / Inkscape / Affinity Designer 중 하나 + Lucide Studio(웹 기반 SVG 정렬 도구) |
아이콘을 "쓰기만" 할 사람은 이 문서의 5번 섹션 같은 내부 구조를 몰라도 된다. npm install lucide-react(또는 원하는 프레임워크 패키지) 한 줄로 끝난다. 내부 구조는 "내가 왜 특정 방식으로 import해야 하는지"를 이해하고 싶을 때만 필요하다(9번 섹션 참고).
가장 흔한 사용 사례인 React를 기준으로 실제 사용 흐름을 그대로 따라가 본다.
npm install lucide-react
import { Camera } from 'lucide-react';
function App() {
return <Camera />;
}
파일 이름 camera.svg가 파스칼케이스 컴포넌트 Camera로 바뀐 것이다. 이 매핑을 만드는 게 5번 섹션에서 본 generateExportsFile이다.
<Camera size={48} color="red" strokeWidth={1} />
새 이미지 파일을 준비할 필요 없이, 같은 SVG 데이터를 런타임에 다른 속성으로 다시 그리는 것뿐이다. 기본값은 size=24 · color=currentColor · strokeWidth=2 — 즉 아무 props 없이 쓰면 디자인 가이드가 정한 원본 그대로 렌더링된다.
DynamicIconimport { DynamicIcon } from 'lucide-react';
// name이 서버에서 온 문자열이라 미리 import를 정해둘 수 없을 때
<DynamicIcon name="camera" />
CMS(콘텐츠 관리 시스템)에서 아이콘 이름을 문자열로 저장해두고 나중에 렌더링해야 하는 경우처럼, 아이콘 이름을 코드 작성 시점에 알 수 없을 때 쓴다. 필요한 아이콘만 그때그때 불러오는(lazy-load) 구조라 번들에는 실제로 쓰는 것만 남는다.
import { Camera } from 'lucide-react'처럼 배럴 파일(barrel file, 여러 모듈을 한곳에서 다시 내보내는 진입점 파일)에서 가져오면, 번들러가 트리셰이킹(안 쓰는 코드 제거)을 잘 해줄 거라 기대하기 쉽다. 하지만 공식 문서(docs/guide/react-native/advanced/optimizations.md)가 명시적으로 경고한다.
Expo로 웹용 빌드를 만들 때 쓰는 Metro 번들러는 배럴 파일의 트리셰이킹을 안정적으로 못 한다. 그 결과 import { Camera } from 'lucide-react-native' 한 줄만 써도 1,756개 아이콘 전부가 최종 번들에 딸려 들어갈 수 있다. 공식 해결책은 import Camera from 'lucide-react-native/icons/camera'처럼 아이콘 파일을 개별 경로로 직접 import하는 것이다.
이 문제가 React Native 전용은 아니다. 오래된 번들러 설정이나 트리셰이킹이 약한 환경이라면 다른 프레임워크 패키지에서도 같은 증상이 날 수 있다 — "import 몇 줄 썼는데 번들이 갑자기 커졌다"는 리포트가 나오면 이 지점을 먼저 의심해야 한다.
lucide-vue-next · lucide-svelte · lucide-angular는 지금은 폐기(deprecated) 이름인터넷의 많은 블로그·유튜브 튜토리얼이 예전 패키지명인 lucide-vue-next, lucide-svelte, lucide-angular를 그대로 설치하라고 안내한다. 하지만 실제로 npm에서 확인하면 이 패키지들은 "Please use @lucide/vue instead" 같은 폐기 안내와 함께 각각 @lucide/vue, @lucide/svelte, @lucide/angular로 이름이 바뀌었다. 옛 이름도 당장 설치는 되지만 더 이상 업데이트되지 않는 버전에 고정될 위험이 있다.
package.json의 버전 번호를 믿지 말 것
이 저장소를 클론해서 packages/lucide-react/package.json을 열어보면 버전이 0.0.1로 적혀 있다(실제로 확인한 값). 하지만 npm에 배포된 실제 버전은 이 글 작성 시점 기준 1.27.0이다. 왜 이런 차이가 날까 — .github/workflows/release.yml을 보면, 버전은 소스 코드에 미리 적어두는 게 아니라 "릴리스 시 git 태그(v1.27.0 등)를 기준으로 pnpm version ... --no-git-tag-version 명령이 그 순간 덮어쓰는 값"이다. 즉 진짜 버전의 근원(source of truth)은 저장소 파일이 아니라 릴리스 워크플로가 참조하는 git 태그다.
packages/lucide-react/src/icons/*.ts 같은 파일들을 GitHub에서 보면 사람이 짠 코드처럼 보이지만, 5번 섹션에서 봤듯 이건 빌드 스크립트의 산출물이다. 이 폴더의 코드를 직접 고쳐도 다음 빌드에서 덮어써진다 — 아이콘 자체를 고치고 싶다면 src/icons/가 아니라 icons/*.svg 원본을 고쳐야 한다.
Feather에서 넘어온 아이콘들은 Lucide의 이름 규칙(예: "용도가 아니라 형태로 이름 짓기" — save 대신 floppy-disk)을 적용받아 일부는 이름이 바뀌었다. Feather 시절 코드를 그대로 복사해 붙이면 import가 실패할 수 있다.
| 세트 | 특징 | Lucide와 차이 |
|---|---|---|
| Feather Icons | Lucide의 원조. 아이콘 수가 적고(약 280개) 유지보수가 매우 느림 | Lucide는 사실상 "활발히 관리되는 Feather 확장판"에 가깝다. 신규 프로젝트라면 Lucide가 아이콘 수·최신성 모두 우위 |
| Heroicons | Tailwind CSS 팀이 만듦. outline/solid 2가지 스타일, 아이콘 수는 상대적으로 적음(약 300개대) | Tailwind 생태계와 궁합은 좋지만 아이콘 종류·프레임워크 지원 폭은 Lucide가 훨씬 넓음 |
| Phosphor Icons | thin/light/regular/bold/fill/duotone 등 6가지 굵기 변형 제공. 아이콘 수 매우 많음 | 스타일 다양성은 Phosphor가 앞서지만, 그만큼 배포 용량도 커짐. Lucide는 "하나의 통일된 스타일"에 집중 |
| Tabler Icons | Lucide와 비슷하게 24×24·2px 선 스타일. 아이콘 수도 매우 많음(수천 개대) | 디자인 철학이 가장 비슷한 경쟁자. 어느 쪽을 골라도 "선 굵기 통일 스타일"이라는 결과는 비슷하며, 취향·생태계 지원(shadcn/ui 등)이 선택 기준이 되는 경우가 많음 |
이들은 모두 "선으로 그린 단순한 그림 아이콘"이라는 같은 장르 안의 서로 다른 글꼴(폰트) 브랜드와 비슷하다. Helvetica냐 Inter냐처럼, 기능은 비슷해도 미묘한 선 두께·모서리 처리 느낌이 다르고, 한 프로젝트 안에서는 한 브랜드만 골라 통일해서 쓰는 것이 핵심이다. 아이콘 세트를 섞어 쓰면 폰트를 섞어 쓴 것처럼 화면이 어색해진다.
Lucide는 화려한 신기술이 아니라, "원본 하나 → 여러 결과물 자동 생성"이라는 아주 오래되고 검증된 소프트웨어 공학 패턴을 아이콘이라는 소재로 아주 깔끔하게 구현한 사례다. 핵심을 세 문장으로 압축하면:
icons/*.svg 1,756장뿐이고, 나머지 14개 패키지는 전부 빌드 시점 생성물이다.웹/앱 프론트엔드 개발자라면 별다른 고민 없이 설치해 쓰면 된다. 특히 shadcn/ui를 쓰는 React 프로젝트라면 이미 Lucide가 기본값으로 딸려 있을 가능성이 높다.
하나의 데이터 원본에서 여러 출력 포맷을 만들어내는 코드 생성(code generation) 파이프라인을 실전 규모로 읽어보고 싶은 개발자에게 이 레포는 훌륭한 교재다. tools/build-icons의 파싱 → 템플릿 함수 → 파일 생성 구조는 다른 도메인(다국어 번역 파일, API 클라이언트 자동 생성 등)에도 그대로 응용된다.
새 아이콘을 기여하려는 디자이너라면, CI가 다 걸러줄 거라 기대하지 말고 Lucide Studio로 직접 그리드에 맞추고 docs/contribute/icon-design-guide.md의 14개 조항을 스스로 점검한 뒤 PR을 올리는 편이 리뷰 왕복을 줄인다.