Conversation
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the Walkthrough디자인 시스템에 SVG 아이콘 파이프라인을 추가했습니다: SVGO 설정 및 정리 스크립트, 아이콘 목록 자동 생성 스크립트와 생성된 타입, Vite svg-sprite 플러그인 적용(패키지·앱들), 그리고 새 React Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as 개발자
participant Scripts as pnpm 스크립트
participant SVGO as SVGO
participant Gen as generate-icon-list.ts
participant Vite as Vite + svg-sprite 플러그인
participant Browser as 앱/브라우저
Dev->>Scripts: pnpm icons:clean
Scripts->>SVGO: src/icons/source/*.svg 최적화 (svgo.config.mjs)
Dev->>Scripts: pnpm generate:icons
Scripts->>Gen: SVG 파일명 스캔 -> iconNames.ts 생성
Dev->>Vite: pnpm dev/build
Vite->>Vite: sprite 생성(iconDirs) 및 body-last에 주입
Browser-->>Dev: 빌드된 앱(주입된 sprite 포함)
sequenceDiagram
autonumber
participant UI as UI 컴포넌트
participant Icon as Icon 컴포넌트
participant Sprite as Injected Sprite in DOM
UI->>Icon: <Icon name="ic_close" size=20 color="..." />
Icon->>Icon: width/height/class/style 계산
Icon->>Sprite: render <svg><use href="#icon-ic_close" /></svg>
Sprite-->>UI: 아이콘이 DOM에서 렌더링됨
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (14)
packages/design-system/tsconfig.json (1)
4-5: typeRoots 설정 불필요 – 삭제 고려design-system 패키지 내에서는 현재
vite/client,@testing-library,storybook등 외부 글로벌 타입 참조가 없으므로,
"typeRoots": ["node_modules/@types"]설정을 제거해도 동작에는 문제가 없습니다.
해당 옵션은 TypeScript의 기본값과 동일한 경로를 명시하고 있어 중복이므로,
향후 외부 글로벌 타입 사용 시 누락 리스크를 줄이기 위해 삭제를 권장합니다.• 수정 위치
– packages/design-system/tsconfig.json제안(diff):
"compilerOptions": { - "typeRoots": ["node_modules/@types"],packages/design-system/svgo.config.mjs (1)
3-8: SVG 스프라이트 내 ID 충돌 방지 방안 검토 필요리포지터리 내에서
<linearGradient>등 ID를 사용하는 SVG 파일이 확인되었습니다 (apps/landing/public/vite.svg, apps/client/public/vite.svg). 스프라이트로 병합 시 전역 ID 충돌 가능성이 있으므로, 아래와 같은 보완을 권장드립니다.• packages/design-system/svgo.config.mjs
–prefixIds플러그인 추가하여 파일명 기반으로 id에 고유 prefix 부여
• 또는 아이콘 소스 단계에서 id 충돌 방지 규칙(네이밍 컨벤션) 도입예시 (svgo.config.mjs):
plugins: [ + { + name: 'prefixIds', + params: { + prefix: ({ path }) => path + .split('/') + .pop() + .replace(/\.svg$/, '') + '-' + } + }, { name: 'preset-default', params: { overrides: { removeViewBox: false } } }, { name: 'removeDimensions' }, ],packages/design-system/src/icons/iconNames.ts (1)
7-7: 생성 스크립트와 괄호 표기 일관성 유지 권장현재 파일은
(typeof iconNames)[number]형태인데, 생성 스크립트는typeof iconNames[number]를 사용합니다. 둘 다 동작은 같지만, 불필요한 변경(churn)을 막기 위해 생성 스크립트 쪽을 본 파일 스타일로 맞추는 것을 권장합니다.packages/design-system/vite.config.ts (1)
12-13: 상대 경로 대신 절대 경로 사용으로 견고성 향상플러그인에 따라 iconDirs는 절대 경로가 더 안전합니다. __dirname 기반 절대 경로로 변경을 권장합니다.
적용 제안(diff):
- iconDirs: ['src/icons/source'], + iconDirs: [path.resolve(__dirname, 'src/icons/source')],packages/design-system/src/icons/scripts/generate-icon-list.ts (3)
11-14: 생성 결과의 결정성을 위해 정렬 추가 권장OS/파일시스템에 따라 readdirSync 결과 순서가 달라질 수 있어, 아이콘 추가/삭제와 무관한 불필요한 diff가 발생할 수 있습니다. 정렬을 추가해 빌드 결정성을 확보하세요.
적용 제안(diff):
-const files = readdirSync(ICON_DIR).filter((file) => file.endsWith('.svg')); +const files = readdirSync(ICON_DIR) + .filter((file) => file.endsWith('.svg')) + .sort((a, b) => a.localeCompare(b));
15-18: 타입 표기 스타일을 생성물(iconNames.ts)과 일치시키세요현재 스크립트는
typeof iconNames[number]를 생성하지만, 산출물은(typeof iconNames)[number]형태입니다. 일관성을 위해 후자 형태로 맞추는 것을 권장합니다.적용 제안(diff):
-const content = `// 이 파일은 자동 생성 파일입니다. (직접 수정 금지) -export const iconNames = ${JSON.stringify(iconNames)} as const; -export type IconName = typeof iconNames[number]; -`; +const content = `// 이 파일은 자동 생성 파일입니다. (직접 수정 금지) +export const iconNames = ${JSON.stringify(iconNames)} as const; +export type IconName = (typeof iconNames)[number]; +`;
8-10: 예외 처리(존재하지 않는 디렉터리 등) 최소 보강 제안ICON_DIR이 존재하지 않거나 비어 있는 경우를 대비해 간단한 가드만 두어도 DX가 좋아집니다. 실패 시 친절한 에러 메시지 또는 빈 리스트를 생성하도록 처리할 수 있습니다.
원하시면 try/catch + 안내 메시지 패턴으로 보강된 버전을 제안드리겠습니다.
packages/design-system/package.json (1)
38-38: 빌드 전용 도구는 devDependencies로 이동 권장 (런타임 오염/설치 비용 절감)
@pivanov/vite-plugin-svg-sprite와svgo는 빌드/생성 단계에서만 사용됩니다. 라이브러리 소비자 앱에까지 불필요하게 설치되지 않도록 devDependencies로 옮기는 것을 권장합니다.다음과 같이 이동 가능합니다:
"devDependencies": { + "@pivanov/vite-plugin-svg-sprite": "^3.1.3", + "svgo": "^4.0.0", ... }, "dependencies": { - "@pivanov/vite-plugin-svg-sprite": "^3.1.3", "@radix-ui/react-slot": "^1.2.3", ... - "svgo": "^4.0.0", "tailwind-merge": "^3.3.1", "tw-animate-css": "^1.3.7" }Also applies to: 45-45
packages/design-system/src/icons/index.ts (1)
1-1: 아이콘 타입 재노출 제안: 소비자 단 타입 접근성 개선Icon 컴포넌트만 공개하면 소비자 쪽에서
IconName타입을 직접 사용하기 어렵습니다../icons엔트리에서 타입을 함께 재노출하면 DX가 개선됩니다.-export { Icon } from './components/icon'; +export { Icon } from './components/icon'; +export type { IconName } from './iconNames';packages/design-system/src/icons/components/icon.tsx (5)
52-53: 기본 크기(24)와 PR 사용설명서(기본 20px) 불일치PR 안내에선 기본 width/height가 20px이라고 되어 있으나, 컴포넌트 기본값은 24입니다. 문서 또는 코드 중 하나를 정합화해 주세요.
문서 기준(20px)으로 맞출 경우:
- const w = width ?? size ?? 24; - const h = height ?? size ?? 24; + const w = width ?? size ?? 20; + const h = height ?? size ?? 20;
55-63: 회전 클래스 분기 간소화 제안중첩 삼항 대신 매핑 객체로 간결하게 표현하면 가독성과 유지보수가 좋아집니다.
- const rotateClass = - rotate === 90 - ? 'rotate-90' - : rotate === 180 - ? 'rotate-180' - : rotate === 270 - ? 'rotate-[270deg]' - : ''; + const rotateMap: Record<NonNullable<IconRotate>, string> = { + 90: 'rotate-90', + 180: 'rotate-180', + 270: 'rotate-[270deg]', + }; + const rotateClass = rotate ? rotateMap[rotate] : '';
66-77: 접근성 보강: aria-hidden 자동 판별 및 role 설정
- 현재 기본
ariaHidden = true라서, 소비자가aria-label을 전달해도 스크린리더에 노출되지 않는 혼선이 생길 수 있습니다.role="img"는 접근성 도구가 의미를 파악하는 데 도움이 됩니다(장식적일 때는 숨김 유지).다음과 같이 개선을 권장합니다.
export const Icon = ({ ... - ariaHidden = true, + ariaHidden = true, ...rest }: IconProps) => { ... - return ( + // aria-label, aria-labelledby, title 중 하나라도 있으면 강제로 노출 + const hasAccessibleName = + !!(rest['aria-label'] || rest['aria-labelledby'] || rest.title); + const computedAriaHidden = ariaHidden && !hasAccessibleName; + + return ( <svg width={typeof w === 'number' ? `${w}px` : w} height={typeof h === 'number' ? `${h}px` : h} className={combined} - style={color ? { color: `var(--color-${color})` } : undefined} - aria-hidden={ariaHidden} + style={color ? { color: `var(--color-${color})` } : undefined} + role={computedAriaHidden ? undefined : 'img'} + aria-hidden={computedAriaHidden} + focusable="false" {...rest} > <use href={`#icon-${name}`} /> </svg> );
66-77: 색상 속성의 실효성 점검: currentColor 미사용 아이콘에서 color prop이 무의미할 수 있음현재
<svg style={{ color: var(--color-XXX) }} />만 설정되어 있고, 내부 심볼이fill="currentColor"/stroke="currentColor"를 사용하지 않는다면 색상 변경이 적용되지 않습니다. PR 설명에 "currentColor 자동 변경은 적용하지 않음"이라고 되어 있으므로, 최소한의 일관성을 위해 다음 중 하나를 권장합니다.옵션 A(안전, 부분 효과):
<svg>기본 fill을 currentColor로 지정하여, 명시적 fill이 없는 path에는 색이 적용되도록 합니다.- <svg + <svg ... - style={color ? { color: `var(--color-${color})` } : undefined} + style={color ? { color: `var(--color-${color})` } : undefined} + fill="currentColor" ... >옵션 B(선택 기능화):
forceCurrentColor같은 prop을 추가해<svg>내부에style혹은<style>로* { fill: currentColor; stroke: currentColor }를 주입(기본값 false). 컬러 아이콘을 강제로 단색화할 수 있어 주의가 필요합니다.적용 시, 기존 컬러 아이콘에 대한 영향 범위를 반드시 확인해 주세요.
41-50: ariaHidden 커스텀 prop vs. aria-hidden 전달 가능성 중복
IconProps에ariaHidden(camelCase)을 두면서, 동시에...rest로aria-hidden(kebab-case)을 전달받으면 설정 충돌 여지가 있습니다. 하나의 경로만 권장합니다.
- 방안 1: 커스텀
ariaHidden제거하고, 소비자에게 표준aria-hidden사용을 안내.- 방안 2: 커스텀
decorative?: boolean으로 변경(우선순위: decorative > aria-hidden > auto).
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (4)
packages/design-system/src/icons/source/dotori.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/down_icon.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_arrow_down_white.svgis excluded by!**/*.svgpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (8)
packages/design-system/package.json(1 hunks)packages/design-system/src/icons/components/icon.tsx(1 hunks)packages/design-system/src/icons/iconNames.ts(1 hunks)packages/design-system/src/icons/index.ts(1 hunks)packages/design-system/src/icons/scripts/generate-icon-list.ts(1 hunks)packages/design-system/svgo.config.mjs(1 hunks)packages/design-system/tsconfig.json(1 hunks)packages/design-system/vite.config.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-04T10:12:01.690Z
Learnt from: constantly-dev
PR: Pinback-Team/pinback-client#10
File: apps/landing/src/index.css:1-1
Timestamp: 2025-07-04T10:12:01.690Z
Learning: In TailwindCSS v4, the import "tailwindcss"; syntax is the new recommended approach that replaces the three separate tailwind directives (tailwind base;, tailwind components;, tailwind utilities;). This is used with the tailwindcss/vite plugin.
Applied to files:
packages/design-system/vite.config.ts
🧬 Code Graph Analysis (2)
packages/design-system/src/icons/scripts/generate-icon-list.ts (1)
packages/design-system/src/icons/iconNames.ts (1)
iconNames(2-6)
packages/design-system/src/icons/components/icon.tsx (1)
packages/design-system/src/icons/iconNames.ts (1)
IconName(7-7)
🔇 Additional comments (3)
packages/design-system/svgo.config.mjs (1)
1-9: SVGO 기본값 구성이 목적에 잘 맞습니다 (viewBox 유지 + 크기 제거)multipass + preset-default(override removeViewBox:false) + removeDimensions 조합이 스프라이트 기반 아이콘에 적합합니다. 👍
packages/design-system/src/icons/iconNames.ts (1)
1-7: 자동 생성 결과가 안정적이며 타입 유틸리티 사용이 적절합니다튜플(as const) + 유니온 타입 파생 패턴이 적절합니다. 아이콘 파이프라인과도 잘 맞습니다.
packages/design-system/package.json (1)
29-29: 개발 도구 추가 반영 LGTM
@vitejs/plugin-react와tsx추가는 목적에 부합하며 문제 없어 보입니다.Also applies to: 32-32
| "icons:clean": "svgo -f src/icons/source --config=./svgo.config.mjs --multipass", | ||
| "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && prettier --write src/icons/iconNames.ts", |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
아이콘 스크립트 체인 및 Prettier 의존성 확인 필요
icons:clean과generate:icons를 함께 실행하는 편의 스크립트(예:icons)를 추가하면 DX가 좋아집니다.generate:icons에서prettier --write를 호출하는데, 이 패키지(또는 워크스페이스 루트)에 Prettier가 설치되어 있어야 합니다. 현재 이 패키지의 devDependencies에는 Prettier가 보이지 않습니다.
확인을 위해 다음 스크립트를 실행해 주세요. 목적: (1) 이 리포 내 Prettier 설치 여부, (2) svgo 설정 파일 존재 여부, (3) 아이콘 리스트 스크립트 존재 여부.
추가 제안(선택):
"scripts": {
...
- "icons:clean": "svgo -f src/icons/source --config=./svgo.config.mjs --multipass",
- "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && prettier --write src/icons/iconNames.ts",
+ "icons:clean": "svgo -f src/icons/source --config=./svgo.config.mjs --multipass",
+ "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && prettier --write src/icons/iconNames.ts",
+ "icons": "pnpm icons:clean && pnpm generate:icons",
...
}🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Prettier 설치 확인 =="
node -e "console.log(require.resolve('prettier'))" 2>/dev/null && echo "prettier: OK (resolve 가능)" || echo "prettier: NOT FOUND"
echo
echo "== SVGO 설정 파일 존재 확인 =="
if [ -f packages/design-system/svgo.config.mjs ]; then
echo "packages/design-system/svgo.config.mjs: OK"
else
echo "packages/design-system/svgo.config.mjs: NOT FOUND"
fi
echo
echo "== 아이콘 생성 스크립트 존재 확인 =="
if [ -f packages/design-system/src/icons/scripts/generate-icon-list.ts ]; then
echo "generate-icon-list.ts: OK"
else
echo "generate-icon-list.ts: NOT FOUND"
fiLength of output: 590
디자인 시스템 패키지에 Prettier 설치 및 아이콘 스크립트 통합 필요
검증 결과:
- Prettier: 미설치 →
generate:icons실행 시prettier명령을 찾지 못해 실패함 - SVGO 설정 파일:
packages/design-system/svgo.config.mjs존재 - 아이콘 생성 스크립트:
packages/design-system/src/icons/scripts/generate-icon-list.ts존재
해결 방안:
packages/design-system의devDependencies에 Prettier 추가 또는 워크스페이스 루트에 Prettier 설치- (선택) 아이콘 작업을 한 번에 실행할 수 있도록 스크립트 병합
예시 변경:
"scripts": {
…
"icons:clean": "svgo -f src/icons/source --config=./svgo.config.mjs --multipass",
"generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && prettier --write src/icons/iconNames.ts",
+ "icons": "pnpm icons:clean && pnpm generate:icons",
…
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "icons:clean": "svgo -f src/icons/source --config=./svgo.config.mjs --multipass", | |
| "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && prettier --write src/icons/iconNames.ts", | |
| "icons:clean": "svgo -f src/icons/source --config=./svgo.config.mjs --multipass", | |
| "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && prettier --write src/icons/iconNames.ts", | |
| "icons": "pnpm icons:clean && pnpm generate:icons", |
🤖 Prompt for AI Agents
packages/design-system/package.json lines 16-17: the generate:icons script
invokes the prettier CLI which is not installed in this package (causing
failures); add prettier to packages/design-system devDependencies (or ensure the
monorepo root has prettier and the package can access it) and update
package.json accordingly; optionally merge the two icon scripts into one (e.g.,
a single "icons:generate" script that runs the tsx generation then prettier) so
icon generation is atomic and the CLI is available when the script runs.
| @@ -0,0 +1,78 @@ | |||
| import type { IconName } from '../iconNames'; | |||
There was a problem hiding this comment.
React 네임스페이스 타입 직접 사용으로 인한 TS 빌드 오류 가능성
React.SVGProps를 사용하고 있지만 React 타입을 임포트하지 않았습니다. 환경에 따라 "Cannot find namespace 'React'" 오류가 발생할 수 있습니다. 네임스페이스 의존을 피하고 SVGProps를 명시 임포트하는 쪽이 안전합니다.
-import type { IconName } from '../iconNames';
+import type { IconName } from '../iconNames';
+import type { SVGProps } from 'react';
...
-interface IconProps extends React.SVGProps<SVGSVGElement> {
+interface IconProps extends SVGProps<SVGSVGElement> {Also applies to: 30-39
🤖 Prompt for AI Agents
In packages/design-system/src/icons/components/icon.tsx around line 1 (and
similarly affecting lines 30-39), the code uses the React namespace type
React.SVGProps without importing React which can trigger "Cannot find namespace
'React'" in some TS setups; instead add a type-only import "import type {
SVGProps } from 'react'" and replace all occurrences of React.SVGProps with
SVGProps so the file relies on explicit type imports rather than the React
namespace.
| <use href={`#icon-${name}`} /> | ||
| </svg> |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
스프라이트 주입 책임 위치 확인: 소비 앱에서 심볼 미주입 시 렌더 실패
<use href="#icon-${name}" />는 DOM 어딘가에 <symbol id="icon-${name}" />가 이미 주입되어 있어야 동작합니다. 현재 스프라이트 주입을 packages/design-system/vite.config.ts의 플러그인에 의존한다면, 디자인시스템을 소비하는 앱의 빌드 파이프라인에서는 심볼이 주입되지 않을 수 있습니다(라이브러리 번들 vs. 앱 번들 경계 이슈).
권장 옵션:
- 소비 앱의 Vite 설정에도 동일한 플러그인을 추가하고,
iconDirs경로를 라이브러리 번들 산출물/리소스로 일치시킵니다(문서화 필수). - 혹은 라이브러리에서 스프라이트 파일을 정적 자산으로 배포하고, 소비자가 HTML에 명시적으로 포함하거나, 라이브러리 제공
SpriteHost컴포넌트를 앱 루트에서 한 번 렌더해<symbol>들을 주입합니다.
다음 스크립트로 현재 리포에서 플러그인 적용 위치를 점검해 주세요.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== vite.config.ts 내 svg-sprite 플러그인 사용 위치 검색 =="
fd -t f vite.config.ts | while read -r f; do
echo "--- $f ---"
rg -nP "@pivanov/vite-plugin-svg-sprite|svgSpritePlugin" -n -C2 "$f" || true
doneLength of output: 1259
스프라이트 주입 위치 검토 필요
검토 결과, SVG 스프라이트 플러그인은 packages/design-system/vite.config.ts에서만 적용되어 있으며, 소비 앱(apps/client, apps/extension, apps/landing)의 Vite 설정에는 전혀 반영되어 있지 않습니다. 이대로 두면 <use href="#icon-{name}" />가 렌더링되지 않아 아이콘이 표시되지 않습니다.
영향 받는 파일:
- apps/client/vite.config.ts (svgSpritePlugin 미적용)
- apps/extension/vite.config.ts (미적용)
- apps/landing/vite.config.ts (미적용)
- packages/design-system/vite.config.ts (적용됨)
권장 조치:
- 소비 앱의 Vite 설정에도
@pivanov/vite-plugin-svg-sprite플러그인을 추가하고,iconDirs옵션을 디자인시스템의 아이콘 소스 경로와 일치시켜 문서화합니다. - 또는 디자인시스템에서 완성된 스프라이트 파일을 정적 자산으로 배포하여 소비자가 HTML에 직접 포함하거나, 라이브러리 내에
SpriteHost컴포넌트를 제공해 앱 루트에서 한 번만 렌더링하도록 구현합니다.
🤖 Prompt for AI Agents
packages/design-system/src/icons/components/icon.tsx around lines 75-76: the
component uses <use href={`#icon-${name}`} /> but the SVG sprite plugin is only
configured in packages/design-system/vite.config.ts so consumer apps won't have
the generated sprite and icons won't render; update each consumer app vite
config (apps/client/vite.config.ts, apps/extension/vite.config.ts,
apps/landing/vite.config.ts) to include @pivanov/vite-plugin-svg-sprite with
iconDirs pointed to the design-system icons source (match the path used in
packages/design-system), and document this requirement in the design-system
README; alternatively, if you prefer a library-side fix, build and publish the
compiled sprite as a static asset or add a SpriteHost React component in the
design-system that renders the generated sprite once at app root and document
how to include it.
| plugins: [ | ||
| react(), | ||
| tailwindcss(), | ||
| svgSpritePlugin({ | ||
| iconDirs: ['src/icons/source'], | ||
| symbolId: 'icon-[name]', | ||
| inject: 'body-last', | ||
| }), | ||
| ], |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
라이브러리 내부에서 스프라이트를 주입하면 소비 애플리케이션에서는 주입이 이뤄지지 않을 수 있습니다
현재 플러그인은 design-system 패키지의 Vite 설정에만 추가되어 있습니다. 이 설정은 라이브러리 빌드에는 영향을 주지만, 이 라이브러리를 사용하는 실제 앱(소비자)의 HTML에는 스프라이트가 자동 주입되지 않습니다. 결과적으로 소비 앱에서 <use href="#icon-...">가 참조할 심볼이 존재하지 않아 아이콘이 표시되지 않을 수 있습니다.
대안:
- 소비 애플리케이션의 Vite 설정에도 동일 플러그인을 추가하여 주입을 앱에서 수행.
- 또는 라이브러리에서 스프라이트를 런타임으로 주입하는 Provider/컴포넌트를 제공(최초 마운트 시 DOM에 삽입).
- 또는 빌드 타임에 sprite.svg 자산을 생성해, 소비 앱이 HTML에 직접 포함하도록 가이드.
지금 상태는 소비 앱 관점에서 “심볼 미주입” 위험이 높으므로 보완이 필요합니다.
원하시면 소비 앱용 Provider 컴포넌트/가이드를 함께 제안드리겠습니다.
소비 앱 쪽에 동일 플러그인이 설정되어 있는지 확인:
🏁 Script executed:
#!/bin/bash
# 레포 전체에서 해당 플러그인 사용 여부 확인
rg -n -C2 -P "@pivanov/vite-plugin-svg-sprite|svgSpritePlugin\\("Length of output: 2563
소비 애플리케이션 Vite 설정에 SVG 스프라이트 플러그인 미적용 – 심볼 주입 누락 위험
현재 packages/design-system/vite.config.ts 에는 svgSpritePlugin 이 적용되어 있으나, 레포 전체 검색 결과 소비 애플리케이션(apps/extension 등)의 Vite 설정 파일에서는 플러그인 사용이 확인되지 않습니다. 이로 인해 <use href="#icon-...">가 참조하는 SVG 심볼이 소비 앱 HTML에 삽입되지 않아 아이콘이 표시되지 않을 수 있습니다.
조치 방안:
- 소비 애플리케이션 Vite 설정(
apps/extension/vite.config.ts등)에svgSpritePlugin({ iconDirs: […], symbolId: 'icon-[name]', inject: 'body-last' })추가 - 또는 런타임에서 스프라이트를 DOM에 삽입하는 Provider/컴포넌트 제공 (초기 마운트 시)
- 또는 빌드 시점에
sprite.svg자산을 생성해, 소비 앱이 HTML에 직접 포함하도록 문서화
필요 시 소비 앱용 Provider 컴포넌트 및 가이드 작성도 지원 가능합니다.
🤖 Prompt for AI Agents
In packages/design-system/vite.config.ts around lines 8-16 the svgSpritePlugin
is configured but consumer apps (e.g., apps/extension) do not apply this plugin
so SVG symbols may not be injected into their HTML; update each consumer Vite
config (e.g., apps/extension/vite.config.ts) to include svgSpritePlugin with the
same options (iconDirs pointing to the design-system icons, symbolId:
'icon-[name]', inject: 'body-last'), or alternatively implement a runtime
Provider/component that injects the sprite into the DOM on initial mount, or add
a build step that emits a shared sprite.svg and document adding it into consumer
HTML—pick one approach and apply consistently across consumer app configs or add
the runtime Provider and corresponding docs/tests.
There was a problem hiding this comment.
이 부분 체크해보셔야 할 것 같아요!
apps 3개에서 vite.config.ts에 따로 svgSpritePlugin 설정 안 해도 저 아이콘 가져다 쓰는 거 문제 없나요??
There was a problem hiding this comment.
🧩 Analysis chain
@constantly-dev 좋은 지적이에요! 이 부분 확실히 체크해봐야겠습니다. SVG 스프라이트 설정이 디자인 시스템에만 있으면 실제 앱에서 아이콘이 안 보일 수 있거든요.
🏁 Script executed:
#!/bin/bash
# 1. apps 디렉터리 구조 확인
echo "=== Apps 디렉터리 구조 ==="
find apps -name "vite.config.*" -type f 2>/dev/null | head -10
echo -e "\n=== 각 앱의 Vite 설정에서 svgSpritePlugin 사용 여부 확인 ==="
rg -n -C3 -P "svgSpritePlugin|@pivanov/vite-plugin-svg-sprite" apps/ || echo "앱들에서 svgSpritePlugin 설정을 찾을 수 없습니다."
echo -e "\n=== 앱들 목록 ==="
ls -la apps/
Length of output: 1136
🏁 Script executed:
#!/bin/bash
# extension 앱에서 svgSpritePlugin이 설치되어 있으니 vite.config.ts에서 실제 사용하는지 확인
echo "=== apps/extension/vite.config.ts 내용 ==="
cat apps/extension/vite.config.ts
echo -e "\n=== apps/client/vite.config.ts 내용 ==="
cat apps/client/vite.config.ts
echo -e "\n=== apps/landing/vite.config.ts 내용 ==="
cat apps/landing/vite.config.ts
echo -e "\n=== 각 앱에서 design-system 의존성 확인 ==="
echo "-- apps/extension/package.json --"
rg -n "design-system" apps/extension/package.json || echo "design-system 의존성 없음"
echo "-- apps/client/package.json --"
rg -n "design-system" apps/client/package.json || echo "design-system 의존성 없음"
echo "-- apps/landing/package.json --"
rg -n "design-system" apps/landing/package.json || echo "design-system 의존성 없음"
Length of output: 2550
예상했던 대로 문제가 있네요! 🚨
현재 상황 분석
- 3개 앱 모두 design-system 의존성은 있음:
apps/extension,apps/client,apps/landing - 하지만 어느 앱도
svgSpritePlugin설정이 없음 - extension 앱은
@pivanov/vite-plugin-svg-sprite패키지를 설치해뒀지만 실제 vite.config.ts에서 사용하지 않음 - client, landing 앱은 vite.config.ts에
// TODO: svg 설정 추가주석이 있음
문제점
현재 설정으로는 아이콘이 표시되지 않습니다:
Icon컴포넌트가<use href="#icon-{name}" />로 스프라이트를 참조하지만- 실제 앱의 DOM에는 해당 심볼들이 주입되지 않음
- 결과: 빈 아이콘 또는 깨진 아이콘
해결 방안
각 앱의 vite.config.ts에 svgSpritePlugin 설정을 추가해야 합니다:
1. apps/extension/vite.config.ts 수정
import svgSpritePlugin from '@pivanov/vite-plugin-svg-sprite';
// ... 기존 imports
export default defineConfig({
plugins: [
react(),
tsconfigPaths({
projects: [resolve(__dirname, '../../tsconfig.json')],
}),
tailwindcss(),
svgSpritePlugin({
iconDirs: ['../../packages/design-system/src/icons/source'],
symbolId: 'icon-[name]',
inject: 'body-last',
}),
crx({ manifest }),
],
// ... 나머지 설정
});2. apps/client/vite.config.ts, apps/landing/vite.config.ts에도 동일 설정 추가
import svgSpritePlugin from '@pivanov/vite-plugin-svg-sprite';
// ... 기존 imports
export default defineConfig({
plugins: [
react(),
tsconfigPaths(),
tailwindcss(),
svgSpritePlugin({
iconDirs: ['../../packages/design-system/src/icons/source'],
symbolId: 'icon-[name]',
inject: 'body-last',
}),
],
});그리고 client, landing 앱의 package.json에도 의존성 추가 필요:
"@pivanov/vite-plugin-svg-sprite": "^3.1.3"지금 당장 수정하지 않으면 Icon 컴포넌트가 제대로 동작하지 않을 거예요! 👀
🧠 Learnings used
Learnt from: constantly-dev
PR: Pinback-Team/pinback-client#10
File: apps/landing/src/index.css:1-1
Timestamp: 2025-07-04T10:12:01.690Z
Learning: In TailwindCSS v4, the import "tailwindcss"; syntax is the new recommended approach that replaces the three separate tailwind directives (tailwind base;, tailwind components;, tailwind utilities;). This is used with the tailwindcss/vite plugin.
Learnt from: constantly-dev
PR: Pinback-Team/pinback-client#10
File: apps/landing/src/index.css:1-1
Timestamp: 2025-07-04T10:12:01.690Z
Learning: In TailwindCSS v4, the import "tailwindcss"; syntax is the new recommended approach that replaces the three separate tailwind directives (tailwind base;, tailwind components;, tailwind utilities;). This single import pulls in all of Tailwind's preflight, components, and utilities in one step and is used with the tailwindcss/vite plugin.
Learnt from: constantly-dev
PR: Pinback-Team/pinback-client#2
File: pnpm-workspace.yaml:3-3
Timestamp: 2025-08-18T13:48:59.021Z
Learning: constantly-dev는 docs 디렉터리를 컨벤션 문서 추가용으로 사용할 예정이라고 명시했습니다.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
packages/design-system/package.json (1)
17-17: generate:icons가 Prettier 미설치 시 실패합니다
prettier --write를 호출하지만 이 패키지의 devDependencies에 Prettier가 없습니다. 워크스페이스 루트에 설치되어 있더라도 pnpm 특성상 서브패키지 스크립트에서 바로prettier바이너리를 못 찾는 경우가 많아 실패합니다. 이 패키지에 Prettier를 추가하거나, 워크스페이스 루트의 Prettier를 강제로 사용하도록 스크립트를 바꾸세요.다음 중 하나를 적용하세요.
- 옵션 A(권장): devDependencies에 Prettier 추가
"devDependencies": { "@pinback/eslint-config": "workspace:*", "@pinback/tailwind-config": "workspace:*", "@pinback/typescript-config": "workspace:*", "@tailwindcss/vite": "^4.1.12", "@turbo/gen": "^2.5.0", "@types/node": "^22.15.3", "@types/react": "19.1.0", "@types/react-dom": "19.1.1", "@vitejs/plugin-react": "^4.5.2", "eslint": "^9.33.0", "tailwindcss": "^4.1.12", "tsx": "^4.20.4", "typescript": "5.9.2", "typescript-eslint": "^8.39.1", - "vite": "^7.1.2" + "vite": "^7.1.2", + "prettier": "^3.3.3" },
- 옵션 B: 루트 Prettier를 사용하도록 스크립트 변경
- "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && prettier --write src/icons/iconNames.ts", + "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && pnpm -w exec prettier --write packages/design-system/src/icons/iconNames.ts",필요하면 루트에 Prettier가 있는지 확인하는 검증 스크립트도 제공할 수 있습니다.
🧹 Nitpick comments (3)
packages/design-system/package.json (2)
39-39: 빌드 전용 플러그인은 devDependencies로 이동하세요
@pivanov/vite-plugin-svg-sprite는 Vite 빌드 타임에만 사용됩니다. runtime dependencies에 두면 소비자 앱 설치 용량 및 종속성 표면이 불필요하게 늘어납니다.의존성 섹션에서 제거:
- "@pivanov/vite-plugin-svg-sprite": "^3.1.3",devDependencies로 이동:
"devDependencies": { + "@pivanov/vite-plugin-svg-sprite": "^3.1.3", "@pinback/eslint-config": "workspace:*", ... }
46-46: SVGO도 devDependencies가 적절합니다
svgo는 아이콘 소스를 전처리하는 도구이므로 런타임 의존성일 필요가 없습니다. devDependencies로 옮겨 설치/배포 표면을 줄이세요.dependencies에서 제거:
- "svgo": "^4.0.0",devDependencies에 추가:
"devDependencies": { + "svgo": "^4.0.0", "@pinback/eslint-config": "workspace:*", ... }packages/design-system/src/icons/iconNames.ts (1)
2-14: 아이콘 네이밍 컨벤션 점검: ‘disable’ vs ‘disabled’여러 항목이 ‘disable’ 형태를 사용합니다. 팀 컨벤션이 ‘disabled’라면 스크립트 단계에서 일괄 정규화(예: kebab/camel→snake, 상태 접미사 통일)를 고려하세요. 반대로 디자이너 산출물 파일명이 규칙이라면 현재 상태도 OK입니다. 결정만 명문화되면 됩니다.
원하면
generate-icon-list.ts에 다음과 같은 후처리를 추가하는 패치를 제안해 드리겠습니다:
- 파일명에서 상태 토큰을 파싱해 ‘disabled’로 치환
- 알파벳/숫자/언더스코어만 허용하도록 sanitize
- 정렬(sorting) 고정으로 PR 디프 변동 최소화
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (11)
packages/design-system/src/icons/source/ic_arrow_down_active.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_arrow_down_disable.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_bookmark_active.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_bookmark_disable.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_clock_active.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_clock_disable.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_close.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_details_category.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_details_disable.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_info.svgis excluded by!**/*.svgpackages/design-system/src/icons/source/ic_plus.svgis excluded by!**/*.svg
📒 Files selected for processing (3)
packages/design-system/package.json(1 hunks)packages/design-system/src/icons/components/icon.tsx(1 hunks)packages/design-system/src/icons/iconNames.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/design-system/src/icons/components/icon.tsx
🔇 Additional comments (6)
packages/design-system/package.json (4)
16-16: SVGO 최적화 스크립트 구성 좋습니다
--config와--multipass플래그 사용이 목적에 부합합니다. 소스 경로도 패키지 기준 상대경로로 올바릅니다.
19-19: DX 향상: 단일 진입점 스크립트 추가 좋습니다
pnpm icons로 정리+생성을 한 번에 수행할 수 있어 작업 흐름이 명확해집니다.
30-30: 변경 영향 없음devDependency 순서 변경은 기능적 영향이 없습니다.
33-33: tsx 도입 적절합니다경량 TS 실행기에
tsx를 사용해 아이콘 목록 생성 스크립트를 구동하는 접근이 적절합니다.packages/design-system/src/icons/iconNames.ts (2)
1-1: 자동 생성 경고 주석 좋습니다수동 편집 방지를 명확히 해 협업 실수를 줄입니다. 생성 스크립트에서 동일 주석 유지도 확인 바랍니다.
14-15: as const + 유니온 타입 패턴 적절합니다런타임 배열과 타입 유니온을 동기화하는 안전한 패턴입니다. 컴포넌트 prop에
IconName을 적용하면 오타를 컴파일 타임에 차단할 수 있습니다.
jllee000
left a comment
There was a problem hiding this comment.
https://www.reddit.com/r/css/comments/x940jt/change_svg_color_with_help_from_css_filter/?tl=ko
currentcolor 넣는 고민에 대해서 저도 찾아보니, 캐릭터 이미지처럼 여러색이 들어간 경우는 색상변경 제어를 넣진 않는것같고
단색인 svg 경우에 뭐 호버에 따라 색상이 달라진다든지의 경우엔 css필터?? 뭐 이런거 넣는 얘기도 있던데, 저도 더 좋은 방안 찾아보겠습니당
|
|
||
| const iconNames = files.map((file) => basename(file, '.svg')); | ||
|
|
||
| const content = `// 이 파일은 자동 생성 파일입니다. (직접 수정 금지) |
There was a problem hiding this comment.
이거 generate빌드하면 그때 그 자동 생성되는 구간이였나용??
There was a problem hiding this comment.
generate빌드하면 이 파일의 함수들로 iconsName파일에 자동생성됩니당
|
|
||
| type IconRotate = 90 | 180 | 270; | ||
|
|
||
| type IconColor = |
constantly-dev
left a comment
There was a problem hiding this comment.
고생하셨습니다~~
prettier 설정이나 svgo를 통해 width/height 자동으로 지워주는 설정 때문에 훨씬 개발 생산성이 높아질 것 같아요!! 최고입니다 👍
몇 개 코멘트 남겼으니 확인 부탁드려요 ~
| "check-types": "tsc --noEmit", | ||
| "generate:component": "turbo gen react-component" | ||
| "icons:clean": "svgo -f src/icons/source --config=./svgo.config.mjs --multipass", | ||
| "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && prettier --write src/icons/iconNames.ts", |
There was a problem hiding this comment.
저번에 문제 생긴 prettier 부분을 이렇게 해결해주셨네요 👍
| type IconColor = | ||
| | 'main0' | ||
| | 'main100' | ||
| | 'main200' | ||
| | 'main300' | ||
| | 'main400' | ||
| | 'main500' | ||
| | 'main600' | ||
| | 'secondary' | ||
| | 'error400' | ||
| | 'success400' | ||
| | 'white' | ||
| | 'black' | ||
| | 'gray0' | ||
| | 'gray100' | ||
| | 'gray200' | ||
| | 'gray300' | ||
| | 'gray400' | ||
| | 'gray500' | ||
| | 'gray600' | ||
| | 'gray700' | ||
| | 'gray800' | ||
| | 'gray900'; |
There was a problem hiding this comment.
확실히 tailwind v4에서 css 형식으로 token 설정을 해주니까 이런 부분도 다 정적으로 박아야 하네요.
해당 icon컴포넌트랑 twMerge 함수 부분도 token 정보를 필요로 해서 이 부분을 중앙화 할 방법을 꼭 생각해내야 할 것 같아요.
같이 고민해봐요 👍
| const w = width ?? size ?? 20; | ||
| const h = height ?? size ?? 20; |
| plugins: [ | ||
| react(), | ||
| tailwindcss(), | ||
| svgSpritePlugin({ | ||
| iconDirs: ['src/icons/source'], | ||
| symbolId: 'icon-[name]', | ||
| inject: 'body-last', | ||
| }), | ||
| ], |
There was a problem hiding this comment.
이 부분 체크해보셔야 할 것 같아요!
apps 3개에서 vite.config.ts에 따로 svgSpritePlugin 설정 안 해도 저 아이콘 가져다 쓰는 거 문제 없나요??
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (8)
package.json (1)
13-13: pnpm.overrides로 플러그인 버전 고정 및 devDependency 중복 제거 권장현재 레포 내 모든
package.json(루트, apps/extension, apps/landing, apps/client, packages/design-system)에서
"@pivanov/vite-plugin-svg-sprite": "^3.1.3"가 동일하게 선언되어 있어(스크립트 검증 완료) 버전 드리프트는 없습니다.
하지만 향후 패키지 추가·업데이트 시 버전 관리 편의성을 위해pnpm.overrides에 고정해두는 것을 권장드립니다.또한, 루트와 각 패키지 모두에 중복 선언되어 있어 유지보수성이 떨어집니다. 팀 규칙에 따라 아래 중 한 가지 방식을 선택하여 통일해주세요.
- 각 앱이 자체적으로 선언
- 루트 한 곳에서만 선언
수정 위치 및 제안 diff:
- 파일:
package.json(루트)"pnpm": { "overrides": { - "vite": "7.1.2" + "vite": "7.1.2", + "@pivanov/vite-plugin-svg-sprite": "^3.1.3" } },
- 각 하위
package.json에서@pivanov/vite-plugin-svg-spritedevDependency 제거 또는 루트에서만 선언하는 쪽으로 정리apps/landing/package.json (1)
17-17: 버전 일관성 확보를 위해 루트 overrides 활용 권장apps/landing/package.json의
pnpm.overrides를 확인해보니, 현재는 vite만 고정되어 있어@pivanov/vite-plugin-svg-sprite에 대한 버전 고정이 적용되지 않습니다.
하나의 워크스페이스 내에서 플러그인 버전을 일관되게 관리하려면, 루트package.json의pnpm.overrides에 다음과 같이 해당 플러그인 버전을 명시해두시는 것을 권장드립니다.
확인 커맨드:
jq -r '.pnpm.overrides' < apps/landing/package.json출력 결과:
{ "vite": "7.1.2" }권장 추가 예시 (루트
package.json):{ "pnpm": { "overrides": { "@pivanov/vite-plugin-svg-sprite": "3.1.3" } } }위와 같이 설정하시면, 하위 패키지에서도 동일한 플러그인 버전이 강제 적용되어 중복 선언이나 버전 불일치 문제를 예방할 수 있습니다.
apps/client/vite.config.ts (2)
10-19: 아이콘 FOUC 방지: sprite 주입 위치를 body-first로 고려현재 inject: 'body-last'는 초기 페인트 시점에 가 심볼보다 먼저 렌더링되면 순간적으로 아이콘이 비어 보일 수 있습니다. 'body-first'로 바꾸면 이 플리커를 줄일 수 있습니다. 기능적으로는 동일합니다.
아래처럼 변경을 제안합니다:
- svgSpritePlugin({ + svgSpritePlugin({ iconDirs: ['src/icons/source'], symbolId: 'icon-[name]', - inject: 'body-last', + inject: 'body-first', }),
9-9: TODO 주석 정리구현이 완료되어 있으므로 해당 TODO는 제거해도 됩니다.
적용 diff:
- // TODO: svg 설정 추가apps/extension/package.json (1)
19-19: devDependency로 이동한 점 적절합니다플러그인은 빌드 시점에만 필요하므로 devDependencies로의 이동이 맞습니다. 루트 overrides로 버전 고정을 추가하면 확실합니다.
apps/landing/vite.config.ts (3)
10-19: 설정은 동작하나, 경로 안정성·ID 충돌 방지·SVGO 일관성 강화를 권장현 설정으로도 작동합니다만 아래 3가지를 권장드립니다.
- 절대 경로 사용: OS·워크스페이스 루트 변화에 덜 민감합니다. 문서 예시도
path.resolve(process.cwd(), ...)사용을 권장합니다. (github.com)- symbolId 충돌 방지: 하위 폴더를 사용할 가능성이 있다면
icon-[dir]-[name]로 바꿔 동일 파일명 충돌을 예방하세요. 해당 패턴은 문서의 기본값과도 부합합니다. (github.com)- SVGO로 width/height 제거: PR 목표(자동 제거)와 일치하도록
removeDimensions플러그인을 추가하세요. 플러그인 기본 SVGO 설정은viewBox를 보존하므로 안전합니다. (github.com)아래 diff를 적용해 보세요.
plugins: [ react(), tsconfigPaths(), tailwindcss(), - svgSpritePlugin({ - iconDirs: ['src/icons/source'], - symbolId: 'icon-[name]', - inject: 'body-last', - }), + svgSpritePlugin({ + iconDirs: [path.resolve(process.cwd(), 'src/icons/source')], + symbolId: 'icon-[dir]-[name]', + svgDomId: 'svg-sprite', + inject: 'body-last', + svgoConfig: { + plugins: [{ name: 'removeDimensions' }], + }, + }), ],또한, 위 diff를 사용하려면 상단에
pathimport가 필요합니다(아래 코드 추가).import path from 'node:path';
10-19: Optional: 파일 출력이 필요하면fileName사용 고려런타임 HTML 주입(
inject)만으로 충분하다면 현 상태 유지가 최적입니다. 다만 정적 파일 캐시(예: CDN)나 SSR 템플릿에서의 명시적 참조가 필요하면fileName: 'sprite.svg'를 추가해 dist에 산출하도록 할 수 있습니다. 두 방식은 문서 상 공존 가능하지만, 대부분 하나만 사용합니다. (github.com)
9-9: TODO 주석 정리 제안이제 설정이 추가되었으니
// TODO: svg 설정 추가주석은 제거해도 좋습니다.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (8)
apps/client/package.json(1 hunks)apps/client/vite.config.ts(1 hunks)apps/extension/package.json(1 hunks)apps/extension/vite.config.ts(2 hunks)apps/landing/package.json(1 hunks)apps/landing/vite.config.ts(1 hunks)package.json(1 hunks)packages/design-system/src/icons/components/icon.tsx(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- apps/client/package.json
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/design-system/src/icons/components/icon.tsx
🔇 Additional comments (3)
apps/extension/vite.config.ts (1)
19-23: HTML 주입 순서 및 다중 엔트리 검증 권장Vite의
transformIndexHtml훅은 async·sequential 훅으로,plugins배열 등록 순서와enforce/order옵션에 따라 실행 순서가 결정됩니다. (main.vitejs.dev, v2.vitejs.dev)검증 체크리스트:
- dist 폴더의 모든 HTML 파일(popup.html, options.html 등)을 열어
<svg>sprite 태그가 주입되었는지 확인- 각 페이지에서
<use href="#icon-...">사용 시 아이콘이 정상 렌더링되는지 확인- content script 또는 shadow DOM 환경에서 inject 위치(
body-first/body-last)가 렌더 타이밍에 영향이 없는지 육안 검증성능 및 초기 페인트 품질 최적화를 위해
inject: 'body-first'로 변경을 권장합니다:- svgSpritePlugin({ + svgSpritePlugin({ iconDirs: ['src/icons/source'], symbolId: 'icon-[name]', - inject: 'body-last', + inject: 'body-first', }),필요 시
enforce: 'post'또는transformIndexHtml({ order: 'post', handler })형태로 훅 실행 순서를 명시적으로 조정하세요. 검증 후 문제 없음을 확인해 주시기 바랍니다.apps/landing/vite.config.ts (2)
15-16: 아이콘 경로 설정 재확인 및 통일 필요현재 아래 스크립트 확인 결과, 지정된 두 경로 모두 실제 SVG 파일을 포함하고 있지 않습니다.
- apps/landing/src/icons/source — SVG 파일 없음
- packages/design-system/src/icons/source — SVG 파일 없음
이로 인해 다음 사항을 점검 및 조치해 주세요:
단일 아이콘 소스 결정
• 앱 로컬(apps/landing/src/icons/source)을 사용할지
• 디자인 시스템 패키지(packages/design-system/src/icons/source)의 공용 아이콘만 사용할지결정된 소스에 맞춰
vite.config.ts의iconDirs값을 업데이트
• DS 공용 아이콘을 사용할 경우, 워크스페이스 구조에 맞춘 절대 경로 (예:path.resolve(process.cwd(), '../../packages/design-system/src/icons/source')) 설정
• Vite 개발 서버의server.fs.allow옵션에 해당 경로가 포함되어 있는지 확인위 사항을 반영한 후, 실제 아이콘 파일이 해당 디렉토리에 존재하는지 재확인 부탁드립니다.
5-5: 플러그인 설치 및 버전 일관성 확인 완료
- apps/landing/package.json (devDependencies):
@pivanov/vite-plugin-svg-sprite→ ^3.1.3- 루트 package.json (devDependencies):
@pivanov/vite-plugin-svg-sprite→ ^3.1.3설치 상태와 버전이 양쪽 모두 일치하므로, 해당 코드 변경을 승인합니다.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
apps/landing/vite.config.ts (2)
14-18: iconDirs의 상대 경로는 CWD에 민감합니다 → 절대 경로로 안전화 권장루트에서 빌드/서브패키지에서 빌드 등 실행 위치가 달라질 때 경로 해석 이슈가 생길 수 있습니다. ESM-safe 절대 경로로 바꿔주세요.
다음 diff는 옵션 내부만 변경합니다:
- svgSpritePlugin({ - iconDirs: ['../../packages/design-system/src/icons/source'], + svgSpritePlugin({ + iconDirs: [resolve(__dirname, '../../packages/design-system/src/icons/source')], symbolId: 'icon-[name]', inject: 'body-last', }),위 변경을 위해 파일 상단에 유틸 import/헬퍼를 추가하세요(선택 코드 블록):
// 추가 필요 (파일 상단) import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = dirname(fileURLToPath(import.meta.url));
14-18: 제안: symbolId 패턴에 디렉터리명 또는 해시 추가 검토스크립트 검증 결과
packages/design-system/src/icons/source내 SVG 파일명은 중복이 없는 것으로 확인되었습니다. 하지만 향후 아이콘 파일 추가 시 이름 충돌 가능성을 사전에 방지하기 위해,symbolId에[dir]또는[hash]토큰을 포함하는 방식을 고려해 보시기를 권장드립니다.
토큰 지원 확인
@pivanov/vite-plugin-svg-sprite는[dir],[name],[hash]토큰을 지원합니다.[dir]: 아이콘이 위치한 상대 디렉터리명[name]: SVG 파일명(확장자 제외)[hash]: 파일 내용 기반 해시값예시 변경안
svgSpritePlugin({ iconDirs: ['../../packages/design-system/src/icons/source'], - symbolId: 'icon-[name]', + // 디렉터리명-파일명 조합 + symbolId: 'icon-[dir]-[name]', });또는
svgSpritePlugin({ iconDirs: ['../../packages/design-system/src/icons/source'], + // 파일명-해시 조합 + symbolId: 'icon-[name]-[hash:6]', });추가 확인 사항
- 팀 컨벤션 또는 디자인 시스템 가이드에 따른
symbolId형식- Icon 컴포넌트를 사용하는 모든 소비처에서 변경된 ID 패턴이 정상 동작하는지 테스트
위 제안은 필수가 아닌 권고사항이며, 현재 코드가 문제 없이 작동하는 점을 참고해 주시기 바랍니다.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
apps/client/vite.config.ts(1 hunks)apps/extension/vite.config.ts(2 hunks)apps/landing/vite.config.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/client/vite.config.ts
- apps/extension/vite.config.ts
🔇 Additional comments (2)
apps/landing/vite.config.ts (2)
10-19: 플러그인 구성 순서와 옵션은 전반적으로 적절합니다react → tsconfigPaths → tailwindcss → svgSprite 순서, inject: 'body-last' 선택 모두 현재 랜딩 앱(use SPA)에는 무리 없습니다. 위 경로/ID 안정화만 반영되면 충분해 보입니다.
5-5: 플러그인 의존성 및 호환성 검증 완료
- apps/landing와 루트 package.json 모두 devDependencies에
@pivanov/vite-plugin-svg-sprite@^3.1.3가 선언되어 있습니다.- pnpm-lock.yaml에서 Vite@7.1.2 환경에서
vite-plugin-svg-sprite@3.1.3이 정상 해상(resolution)된 것을 확인했습니다.- 프로젝트가 Vite 7을 사용 중이며, 플러그인도 해당 버전과 호환됨을 lockfile에서 명백히 확인할 수 있습니다.
추가로, CI 및 로컬 빌드에서 SVG 스프라이트 기능이 예상대로 동작하는지만 한 번 더 검증해주시면 됩니다.
|
✅ Storybook chromatic 배포 확인: |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/design-system/package.json (2)
19-19: Prettier 실행 주체 확인(로컬 vs 워크스페이스 루트)현재 패키지 devDependencies에
prettier가 없는데, 스크립트는prettier --write를 직접 호출합니다. 루트에 설치되어 있고 pnpm이 PATH로 노출해주는 전제라면 OK지만, 워크스페이스 설정에 따라 실패할 수 있습니다. 두 가지 중 하나로 명확히 하는 것을 권장합니다.옵션 A(권장, 루트 사용 명시):
- "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && prettier --write src/icons/iconNames.ts", + "generate:icons": "tsx src/icons/scripts/generate-icon-list.ts && pnpm -w prettier --write src/icons/iconNames.ts",옵션 B(패키지 로컬 설치):
"devDependencies": { + "prettier": "^3", ... }원하시면 워크스페이스 구성에 맞춰 한쪽으로 정리하는 추가 PR 패치 제안 드리겠습니다.
55-55: 빌드/개발 전용 의존성은 devDependencies로 이동 권장
@pivanov/vite-plugin-svg-sprite와svgo는 런타임이 아닌 빌드/도구 체인 전용입니다. 라이브러리 소비자 번들 무게와 설치 시간을 줄이기 위해 devDependencies로 이동하는 것을 권장합니다."devDependencies": { ... + "@pivanov/vite-plugin-svg-sprite": "^3.1.3", + "svgo": "^4.0.0", "tsx": "^4.20.4", ... }, "dependencies": { - "@pivanov/vite-plugin-svg-sprite": "^3.1.3", "@radix-ui/react-slot": "^1.2.3", ... - "svgo": "^4.0.0", "tailwind-merge": "^3.3.1", "tw-animate-css": "^1.3.7" }주의: 다른 앱들의 Vite 설정에서 이 플러그인을 직접 사용한다면, 각 앱 패키지의 devDependencies에 명시돼 있어야 합니다.
Also applies to: 62-62
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (2)
packages/design-system/package.json(2 hunks)packages/design-system/vite.config.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/design-system/vite.config.ts
🔇 Additional comments (3)
packages/design-system/package.json (3)
21-21: 아이콘 통합 스크립트(icons) 추가 굿
pnpm icons:clean && pnpm generate:icons로 DX가 좋아졌습니다. 연쇄 실행 순서도 적절합니다.
48-48:tsx추가 적절아이콘 리스트 생성 스크립트 실행을 위한
tsx추가가 타당합니다.
18-18: 로컬 설치된 SVGO v4에서 아래 명령들을 직접 실행해 주세요.
옵션-f(디렉터리 지정)와--multipass가 정상 동작하는지 확인이 필요합니다.# SVGO 버전 확인 npx svgo --version # help 출력에서 -f, --multipass 옵션 노출 여부 확인 npx svgo --help | grep -E " -f |--multipass" # 실제 dry-run 테스트 (성공 시 아무 에러 없이 OK 메시지 출력) npx svgo \ -f packages/design-system/src/icons/source \ --config=packages/design-system/svgo.config.mjs \ --multipass \ --dry-run && echo "OK"실행 후 결과를 공유해 주시면 감사하겠습니다.
📌 Related Issues
✅ 체크 리스트
📄 Tasks
⭐ PR Point (To Reviewer)
Icons svg sprite 방식 적용
svg sprite장점은 해당 pr내용과 같아요.
다만 width,height 값이 svg파일에 들어가 있으면 ui가 깨지거나 원하는대로 조정하기가 힘들어 일일이 삭제해줘야하는 번거로움이 있어 svgr로 바꿀까하는 고민이있었습니다. 하지만 다음글에 보면 svgr도 일일이 삭제해줘야하는 번거로움은 동일해보여 svg sprite 방식으로 하기로 결정했습니다.
width,height 자동 삭제
width,height는 개발자가 삭제하거나 피그마에서 export할 때 방식 수정하는 방법이 있었어요. 피그마에서 플러그인 사용해서 설정하는 방식이 익숙하지않아 svgo를 사용해서 명령어로 이미지들의 width,height 가 자동으로 삭제되게하였습니다. 그래서 저번 방식에서 추가적으로 명령어를 한번 더 입력해줘야합니다-! 그럼 자동으로 모든 파일의 width,height 삭제 되어용.. 이정도는 괜찮죠?
자동 프리티어
명령어 입력후 아이콘의 이름이 파일에 추가될 때 자동으로 프리티어 적용이 안되서 ctrl+s해서 정렬해줬었습니다. 이부분 또한 자동으로 같이 포맷되게 적용했습니다.
current color 자동 변경
사실 이부분은 적용하지 않았습니다. 밖에서 컬러 주입하여 사용하려 fii/stroke의 컬러를 기본컬러-> current color로 자동 변환해주는게 1번과 동일하게 svgo 최적화가 있었습니다. 다만 이렇게되면 컬러를 주입하지 않을경우 색이 다 날라가거나, 기본 디폴트 컬러를 적용해두는 방식으러 해야하는데 이 방식이 더 복잡할거같다는 생각이 들었습니다. 기본 아이콘이 아닌 캐릭터같은 파일들은 밖에서 색을 주입하기도 힘들고 아이콘이 많은편이아니라 중복되고 색만 다른 아이콘들은 번거롭지만 일일이 삭제하고 주입하는 방식으로하는게 좋을것 같다고 판단했습니다. 이 방식에 대해서 추가적의 의견도 궁금합니다-!!!
사용방법
📷 Screenshot
Summary by CodeRabbit
신기능
작업(Chores)