Refactor(client): bundle size optimization#199
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
걷기라우팅 설정을 변경하여 Remind 경로를 인덱스 라우트로 전환하고, Vite 빌드 설정에서 번들 시각화 플러그인과 수동 청크 분할(React 및 framer-motion 벤더 분리)을 추가했으며, 관련 dev 의존성을 package.json에 포함했습니다. 변경 사항
예상 코드 리뷰 노력🎯 2 (간단함) | ⏱️ ~12분 추천 검토자
시
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. 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. Comment |
|
✅ Storybook chromatic 배포 확인: |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
apps/client/vite.config.ts (2)
7-7: visualizer 자동 열기 동작을 환경에 따라 조건부로 설정하는 것을 고려하세요.
open: true설정은 매 빌드마다 브라우저를 자동으로 열어 개발 중에 번거로울 수 있습니다.다음과 같이 환경 변수를 통해 조건부로 설정하는 것을 권장합니다:
- visualizer({ filename: 'dist/bundle-analysis.html', open: true }), + visualizer({ + filename: 'dist/bundle-analysis.html', + open: process.env.ANALYZE === 'true' + }),그런 다음 package.json에 별도의 스크립트를 추가할 수 있습니다:
"scripts": { "build:analyze": "ANALYZE=true turbo run build" }Also applies to: 21-21
23-40: manualChunks의 경로 매칭 로직을 더 견고하게 개선할 수 있습니다.현재 구현은 작동하지만, 문자열 포함 검사는 오탐 가능성이 있습니다.
더 정확한 패키지 매칭을 위해 다음과 같이 개선할 수 있습니다:
manualChunks: (id: string) => { - if ( - id.includes('node_modules/react/') || - id.includes('node_modules/react-dom/') || - id.includes('node_modules/react-router-dom/') - ) { + if (id.includes('node_modules')) { + if (/[\\/]node_modules[\\/](react|react-dom|react-router-dom)[\\/]/.test(id)) { - return '@react-vendor'; + return '@react-vendor'; + } + if (/[\\/]node_modules[\\/]framer-motion[\\/]/.test(id)) { + return '@framer-motion-vendor'; + } } - if (id.includes('node_modules/framer-motion/')) { - return '@framer-motion-vendor'; - } },이렇게 하면 경로 구분자를 정확히 매칭하여 오탐을 방지할 수 있습니다.
apps/client/src/layout/Layout.tsx (1)
3-3: Suspense fallback UI를 개선하는 것을 고려하세요.Suspense 래퍼 구현은 올바르며 lazy-loaded 라우트와 잘 통합됩니다. 다만 현재 fallback이 너무 단순하여 프로덕션 환경에서는 UX 개선이 필요합니다.
더 나은 사용자 경험을 위해 적절한 로딩 컴포넌트를 사용하는 것을 권장합니다:
+import LoadingSpinner from '@components/LoadingSpinner'; // 또는 적절한 로딩 컴포넌트 const Layout = () => { const location = useLocation(); const isOnboarding = location.pathname.startsWith('/onboarding'); return ( <> <div className="flex h-screen"> {!isOnboarding && <Sidebar />} <main className="bg-gray-bg flex-1 overflow-y-auto"> - <Suspense fallback={<div>Loading...</div>}> + <Suspense fallback={ + <div className="flex h-full items-center justify-center"> + <LoadingSpinner /> + </div> + }> <Outlet /> </Suspense> </main> </div> </> ); };또는 디자인 시스템에 이미 로딩 컴포넌트가 있다면 그것을 활용할 수 있습니다.
Also applies to: 14-16
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (4)
apps/client/src/layout/Layout.tsx(2 hunks)apps/client/src/routes/router.tsx(1 hunks)apps/client/vite.config.ts(2 hunks)package.json(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 2
File: pnpm-workspace.yaml:3-3
Timestamp: 2025-08-18T13:48:59.065Z
Learning: constantly-dev는 docs 디렉터리를 컨벤션 문서 추가용으로 사용할 예정이라고 명시했습니다.
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 5
File: apps/extension/src/index.css:1-1
Timestamp: 2025-08-19T17:18:57.678Z
Learning: constantly-dev는 디자인 시스템 설정 PR 머지 후 `import 'pinback/tailwind-config/shared-styles.css';`를 `app.css`나 `index.css`에서 사용하여 공유 스타일을 관리할 계획입니다.
🧬 Code graph analysis (2)
apps/client/src/routes/router.tsx (1)
apps/client/src/pages/level/Level.tsx (1)
Level(12-73)
apps/client/src/layout/Layout.tsx (1)
apps/client/src/shared/components/sidebar/Sidebar.tsx (1)
Sidebar(24-236)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: storybook
🔇 Additional comments (3)
package.json (1)
29-29: LGTM!번들 분석을 위한 visualizer 플러그인 추가가 적절합니다. devDependencies에 올바르게 배치되었습니다.
apps/client/src/routes/router.tsx (2)
5-10: LGTM!React.lazy를 사용한 코드 스플리팅 구현이 올바르게 되어 있습니다. 번들 최적화에 효과적입니다.
1-1: Remind 컴포넌트의 eager 로딩이 의도적인지 확인하세요.다른 페이지는 모두 lazy 로딩을 사용하는 반면, Remind는 eager 로딩을 사용하고 있습니다. 이는 랜딩 페이지로서 즉시 로드되어야 하므로 합리적일 수 있지만, 번들 최적화 목표와 일관성을 위해 의도적인 선택인지 확인이 필요합니다.
만약 Remind도 lazy 로딩하려면 다음과 같이 수정할 수 있습니다:
-import Remind from '@pages/remind/Remind'; import { ROUTES_CONFIG } from '@routes/routesConfig'; import { createBrowserRouter } from 'react-router-dom'; import Layout from 'src/layout/Layout'; import { lazy } from 'react'; +const Remind = lazy(() => import('@pages/remind/Remind')); const MyBookmark = lazy(() => import('@pages/myBookmark/MyBookmark')); const Category = lazy(() => import('@pages/category/Category')); const Level = lazy(() => import('@pages/level/Level')); const OnBoarding = lazy(() => import('@pages/onBoarding/OnBoarding'));참고:
index: true로의 변경은 React Router v7의 올바른 패턴입니다.Also applies to: 18-19
| if ( | ||
| id.includes('node_modules/react/') || | ||
| id.includes('node_modules/react-dom/') || | ||
| id.includes('node_modules/react-router-dom/') | ||
| ) { | ||
| return '@react-vendor'; |
There was a problem hiding this comment.
옹 이런식으로, 무거운 청크들을 분리하고 최적화하는군녀~! 굿굿
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)
apps/client/src/routes/router.tsx (1)
1-12: 🛠️ Refactor suggestion | 🟠 Major번들 최적화 목표 대비 정적 import —
React.lazy()적용 필요PR 목표("동적 로딩으로 초기 로드 개선")를 달성하려면 라우트 컴포넌트를
React.lazy()+ 동적import()로 전환해야 합니다.vite.config.ts의manualChunks설정은 정적으로 import된 모듈을 청크로 묶을 뿐, 라우트별 코드 스플리팅을 생성하지 않습니다. 현재 구조에서는 첫 번째 페이지 진입 시 모든 페이지 코드가 함께 번들에 포함됩니다.♻️ 라우트별 코드 스플리팅 적용 예시
-import Category from '@pages/category/Category'; -import Level from '@pages/level/Level'; -import Login from '@pages/login/Login'; -import MyBookmark from '@pages/myBookmark/MyBookmark'; -import GoogleCallback from '@pages/onBoarding/GoogleCallback'; -import OnBoarding from '@pages/onBoarding/OnBoarding'; -import PrivacyPolicy from '@pages/policy/PrivacyPolicy'; -import TermsOfService from '@pages/policy/TermsOfService'; -import Remind from '@pages/remind/Remind'; +import { lazy } from 'react'; + +const Category = lazy(() => import('@pages/category/Category')); +const Level = lazy(() => import('@pages/level/Level')); +const Login = lazy(() => import('@pages/login/Login')); +const MyBookmark = lazy(() => import('@pages/myBookmark/MyBookmark')); +const GoogleCallback = lazy(() => import('@pages/onBoarding/GoogleCallback')); +const OnBoarding = lazy(() => import('@pages/onBoarding/OnBoarding')); +const PrivacyPolicy = lazy(() => import('@pages/policy/PrivacyPolicy')); +const TermsOfService = lazy(() => import('@pages/policy/TermsOfService')); +const Remind = lazy(() => import('@pages/remind/Remind'));그리고 최상위에서
Suspense로 감싸야 합니다. PR에서 추가된 로딩 인디케이터를Layout또는RouterProvider레벨의fallback으로 활용할 수 있습니다:import { ROUTES_CONFIG } from '@routes/routesConfig'; -import { createBrowserRouter } from 'react-router-dom'; +import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { Suspense } from 'react'; +import LoadingIndicator from 'src/components/LoadingIndicator'; // 실제 경로로 교체
Layout컴포넌트 내부 또는 각 라우트의element를<Suspense fallback={<LoadingIndicator />}>로 감쌉니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/client/src/routes/router.tsx` around lines 1 - 12, The router currently statically imports page components (Category, Level, Login, MyBookmark, GoogleCallback, OnBoarding, PrivacyPolicy, TermsOfService, Remind) so all pages are bundled up front; change each static import in router.tsx to lazy-loaded components using React.lazy(() => import('...')) for each of those symbols and update the route entries (where ROUTES_CONFIG is used) to reference the lazy components, then ensure you wrap the router render (either in Layout or at RouterProvider level) with React.Suspense and pass the existing LoadingIndicator (or Layout fallback) as the fallback so route components load dynamically and enable per-route code splitting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@apps/client/src/routes/router.tsx`:
- Around line 1-12: The router currently statically imports page components
(Category, Level, Login, MyBookmark, GoogleCallback, OnBoarding, PrivacyPolicy,
TermsOfService, Remind) so all pages are bundled up front; change each static
import in router.tsx to lazy-loaded components using React.lazy(() =>
import('...')) for each of those symbols and update the route entries (where
ROUTES_CONFIG is used) to reference the lazy components, then ensure you wrap
the router render (either in Layout or at RouterProvider level) with
React.Suspense and pass the existing LoadingIndicator (or Layout fallback) as
the fallback so route components load dynamically and enable per-route code
splitting.
📌 Related Issues
📄 Tasks
번들 사이즈 최적화 진행
⭐ PR Point (To Reviewer)
https://peppered-parade-9ba.notion.site/2a9081ae8cf980698826d0264b44eb32?source=copy_link
노션으로 대체하겠습니다!
Summary by CodeRabbit
릴리스 노트
새로운 기능
최적화
Chores
Summary by CodeRabbit
릴리스 노트
최적화
기타