[CHORE] SVGR 세팅 - #55
Conversation
SVG를 React 컴포넌트로 변환하기 위해 @svgr/cli를 devDependency로 추가했습니다.
svgr.config.mjs에서 SVG 최적화(SVGO), JSX 자동 런타임, PlayIcon 형태의 컴포넌트 네이밍을 설정했습니다. generate-icons.mjs는 SVGR CLI로 SVG를 TSX로 변환하고 barrel 파일을 자동 생성합니다.
turbo.json에 icons:generate 태스크를 등록해 source SVG 변경 시에만 재생성하도록 캐싱을 구성했습니다. build가 icons:generate에 의존하도록 연결하고, generated 파일 경로를 루트 gitignore에 추가했습니다.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughSVGR 기반 아이콘 생성 파이프라인이 추가된다. SVG 소스는 생성 스크립트로 TSX 컴포넌트로 변환되고, 아이콘 배럴과 Turborepo 작업 의존성이 함께 갱신된다. 생성 산출물과 Storybook 로그는 Git 추적에서 제외된다. Changes아이콘 자동 생성 파이프라인
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested labels: Suggested reviewers: Related issues: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
CI 환경에서 generated 폴더가 없어 check-types가 실패하는 문제를 수정했습니다.
Timo Performance ReportBundle Size — timo-web
Lighthouse — timo-web
Image Optimization — timo-web
측정 커밋: |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/timo-design-system/generate-icons.mjs`:
- Around line 8-11: `toPascalCase()` in `generate-icons.mjs` only normalizes
hyphens and underscores, so icon filenames containing dots, spaces, or leading
digits can produce invalid export names and break the barrel file. Update the
name-generation path used for icon exports (and keep it aligned with the SVGR
template) so every filename is converted into a valid JavaScript identifier
before appending `Icon`, including sanitizing separators like `.`, whitespace,
and any non-identifier characters, and ensuring names do not start with a digit.
In `@packages/timo-design-system/svgr.config.mjs`:
- Around line 27-37: The SVGR template is generating icons as a const
declaration followed by a separate named export, which does not match the
project’s Arrow function + named export convention. Update the template in
svgr.config.mjs so the generated component uses a direct named export form (for
example, the template that builds ${name} from variables.componentName should
emit the component as an exported const), keeping the JSX and props structure
the same while removing the separate export block.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0ee714e3-b5f9-468c-bcf0-9163c8be6908
⛔ Files ignored due to path filters (2)
packages/timo-design-system/src/icons/source/play.svgis excluded by!**/*.svgpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (7)
.gitignorepackage.jsonpackages/timo-design-system/generate-icons.mjspackages/timo-design-system/package.jsonpackages/timo-design-system/src/icons/index.tspackages/timo-design-system/svgr.config.mjsturbo.json
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
turbo.json (2)
12-14: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
icons:generate캐시 입력이 불완전합니다.Line 13은 SVG 원본만 입력으로 잡고 있어서,
generate-icons.mjs나svgr.config.mjs가 바뀌어도 Turbo가 기존 산출물을 재사용할 수 있습니다. 그러면 생성 규칙이 바뀌었는데도src/icons/generated/**와src/icons/index.ts가 stale 상태로 남습니다. Turborepo의 task inputs 문서를 기준으로 생성 스크립트와 설정 파일도 입력에 포함해 주세요.수정 예시
"icons:generate": { - "inputs": ["src/icons/source/**"], + "inputs": [ + "src/icons/source/**", + "generate-icons.mjs", + "svgr.config.mjs" + ], "outputs": ["src/icons/generated/**", "src/icons/index.ts"] },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@turbo.json` around lines 12 - 14, The `icons:generate` task in `turbo.json` is only tracking the SVG source files, so changes to the generation logic can leave `src/icons/generated/**` and `src/icons/index.ts` stale. Update the task’s `inputs` to also include the icon generation script and configuration files used by `generate-icons.mjs` and `svgr.config.mjs`, so Turbo invalidates the cache whenever the generation rules change.
16-17: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
build도 로컬icons:generate를 선행해야 합니다.Line 17의
^icons:generate는 의존 패키지의 작업만 기다립니다. 그래서 아이콘을 직접 생성하는 패키지 자체를 빌드할 때는 로컬icons:generate가 실행되지 않아, 깨끗한 체크아웃에서 생성 파일 누락/구버전 산출물로 빌드가 흔들릴 수 있습니다.check-types처럼build에도 로컬 의존성을 추가해 두는 편이 안전합니다. Turborepo의dependsOn문서를 함께 확인해 보세요.수정 예시
"build": { - "dependsOn": ["^build", "^icons:generate"], + "dependsOn": ["icons:generate", "^build", "^icons:generate"], "inputs": ["$TURBO_DEFAULT$", ".env*"], "outputs": [".next/**", "!.next/cache/**", "!.next/dev/**"], "passThroughEnv": ["SENTRY_AUTH_TOKEN"] },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@turbo.json` around lines 16 - 17, The build pipeline is only waiting on dependency packages’ icons generation, so the package that owns `icons:generate` can still build without first generating its local icons. Update the `build` task in `turbo.json` so `dependsOn` includes the local `icons:generate` dependency as well as the existing upstream one, following the same pattern used by `check-types`, to ensure `build` always runs after `icons:generate` in the current package.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@turbo.json`:
- Around line 12-14: The `icons:generate` task in `turbo.json` is only tracking
the SVG source files, so changes to the generation logic can leave
`src/icons/generated/**` and `src/icons/index.ts` stale. Update the task’s
`inputs` to also include the icon generation script and configuration files used
by `generate-icons.mjs` and `svgr.config.mjs`, so Turbo invalidates the cache
whenever the generation rules change.
- Around line 16-17: The build pipeline is only waiting on dependency packages’
icons generation, so the package that owns `icons:generate` can still build
without first generating its local icons. Update the `build` task in
`turbo.json` so `dependsOn` includes the local `icons:generate` dependency as
well as the existing upstream one, following the same pattern used by
`check-types`, to ensure `build` always runs after `icons:generate` in the
current package.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: fcd61b80-04e5-41b2-a818-4129d3008837
📒 Files selected for processing (1)
turbo.json
named export 선언을 별도 구문으로 분리하던 방식에서 export const 인라인 방식으로 변경했습니다.
kimminna
left a comment
There was a problem hiding this comment.
web, storybook에서 정상 임포트 & 렌더링되는 것 확인했습니다!
다만 generated/는 gitignore되어 있고 src/icons/index.ts는 커밋되는 구조인데, index.ts가 ./generated/Play를 import하므로 fresh clone 후 generated/가 없는 상태에서 타입 체크가 바로 실패합니다. IDE에서도 즉시 에러가 표시되는 문제가 있어요.
생성 파일은 커밋하지 않아야 하니까 둘 다 gitignore에 넣는 방식이 어떨까 싶어요! 터보레포가 빌드, check-types 전에 icons:generate를 항상 선행 실행하니까 워크플로우에서는 문제 없을 것 같습니다!
…to chore/ui/54-setup-svgr # Conflicts: # packages/timo-design-system/package.json # pnpm-lock.yaml # turbo.json
|
현재 .gitignore에는 아래 두 항목만 추가했습니다. packages/timo-design-system/src/icons/generated/ : 생성되는 아이콘 파일 앞으로 icons:generate를 실행해 generated/ 아래에 파일이 추가되더라도 git에서 모두 무시되므로, SVG 원본(src/icons/source/)만 관리하면 됩니다. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
turbo.json (1)
12-15: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
icons:generate해시 입력에 설정과 생성 스크립트를 추가하세요.
src/icons/source/**만 해시되면svgr.config.mjs나generate-icons.mjs를 바꿔도 캐시가 그대로 재사용될 수 있어요. 아이콘 파이프라인은 깔끔한데, 캐시 재료가 조금 부족합니다 🙂🔧 제안
"icons:generate": { - "inputs": ["src/icons/source/**"], + "inputs": ["src/icons/source/**", "svgr.config.mjs", "generate-icons.mjs"], "outputs": ["src/icons/generated/**", "src/icons/index.ts"] },Turborepo의
inputs는 태스크 해시에 포함할 파일을 지정하므로, 관련 설정/스크립트도 함께 넣는 게 맞아요. https://turborepo.dev/docs/reference/configuration#inputs🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@turbo.json` around lines 12 - 15, `icons:generate` 태스크의 해시 입력이 `src/icons/source/**`만 포함해서 `svgr.config.mjs`와 `generate-icons.mjs` 변경이 캐시에 반영되지 않습니다. `turbo.json`의 `icons:generate` 설정에서 이 두 파일도 `inputs`에 포함되도록 추가해, 아이콘 생성 결과가 설정/스크립트 변경에 따라 다시 실행되게 수정하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@turbo.json`:
- Around line 12-15: `icons:generate` 태스크의 해시 입력이 `src/icons/source/**`만 포함해서
`svgr.config.mjs`와 `generate-icons.mjs` 변경이 캐시에 반영되지 않습니다. `turbo.json`의
`icons:generate` 설정에서 이 두 파일도 `inputs`에 포함되도록 추가해, 아이콘 생성 결과가 설정/스크립트 변경에 따라 다시
실행되게 수정하세요.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 083c7ea0-ee82-4815-9d98-a2bd00305acf
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (5)
.gitignorepackage.jsonpackages/timo-design-system/package.jsonpackages/timo-design-system/src/icons/index.tsturbo.json
💤 Files with no reviewable changes (1)
- packages/timo-design-system/src/icons/index.ts
jjangminii
left a comment
There was a problem hiding this comment.
SVG Sprite에서 SVGR로 전환하느라 고생했어요-!
inputs/outputs 명시로 SVG가 바뀌지 않으면 캐시를 재사용하는 부분도 꼼꼼하게 챙겨주셨네요 👍
감사합니다~~
yumin-kim2
left a comment
There was a problem hiding this comment.
처음 보는 개념들인데 PR 설명 덕분에 흐름을 잘 이해할 수 있었어요 🙏 SVG 넣고 명령어 하나로 끝나는 구조 너무 편리할 것 같아요.! 너무 수고하셨습니당 ~~~👍👍
There was a problem hiding this comment.
dependsOn으로 아이콘 생성 → 빌드 순서를 보장할 수 있다는게 신기하네요..!
SVG 바뀔 때만 다시 생성하고 캐시 쓰는 것도 더 효율적으로 쓸 수 있는 것 같아요. 많이 배워갑니다 🫰🏻
| .replace(/[-_](.)/g, (_, c) => c.toUpperCase()) | ||
| .replace(/^(.)/, (_, c) => c.toUpperCase()); |
There was a problem hiding this comment.
처음 보는 패턴이 있어서 찾아봤더니 정규식이라는 걸 처음 알게 됐어요! 복잡한 문자열 변환을 한 줄로 처리할 수 있는게 신기하네요 👀
ISSUE 🔗
close #54
What is this PR? 🔍
SVG Sprite 방식을 제거하고 SVGR 기반 아이콘 시스템을 구축했습니다.
왜 SVG Sprite에서 SVGR로 전환했나
SVG Sprite는
<use href>방식으로 아이콘을 참조하는데, Next.js App Router 환경에서는 Sprite 파일을 layout에 직접 인라인 주입해야 작동합니다. 또한 아이콘을 추가할 때마다 생성 스크립트를 별도로 실행하고iconNames.ts를 함께 관리해야 했습니다.SVGR은 SVG를 React 컴포넌트로 직접 변환하기 때문에 일반 컴포넌트와 동일하게 named import로 사용할 수 있고, 트리쉐이킹도 자연스럽게 됩니다. Next.js 생태계에서 사실상 표준으로 자리잡은 방식이기도 합니다.
모노레포 구조에서의 설계
이 프로젝트는
timo-design-system패키지가 아이콘을 관리하고timo-web이 소비하는 구조입니다. 여기서 두 가지를 결정했습니다.① 아이콘 생성은
timo-design-system패키지에서 담당svgr.config.mjs와generate-icons.mjs를timo-design-system에 두고,icons:generate스크립트로 실행합니다. 생성된 컴포넌트는@repo/timo-design-system/icons로 export됩니다.② Turborepo 파이프라인으로 빌드 순서 보장
timo-web의build스크립트에 직접 넣지 않고turbo.json에 별도 태스크로 등록했습니다.inputs(source SVG)와outputs(generated 파일)를 명시해 SVG가 바뀌지 않으면 캐시를 재사용합니다.build.dependsOn: ["^icons:generate"]로timo-web빌드 전 아이콘 생성이 자동으로 선행됩니다.프로젝트에 맞게 커스텀한 부분
SvgPlay→PlayIconicon: false1em고정 대신 CSS로 직접 제어style속성 제거removeAttrsstyle이 중복 생성되어 TypeScript 에러 발생jsxRuntime: 'automatic'viewBox유지removeViewBox: false아이콘 추가 방법 📖
1. SVG 파일 추가
packages/timo-design-system/src/icons/source/폴더에 SVG 파일을 추가합니다.파일명은 소문자 kebab-case로 작성합니다. 컴포넌트 이름은 자동으로 PascalCase +
Icon으로 변환됩니다.(
arrow-right.svg→ArrowRightIcon)2. 아이콘 생성 실행
src/icons/generated/에 TSX 컴포넌트가 생성되고,src/icons/index.tsbarrel이 자동 업데이트됩니다.3. 사용
width/heightprop 또는 CSS로 크기를 지정합니다.aria-hidden="true"가 기본 적용됩니다. 접근성이 필요한 경우aria-label을 직접 추가하세요.To Reviewers
toPascalCase는-,_구분자 처리만 구현되어 있습니다. 파일명에 숫자나 camelCase가 들어오는 케이스는 검증하지 않았으니 아이콘 추가 시 파일명 컨벤션을 지켜주세요.Screenshot 📷
Test Checklist ✔
pnpm icons:generate실행 —PlayIcon컴포넌트 및 barrel 정상 생성 확인pnpm check-types통과pnpm build— 미실행: CI에서 확인 예정