Skip to content

Feat/design system#6

Merged
citron03 merged 9 commits intomainfrom
feat/design-system
Nov 16, 2025
Merged

Feat/design system#6
citron03 merged 9 commits intomainfrom
feat/design-system

Conversation

@citron03
Copy link
Owner

@citron03 citron03 commented Nov 14, 2025

PR Type

Enhancement, Bug fix, Documentation


Description

  • 새 디자인 시스템 패키지 및 ColorPicker 컴포넌트 추가

  • pnpm 카탈로그를 통한 종속성 관리 중앙화

  • 웹 앱의 SSR 및 클라이언트 렌더링 문제 해결

  • ESLint, Storybook 등 프로젝트 설정 업데이트


Diagram Walkthrough

flowchart LR
    A["새 디자인 시스템 패키지"] --> B["ColorPicker 컴포넌트 추가"];
    C["pnpm 카탈로그 도입"] --> D["중앙화된 종속성 관리"];
    E["웹 앱 개선"] --> F["SSR/클라이언트 렌더링 문제 해결"];
    E --> G["이벤트 버스 리팩토링"];
Loading

File Walkthrough

Relevant files
New component
1 files
index.tsx
새 `ColorPicker` 컴포넌트 구현                                                                   
+56/-0   
Refactoring
2 files
page.tsx
이벤트 버스 로직을 별도 파일로 분리                                                                         
+1/-27   
page.tsx
`VirtualListPage` 컴포넌트 내보내기 방식 변경                                               
+1/-1     
New module
2 files
eventBus.ts
이벤트 버스 유틸리티 함수를 위한 새 모듈 추가                                                             
+27/-0   
index.ts
디자인 시스템 패키지 진입점 및 `ColorPicker` 내보내기                                         
+4/-0     
Configuration changes
6 files
next.config.ts
Next.js 및 Vanilla Extract 플러그인 설정 조정                                         
+4/-7     
main.ts
Storybook에 Vanilla Extract 플러그인 추가                                             
+22/-0   
preview.ts
Storybook 미리보기 기본 설정 추가                                                                   
+10/-0   
eslint.config.js
ESLint TypeScript 플러그인 임포트 및 설정 수정                                             
+2/-8     
tsconfig.base.json
`moduleResolution`을 `node`에서 `bundler`로 변경                             
+1/-1     
tsconfig.json
디자인 시스템 패키지 TypeScript 설정 추가                                                         
+13/-0   
New styles
1 files
index.css.ts
`ColorPicker` 컴포넌트 스타일 정의                                                               
+29/-0   
Documentation
3 files
ColorPicker.stories.tsx
`ColorPicker` 컴포넌트 Storybook 스토리 추가                                           
+25/-0   
README.md
디자인 시스템 프로젝트에 대한 상세 README 추가                                                       
+171/-0 
README.md
루트 README 파일 한글화                                                                                 
+32/-35 
Bug fix
3 files
index.tsx
`visibleCount` 계산을 `useEffect`로 옮겨 SSR 문제 해결                         
+5/-1     
index.tsx
`visibleCount` 계산을 `useEffect`로 옮겨 SSR 문제 해결                         
+5/-1     
tui-grid@4.21.22.patch
`tui-grid.css` 파일에 대한 CSS 호환성 패치 적용                                           
+15/-0   
Client-side rendering
1 files
page.tsx
`TuiGridReact` 컴포넌트를 동적으로 임포트하여 SSR 비활성화                                 
+6/-1     
Type changes
1 files
layout.tsx
모달 prop을 필수로 변경                                                                                   
+1/-1     
Dependency management
4 files
pnpm-workspace.yaml
pnpm 카탈로그를 정의하여 종속성 버전 중앙 관리                                                         
+147/-2 
package.json
pnpm 카탈로그 스크립트 및 디자인 시스템 스크립트 추가, 종속성 업데이트                             
+71/-21 
package.json
`apps/web` 종속성을 pnpm 카탈로그 참조로 업데이트 및 새 종속성 추가                       
+40/-32 
package.json
`apps/scripts` 종속성을 pnpm 카탈로그 참조로 업데이트                                     
+4/-4     
Tooling
1 files
convert-to-catalog.mjs
`package.json` 종속성을 카탈로그 참조로 변환하는 스크립트 추가                               
+130/-0 
New package
1 files
package.json
새 디자인 시스템 패키지 정의 및 종속성 설정                                                               
+37/-0   
Additional files
1 files
pnpm-lock.yaml +9039/-3470

@github-actions
Copy link

github-actions bot commented Nov 14, 2025

PR Reviewer Guide 🔍

(Review updated until commit e2a9d9e)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

ColorPicker 상태 동기화

ColorPicker 컴포넌트에서 color prop이 변경될 때 internalColor 상태를 useEffect로 동기화하는 로직이 있어요. 일반적으로는 잘 작동하지만, color prop이 자주 변경되거나 복잡한 객체일 경우 불필요한 리렌더링이나 예측치 못한 동작을 유발할 수 있습니다. 현재는 단순한 색상 문자열이라 괜찮지만, 혹시 나중에 복잡한 객체로 확장될 경우를 대비해서 useRefuseMemo를 활용하여 최적화할 여지가 있는지 한번 고민해 보면 좋을 것 같아요!

useEffect(() => {
  setInternalColor(color);
}, [color]);
React Compiler (실험적 기능)

reactCompiler: true 설정은 React 19의 실험적인 기능으로, 성능 최적화에 큰 도움이 될 것으로 기대됩니다! 🎉 하지만 아직 실험 단계이므로, 예상치 못한 동작이나 향후 버전에서 변경될 가능성이 있다는 점을 인지하고 있으면 좋을 것 같아요. 혹시 컴파일러 적용 후 특이사항이 발생하면 바로 공유해주세요!

reactCompiler: true,
tui-grid 패치 관리

tui-grid에 패치를 적용하여 특정 CSS 문제를 해결하신 점은 정말 현명한 방법이에요! 👍 외부 라이브러리 버그를 기다리지 않고 빠르게 대응할 수 있죠. 다만, 이 패치가 tui-grid의 다음 버전에서 공식적으로 해결되는지 주기적으로 확인하고, 해결된다면 패치를 제거하여 관리 부담을 줄이는 것이 좋을 것 같아요!

diff --git a/dist/tui-grid.css b/dist/tui-grid.css
index 20d5551aea9bc49be05b1f316907026db27e989d..fa76f7199bd664df9c5c9ade0f7f1e34dde5b0d1 100644
--- a/dist/tui-grid.css
+++ b/dist/tui-grid.css
@@ -395,8 +395,8 @@
   display: block;
   overflow: hidden;
   line-height: 1.5;
-  *margin-left: -2px;
-  *padding-left: 2px;
+  margin-left: -2px;
+  padding-left: 2px;
 }
 .tui-grid-cell-content input[type='text'],
 .tui-grid-cell-content input[type='password'] {

@github-actions
Copy link

github-actions bot commented Nov 14, 2025

PR Code Suggestions ✨

Latest suggestions up to e2a9d9e

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
창 크기 변경 시 목록 업데이트

VirtualizedList 컴포넌트의 visibleCount는 창 크기 변경 시 업데이트되지 않습니다. window.innerHeight는 창 크기에
따라 달라지므로, 창 크기가 조정될 때 visibleCount를 다시 계산하고 업데이트하도록 resize 이벤트 리스너를 추가해야 합니다. 이는
가상화된 목록의 올바른 렌더링을 보장합니다.

apps/web/app/virtual-list/absolute/index.tsx [12-14]

 useEffect(() => {
-  setVisibleCount(Math.ceil(window.innerHeight / itemHeight) + bufferCount * 2);
+  const calculateVisibleCount = () => {
+    setVisibleCount(Math.ceil(window.innerHeight / itemHeight) + bufferCount * 2);
+  };
+  calculateVisibleCount(); // 초기 계산
+  window.addEventListener('resize', calculateVisibleCount);
+  return () => window.removeEventListener('resize', calculateVisibleCount);
 }, []);
Suggestion importance[1-10]: 10

__

Why: The visibleCount calculation depends on window.innerHeight, which changes on window resize. Adding a resize event listener and its cleanup is crucial to ensure the virtualized list renders correctly and maintains its functionality across different window sizes.

High
페이지 컴포넌트 내보내기 수정

apps/web/app/virtual-list/page.tsx 파일의 VirtualListPage 컴포넌트는 더 이상 내보내지지 않습니다.
Next.js 페이지 컴포넌트는 일반적으로 export default로 내보내져야 해당 경로에서 접근할 수 있습니다. 이 변경으로 인해 페이지가
렌더링되지 않을 수 있습니다.

apps/web/app/virtual-list/page.tsx [9]

-const VirtualListPage = () => {
+export default function VirtualListPage() {
Suggestion importance[1-10]: 10

__

Why: Next.js page components require a export default statement to be accessible as a page. The PR removes this export, which would prevent the VirtualListPage from being rendered, making this a critical functional issue.

High
prepare 스크립트의 무한 루프 가능성 제거

apps/design-system/package.jsonprepare 스크립트가 pnpm -w install로 설정되어 있습니다. prepare
스크립트는 일반적으로 현재 패키지의 빌드 또는 타입스크립트 컴파일과 같은 작업을 수행하는 데 사용됩니다. pnpm -w install은 전체
워크스페이스의 종속성을 설치하는 명령으로, 이 스크립트가 pnpm install에 의해 트리거될 경우 무한 루프를 유발하거나 의도치 않은 동작을 초래할
수 있습니다. 이 스크립트의 목적을 명확히 하고, 필요한 경우 pnpm install 대신 pnpm build와 같은 패키지별 빌드 명령으로 대체하는
것을 고려해야 합니다.

apps/design-system/package.json [13]

-"prepare": "pnpm -w install"
+"prepare": "pnpm build"
Suggestion importance[1-10]: 9

__

Why: prepare 스크립트에서 pnpm -w install을 호출하는 것은 pnpm install 시 무한 루프를 유발할 수 있는 심각한 문제입니다. pnpm build와 같이 패키지 자체의 빌드 명령으로 변경하여 올바른 동작을 보장해야 합니다.

High
General
색상 견본 실시간 업데이트

ColorPicker 컴포넌트의 colorSwatchcolor prop 대신 internalColor 상태를 사용하여 색상을 표시해야 합니다.
이렇게 하면 사용자가 SketchPicker와 상호작용할 때 색상 견본이 실시간으로 업데이트되어 더 나은 사용자 경험을 제공할 수 있습니다. 현재
구현은 외부 color prop이 변경될 때만 견본을 업데이트합니다.

apps/design-system/src/components/ColorPicker/index.tsx [42]

-<div className={styles.colorSwatch} style={{ background: color }} />
+<div className={styles.colorSwatch} style={{ background: internalColor }} />
Suggestion importance[1-10]: 9

__

Why: Changing the colorSwatch background to internalColor ensures the swatch updates in real-time as the user interacts with the SketchPicker, significantly improving the user experience. The current implementation only updates the swatch when the external color prop changes.

High
카탈로그를 사용하여 종속성 버전 관리 통일

pnpm-workspace.yaml에 패키지 카탈로그가 정의되어 있음에도 불구하고, 루트 package.json
apps/web/package.json의 여러 종속성들이 여전히 특정 버전으로 직접 지정되어 있습니다. 이는 카탈로그를 통한 중앙 집중식 버전 관리의
이점을 상실하게 하므로, 해당 종속성들을 pnpm-workspace.yaml의 적절한 카탈로그에 추가하고 catalog: 또는 catalog: 형식으로
참조하도록 수정하여 일관성을 확보해야 합니다.

package.json [61-67]

-"eslint": "^9.39.1",
-"eslint-config-next": "^16.0.3",
-"eslint-config-prettier": "^10.1.8",
-"eslint-plugin-import": "^2.32.0",
-"eslint-plugin-prettier": "^5.5.4",
-"eslint-plugin-react": "^7.37.5",
-"eslint-plugin-react-hooks": "^7.0.1"
+"eslint": "catalog:eslint",
+"eslint-config-next": "catalog:eslint",
+"eslint-config-prettier": "catalog:eslint",
+"eslint-plugin-import": "catalog:eslint",
+"eslint-plugin-prettier": "catalog:eslint",
+"eslint-plugin-react": "catalog:eslint",
+"eslint-plugin-react-hooks": "catalog:eslint"
Suggestion importance[1-10]: 9

__

Why: 여러 ESLint 관련 종속성들이 pnpm-workspace.yaml의 카탈로그에 정의되어 있음에도 불구하고 package.json에서 직접 버전을 지정하고 있습니다. 카탈로그 참조를 사용하면 모노레포 전체의 종속성 버전 관리가 통일되어 유지보수성이 향상됩니다.

High
카탈로그 버전 참조를 사용하여 일관성 유지

pnpm-workspace.yamlcatalog 섹션에 eslint-plugin-react-compiler
npm:eslint-plugin-react-compiler@experimental로 정의되어 있습니다. 하지만 루트 package.json
apps/web/package.json에서는 19.1.0-rc.2와 같이 특정 버전으로 직접 지정되어 있어 카탈로그 사용의 일관성을 해치고 있습니다.
카탈로그를 통해 버전을 관리하도록 catalog:를 사용하거나, 카탈로그의 버전을 19.1.0-rc.2로 업데이트하여 일관성을 유지해야 합니다.

package.json [68]

-"eslint-plugin-react-compiler": "19.1.0-rc.2"
+"eslint-plugin-react-compiler": "catalog:"
Suggestion importance[1-10]: 8

__

Why: eslint-plugin-react-compiler의 버전이 pnpm-workspace.yaml의 카탈로그와 package.json에서 다르게 정의되어 있어 일관성을 해칩니다. 카탈로그 참조를 사용하면 중앙 집중식 버전 관리가 가능해집니다.

Medium

Previous suggestions

Suggestions up to commit 254ef16
CategorySuggestion                                                                                                                                    Impact
General
초기 렌더링 깜박임을 방지합니다

visibleCountuseState(0)으로 초기화하면 초기 렌더링 시 목록이 비어 보이거나 잘못된 레이아웃이 표시될 수 있습니다.
window.innerHeight에 접근할 수 있는 클라이언트 측에서 useState의 초기화 함수 내에서 visibleCount를 계산하여 초기
렌더링 시 올바른 값을 가지도록 하세요.

apps/web/app/virtual-list/absolute/index.tsx [10-14]

-const [visibleCount, setVisibleCount] = useState(0);
+const [visibleCount, setVisibleCount] = useState(() =>
+  typeof window !== 'undefined'
+    ? Math.ceil(window.innerHeight / itemHeight) + bufferCount * 2
+    : 0
+);
 
-  useEffect(() => {
-    setVisibleCount(Math.ceil(window.innerHeight / itemHeight) + bufferCount * 2);
-  }, []);
-
Suggestion importance[1-10]: 9

__

Why: Initializing visibleCount within useState's initializer function, with a window check, correctly prevents potential layout shifts or incorrect rendering during initial load, especially in SSR environments. This improves user experience and component correctness.

High
README 예시의 private 설정 수정

apps/design-system 패키지는 npm/GitHub Packages로 배포 가능한 패키지 구조를 목표로 하지만, README 예시의
package.json에는 "private": true로 설정되어 있습니다. 이는 패키지 배포를 방해하므로, 예시에서 "private": false
수정하여 실제 목표와 일치시켜야 합니다.

apps/design-system/README.md [33-46]

 // 예시 (apps/design-system/package.json)
 {
   "name": "@your-scope/design-system",
-  "private": true,
+  "private": false,
   "version": "0.1.0",
   "type": "module",
   "scripts": {
     "dev": "storybook dev -p 6006",
     "build": "build-storybook",
     "lint": "eslint . --ext .ts,.tsx",
     "test": "vitest"
   }
 }
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies an inconsistency between the README's stated goal of a publishable package and the private: true setting in the example package.json. Correcting this in the documentation is important for clarity.

Medium
React Strict Mode를 활성화합니다

reactStrictModefalse로 설정하면 개발 모드에서 잠재적인 문제를 감지하는 React의 기능을 비활성화합니다. 이는 렌더링 동작의
불일치나 예상치 못한 부작용을 숨길 수 있습니다. reactStrictModetrue로 유지하여 애플리케이션의 안정성과 미래 호환성을 보장하는 것이
좋습니다.

apps/web/next.config.ts [21-24]

 reactCompiler: true,
 experimental: {},
 // useEffect 두 번 실행 방지
-reactStrictMode: false,
+reactStrictMode: true,
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out the benefits of reactStrictMode for identifying potential issues. While the PR explicitly disables it, enabling strict mode is generally a good practice for application stability and future compatibility.

Medium
Possible issue
라이브러리 빌드 스크립트 추가

apps/design-system 패키지는 maintypes 필드를 통해 라이브러리 빌드를 예상하지만, 실제 컴포넌트 라이브러리 코드를 dist
폴더로 컴파일하는 스크립트가 누락되어 있습니다. tsc 명령어를 사용하여 라이브러리를 빌드하는 build:lib 스크립트를 추가하고, prepare
스크립트에서 이를 호출하도록 업데이트해야 합니다.

apps/design-system/package.json [8-14]

 "scripts": {
   "dev": "storybook dev -p 6006",
   "build": "build-storybook -o build",
+  "build:lib": "tsc",
   "lint": "eslint . --ext .ts,.tsx",
   "test": "vitest",
-  "prepare": "pnpm -w install"
+  "prepare": "pnpm run build:lib"
 },
Suggestion importance[1-10]: 9

__

Why: This suggestion addresses a critical missing piece for a library package. Without a build:lib script, the main and types fields in package.json are ineffective, preventing proper consumption or publication of the library.

High
모달 prop을 선택 사항으로 유지합니다

modal prop을 선택 사항(modal?: ReactNode;)에서 필수(modal: ReactNode;)로 변경하면 이 Layout 컴포넌트를
사용하는 기존 코드에서 타입 오류가 발생할 수 있습니다. modal이 항상 제공되지 않는 경우, 이전처럼 선택 사항으로 유지하거나 모든 호출 사이트가
업데이트되었는지 확인해야 합니다.

apps/web/app/next-modal/screen/layout.tsx [5]

-modal: ReactNode;
+modal?: ReactNode;
Suggestion importance[1-10]: 8

__

Why: Changing the modal prop from optional to required can introduce breaking changes and type errors in existing code. The suggestion correctly highlights this potential issue, which is important for API stability and backward compatibility.

Medium
eslint-plugin-react-compiler 버전 일치

pnpm-workspace.yamlcatalog에 정의된 eslint-plugin-react-compiler 버전이 루트 package.json
devDependencies에 명시된 버전(19.1.0-rc.2)과 일치하지 않습니다. 일관된 종속성 관리를 위해 catalog의 버전을 루트
package.json과 동일하게 업데이트해야 합니다.

pnpm-workspace.yaml [10]

-eslint-plugin-react-compiler: npm:eslint-plugin-react-compiler@experimental
+eslint-plugin-react-compiler: 19.1.0-rc.2
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out a version inconsistency between pnpm-workspace.yaml and package.json. Aligning these versions ensures consistent dependency management and avoids potential issues with the experimental tag.

Medium
Suggestions
CategorySuggestion                                                                                                                                    Impact
General
색상 선택기 성능 개선

SketchPickeronChange는 사용자가 색상을 조정하는 동안 지속적으로 호출됩니다. 현재 구현은 이 변경 사항을 부모 컴포넌트에 즉시
전달하여 불필요한 리렌더링을 유발하고 성능에 영향을 줄 수 있습니다. ColorPicker 컴포넌트 내부에 임시 색상 상태를 관리하고,
SketchPickeronChangeComplete를 사용하여 최종 색상 선택 시에만 부모의 onChange를 호출하도록 변경하여 성능을
최적화하세요.

apps/design-system/src/components/ColorPicker/index.tsx [12-36]

 export const ColorPicker = ({ color, onChange }: ColorPickerProps): JSX.Element => {
   const [displayColorPicker, setDisplayColorPicker] = useState(false);
+  const [internalColor, setInternalColor] = useState(color);
+
+  useEffect(() => {
+    setInternalColor(color);
+  }, [color]);
 
   const handleClick = () => {
     setDisplayColorPicker(!displayColorPicker);
   };
 
   const handleClose = () => {
     setDisplayColorPicker(false);
+  };
+
+  const handleSketchPickerChange = (newColor: ColorResult) => {
+    setInternalColor(newColor.hex);
+  };
+
+  const handleSketchPickerChangeComplete = (newColor: ColorResult) => {
+    onChange(newColor);
   };
 
   return (
     <div>
       <div className={styles.swatch} onClick={handleClick}>
         <div className={styles.colorSwatch} style={{ background: color }} />
       </div>
       {displayColorPicker ? (
         <div className={styles.popover}>
           <div className={styles.cover} onClick={handleClose} />
-          <SketchPicker color={color} onChange={onChange} />
+          <SketchPicker
+            color={internalColor}
+            onChange={handleSketchPickerChange}
+            onChangeComplete={handleSketchPickerChangeComplete}
+          />
         </div>
       ) : null}
     </div>
   );
 };
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a performance issue with SketchPicker's continuous onChange calls. It provides an excellent solution by introducing internal state and using onChangeComplete to optimize re-renders and properly manage the controlled component's state.

High
패키지 배포 설정 확인

README.md에서는 디자인 시스템이 "npm/GitHub Packages로 배포 가능한 패키지 구조"를 목표로 한다고 명시하고 있지만,
package.json 파일에는 "private": true로 설정되어 있습니다. 이 패키지를 외부에 배포할 계획이라면 private: true
제거해야 합니다. 그렇지 않다면, README.md의 목표를 내부 사용으로 명확히 수정하는 것이 좋습니다.

apps/design-system/package.json [4]

-"private": true,
+"private": false,
Suggestion importance[1-10]: 9

__

Why: README.md에서 패키지 배포를 목표로 한다고 명시했지만, package.json"private": true로 설정되어 있어 배포가 불가능합니다. 이는 프로젝트의 목표와 현재 설정 간의 중요한 불일치이므로 수정이 필요합니다.

High
종속성 버전 일관성 유지

pnpm-workspace.yamlcatalog에서 Storybook 관련 패키지 버전이 정의되어 있으므로, devDependencies 내의 모든
종속성 버전을 *로 통일하여 중앙 집중식 버전 관리를 활용하는 것이 좋습니다. 이는 일관성을 유지하고 버전 충돌 위험을 줄이는 데 도움이 됩니다.

apps/design-system/package.json [19-31]

 "devDependencies": {
-  "@storybook/addon-essentials": "8.5.0",
-  "@storybook/addon-interactions": "8.5.0",
-  "@storybook/builder-vite": "8.5.0",
-  "@storybook/cli": "8.5.0",
-  "@storybook/react": "8.5.0",
-  "@storybook/react-vite": "8.5.0",
-  "storybook": "8.5.0",
+  "@storybook/addon-essentials": "*",
+  "@storybook/addon-interactions": "*",
+  "@storybook/builder-vite": "*",
+  "@storybook/cli": "*",
+  "@storybook/react": "*",
+  "@storybook/react-vite": "*",
+  "storybook": "*",
   "typescript": "*",
-  "vite": "5.4.21",
+  "vite": "*",
   "@vanilla-extract/css": "*",
   "@vanilla-extract/vite-plugin": "*"
 },
Suggestion importance[1-10]: 7

__

Why: pnpm-workspace.yamlcatalog에서 Storybook 및 Vite 버전이 정의되어 있으므로, apps/design-system/package.jsondevDependencies에서 해당 패키지 버전을 *로 통일하여 중앙 집중식 버전 관리를 활용하는 것이 좋습니다.

Medium
Possible issue
잘못된 스크립트 필터링 수정

ds 스크립트가 pnpm run web을 사용하여 web 애플리케이션을 대상으로 지정하고 있습니다. 이는 디자인 시스템 패키지를 직접 필터링하고 해당
패키지 내에서 명령을 실행하도록 수정해야 합니다. 현재 설정은 의도한 대로 작동하지 않을 것입니다.

package.json [7-8]

-"ds": "pnpm run web --filter @citron03/design-system",
+"ds": "pnpm --filter @citron03/design-system",
 "ds:dev": "pnpm run ds dev",
Suggestion importance[1-10]: 9

__

Why: ds 스크립트가 pnpm run web을 사용하여 web 애플리케이션을 대상으로 지정하는 것은 잘못되었습니다. pnpm --filter를 직접 사용하여 디자인 시스템 패키지를 대상으로 지정해야 스크립트가 의도한 대로 작동합니다.

High

@github-actions
Copy link

Persistent review updated to latest commit a87571a

@github-actions
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
색상 선택기 성능 개선

SketchPickeronChange는 사용자가 색상을 조정하는 동안 지속적으로 호출됩니다. 현재 구현은 이 변경 사항을 부모 컴포넌트에 즉시
전달하여 불필요한 리렌더링을 유발하고 성능에 영향을 줄 수 있습니다. ColorPicker 컴포넌트 내부에 임시 색상 상태를 관리하고,
SketchPickeronChangeComplete를 사용하여 최종 색상 선택 시에만 부모의 onChange를 호출하도록 변경하여 성능을
최적화하세요.

apps/design-system/src/components/ColorPicker/index.tsx [12-36]

 export const ColorPicker = ({ color, onChange }: ColorPickerProps): JSX.Element => {
   const [displayColorPicker, setDisplayColorPicker] = useState(false);
+  const [internalColor, setInternalColor] = useState(color);
+
+  useEffect(() => {
+    setInternalColor(color);
+  }, [color]);
 
   const handleClick = () => {
     setDisplayColorPicker(!displayColorPicker);
   };
 
   const handleClose = () => {
     setDisplayColorPicker(false);
+  };
+
+  const handleSketchPickerChange = (newColor: ColorResult) => {
+    setInternalColor(newColor.hex);
+  };
+
+  const handleSketchPickerChangeComplete = (newColor: ColorResult) => {
+    onChange(newColor);
   };
 
   return (
     <div>
       <div className={styles.swatch} onClick={handleClick}>
         <div className={styles.colorSwatch} style={{ background: color }} />
       </div>
       {displayColorPicker ? (
         <div className={styles.popover}>
           <div className={styles.cover} onClick={handleClose} />
-          <SketchPicker color={color} onChange={onChange} />
+          <SketchPicker
+            color={internalColor}
+            onChange={handleSketchPickerChange}
+            onChangeComplete={handleSketchPickerChangeComplete}
+          />
         </div>
       ) : null}
     </div>
   );
 };
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a performance issue with SketchPicker's continuous onChange calls. It provides an excellent solution by introducing internal state and using onChangeComplete to optimize re-renders and properly manage the controlled component's state.

High
패키지 배포 설정 확인

README.md에서는 디자인 시스템이 "npm/GitHub Packages로 배포 가능한 패키지 구조"를 목표로 한다고 명시하고 있지만,
package.json 파일에는 "private": true로 설정되어 있습니다. 이 패키지를 외부에 배포할 계획이라면 private: true
제거해야 합니다. 그렇지 않다면, README.md의 목표를 내부 사용으로 명확히 수정하는 것이 좋습니다.

apps/design-system/package.json [4]

-"private": true,
+"private": false,
Suggestion importance[1-10]: 9

__

Why: README.md에서 패키지 배포를 목표로 한다고 명시했지만, package.json"private": true로 설정되어 있어 배포가 불가능합니다. 이는 프로젝트의 목표와 현재 설정 간의 중요한 불일치이므로 수정이 필요합니다.

High
종속성 버전 일관성 유지

pnpm-workspace.yamlcatalog에서 Storybook 관련 패키지 버전이 정의되어 있으므로, devDependencies 내의 모든
종속성 버전을 *로 통일하여 중앙 집중식 버전 관리를 활용하는 것이 좋습니다. 이는 일관성을 유지하고 버전 충돌 위험을 줄이는 데 도움이 됩니다.

apps/design-system/package.json [19-31]

 "devDependencies": {
-  "@storybook/addon-essentials": "8.5.0",
-  "@storybook/addon-interactions": "8.5.0",
-  "@storybook/builder-vite": "8.5.0",
-  "@storybook/cli": "8.5.0",
-  "@storybook/react": "8.5.0",
-  "@storybook/react-vite": "8.5.0",
-  "storybook": "8.5.0",
+  "@storybook/addon-essentials": "*",
+  "@storybook/addon-interactions": "*",
+  "@storybook/builder-vite": "*",
+  "@storybook/cli": "*",
+  "@storybook/react": "*",
+  "@storybook/react-vite": "*",
+  "storybook": "*",
   "typescript": "*",
-  "vite": "5.4.21",
+  "vite": "*",
   "@vanilla-extract/css": "*",
   "@vanilla-extract/vite-plugin": "*"
 },
Suggestion importance[1-10]: 7

__

Why: pnpm-workspace.yamlcatalog에서 Storybook 및 Vite 버전이 정의되어 있으므로, apps/design-system/package.jsondevDependencies에서 해당 패키지 버전을 *로 통일하여 중앙 집중식 버전 관리를 활용하는 것이 좋습니다.

Medium
Possible issue
잘못된 스크립트 필터링 수정

ds 스크립트가 pnpm run web을 사용하여 web 애플리케이션을 대상으로 지정하고 있습니다. 이는 디자인 시스템 패키지를 직접 필터링하고 해당
패키지 내에서 명령을 실행하도록 수정해야 합니다. 현재 설정은 의도한 대로 작동하지 않을 것입니다.

package.json [7-8]

-"ds": "pnpm run web --filter @citron03/design-system",
+"ds": "pnpm --filter @citron03/design-system",
 "ds:dev": "pnpm run ds dev",
Suggestion importance[1-10]: 9

__

Why: ds 스크립트가 pnpm run web을 사용하여 web 애플리케이션을 대상으로 지정하는 것은 잘못되었습니다. pnpm --filter를 직접 사용하여 디자인 시스템 패키지를 대상으로 지정해야 스크립트가 의도한 대로 작동합니다.

High

@github-actions
Copy link

Persistent review updated to latest commit 254ef16

@github-actions
Copy link

Persistent review updated to latest commit e2a9d9e

@citron03 citron03 merged commit b741c4a into main Nov 16, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant