Skip to content

๐Ÿš€ ์›น ์•ฑ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ์ตœ์ ํ™” (198kB โ†’ 160kB)#416

Open
manNomi wants to merge 10 commits intomainfrom
optimize/bundle-size
Open

๐Ÿš€ ์›น ์•ฑ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ์ตœ์ ํ™” (198kB โ†’ 160kB)#416
manNomi wants to merge 10 commits intomainfrom
optimize/bundle-size

Conversation

@manNomi
Copy link
Contributor

@manNomi manNomi commented Feb 8, 2026

Summary

์›น ์•ฑ์˜ First Load JS shared by all์„ 198 kB โ†’ 160 kB (-38 kB, -19.2%)๋กœ ๊ฐ์†Œ์‹œํ‚ต๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ ์‚ฌํ•ญ

1. Sentry transpileClientSDK ๋น„ํ™œ์„ฑํ™”

  • IE11 ํ˜ธํ™˜์„ ์œ„ํ•œ SDK ํŠธ๋žœ์ŠคํŒŒ์ผ์„ ์ œ๊ฑฐํ•˜์—ฌ ๋ฒˆ๋“ค ํฌ๊ธฐ ๊ฐ์†Œ
  • ํ˜„๋Œ€ ๋ธŒ๋ผ์šฐ์ €๋งŒ ์ง€์›ํ•˜๋ฏ€๋กœ IE11 ํ˜ธํ™˜ ๋ถˆํ•„์š”

2. Sentry replayIntegration lazy load

  • Session Replay SDK (~30-40kB)๋ฅผ ์ดˆ๊ธฐ ๋ฒˆ๋“ค์—์„œ ์ œ์™ธ
  • lazyLoadIntegration์œผ๋กœ ๋น„๋™๊ธฐ ๋กœ๋”ฉํ•˜์—ฌ ์ดˆ๊ธฐ ๋กœ๋”ฉ ์„ฑ๋Šฅ ๊ฐœ์„ 
  • Replay ๊ธฐ๋Šฅ์€ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ (๋กœ๋”ฉ ์‹œ์ ๋งŒ ์ง€์—ฐ)

3. @next/bundle-analyzer ์ถ”๊ฐ€

  • ๋ฒˆ๋“ค ๋ถ„์„ ๋„๊ตฌ ์„ค์น˜ (ANALYZE=true pnpm --filter @solid-connect/web run analyze)
  • ํ–ฅํ›„ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ๋ชจ๋‹ˆํ„ฐ๋ง ๊ฐ€๋Šฅ

4. optimizePackageImports ์„ค์ •

  • lucide-react, @radix-ui/*, zod, react-hook-form ๋“ฑ tree-shaking ์ตœ์ ํ™”
  • ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ชจ๋“ˆ์ด ๋ฒˆ๋“ค์— ํฌํ•จ๋˜์ง€ ์•Š๋„๋ก ์„ค์ •

5. score/search ํŽ˜์ด์ง€ dynamic import

  • ScoreScreen, SearchBar, SchoolSearchForm ์ปดํฌ๋„ŒํŠธ๋ฅผ next/dynamic์œผ๋กœ ๋ณ€๊ฒฝ
  • ํ•ด๋‹น ํŽ˜์ด์ง€ ์ง„์ž… ์‹œ์—๋งŒ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ๋กœ๋”ฉ

๋นŒ๋“œ ๊ฒฐ๊ณผ ๋น„๊ต

ํ•ญ๋ชฉ Before After ๋ณ€ํ™”
First Load JS shared 198 kB 160 kB -38 kB (-19.2%)
/university/score 250 kB 212 kB -38 kB
/university/score/submit/gpa 321 kB 284 kB -37 kB
/university/score/submit/language-test 322 kB 285 kB -37 kB
/university/search 285 kB 248 kB -37 kB
Shared chunk count 4 3 -1 (d763957a ์ œ๊ฑฐ๋จ)

์ฐธ๊ณ 

  • useMutationWithFailure.ts์˜ ๊ธฐ์กด ํƒ€์ž… ์—๋Ÿฌ๊ฐ€ main์—๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค (์ด PR๊ณผ ๋ฌด๊ด€)

@vercel
Copy link

vercel bot commented Feb 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
solid-connect-web-admin Error Error Feb 8, 2026 5:30pm
solid-connection-web Ready Ready Preview, Comment Feb 8, 2026 5:30pm

@coderabbitai
Copy link

coderabbitai bot commented Feb 8, 2026

Walkthrough

  1. ํฌ๋งทํŒ… ๋ฐ ๋“ค์—ฌ์“ฐ๊ธฐ ์ •๊ทœํ™”๊ฐ€ ์—ฌ๋Ÿฌ ํŒŒ์ผ์—์„œ ์ ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  2. ๋‘ Score ํ…Œ์ด๋ธ”(GpaScoreTable, LanguageScoreTable)์— fetchScores๋ฅผ useCallback์œผ๋กœ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•˜๊ณ  useEffect ์˜์กด์„ฑ์„ ์•ˆ์ •ํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค.
  3. Button ๋ฐ Input ์ปดํฌ๋„ŒํŠธ์— ๋ช…์‹œ์  named export๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  4. ์ผ๋ถ€ ํŽ˜์ด์ง€ ์ปดํฌ๋„ŒํŠธ๋ฅผ next/dynamic์œผ๋กœ ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ๋™์  ๋กœ๋“œํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.
  5. Next.js์— ๋ฒˆ๋“ค ๋ถ„์„๊ธฐ(@next/bundle-analyzer)์™€ optimizePackageImports ์„ค์ •์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.
  6. Sentry ๋ฆฌํ”Œ๋ ˆ์ด ํ†ตํ•ฉ์„ ๋Ÿฐํƒ€์ž„ lazy-load ๋ฐฉ์‹์œผ๋กœ ์ „ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.
  7. useMutationWithFailure.ts ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•ด React Query์˜ useMutation์„ onFailure๋ฅผ ์ง€์›ํ•˜๋„๋ก ํ™•์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.
  8. .npmrc์™€ CI์šฉ tsconfig.ci.json ๋“ฑ ๊ตฌ์„ฑ ํŒŒ์ผ์ด ์ถ”๊ฐ€ยท์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Estimated code review effort

๐ŸŽฏ 3 (Moderate) | โฑ๏ธ ~35 minutes

Suggested reviewers

  • wibaek
  • enunsnv
  • khwww
๐Ÿšฅ Pre-merge checks | โœ… 2 | โŒ 1
โŒ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage โš ๏ธ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
โœ… Passed checks (2 passed)
Check name Status Explanation
Title check โœ… Passed PR ์ œ๋ชฉ์ด ์›น ์•ฑ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ์ตœ์ ํ™”์˜ ํ•ต์‹ฌ ๋ณ€ํ™”(198kB โ†’ 160kB)๋ฅผ ๋ช…ํ™•ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๋ฉฐ, ์‹ค์ œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์˜ ์ฃผ์š” ๋ชฉํ‘œ๋ฅผ ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
Description check โœ… Passed PR ์„ค๋ช…์ด ์ •ํ•ด์ง„ ํ…œํ”Œ๋ฆฟ(๊ด€๋ จ ์ด์Šˆ, ์ž‘์—… ๋‚ด์šฉ, ํŠน์ด ์‚ฌํ•ญ, ๋ฆฌ๋ทฐ ์š”๊ตฌ์‚ฌํ•ญ)์„ ์™„๋ฒฝํ•˜๊ฒŒ ๋”ฐ๋ฅด์ง€๋Š” ์•Š์œผ๋‚˜, Summary, ๋ณ€๊ฒฝ ์‚ฌํ•ญ, ๋นŒ๋“œ ๊ฒฐ๊ณผ ๋น„๊ต ๋“ฑ์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ๋งค์šฐ ์ƒ์„ธํ•˜๊ณ  ๋ช…ํ™•ํ•ฉ๋‹ˆ๋‹ค.

โœ๏ธ Tip: You can configure your own custom pre-merge checks in the settings.

โœจ Finishing touches
๐Ÿงช Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch optimize/bundle-size

No actionable comments were generated in the recent review. ๐ŸŽ‰


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.

โค๏ธ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

๐Ÿค– Fix all issues with AI agents
In `@apps/admin/src/components/features/scores/GpaScoreTable.tsx`:
- Around line 214-223: Fix the inconsistent indentation in the pagination block
inside GpaScoreTable: align the Array.from({ length: totalPages }, ...)
expression to the same indentation level as the surrounding <Button> siblings
and make the props on the Button (key, onClick, variant) vertically aligned
(ensure onClick is at the same indent level as key and variant). Locate the
pagination map using Array.from and the Button elements that call
handlePageChange(idx + 1) and reference page to set the variant, then reformat
those lines so indentation is consistent and symmetric.

In `@apps/admin/src/components/features/scores/LanguageScoreTable.tsx`:
- Around line 236-245: Fix the indentation in LanguageScoreTable's pagination
block to match GpaScoreTable: align the {Array.from({ length: totalPages }, (_,
idx) => ( ... ))} block with the surrounding <Button> container and ensure the
attributes inside each Button (key={idx + 1}, onClick={() =>
handlePageChange(idx + 1)}, variant={page === idx + 1 ? "default" :
"secondary"}) have consistent indentation levels (make onClick aligned with key
and variant). Locate the pagination code in LanguageScoreTable (references:
totalPages, page, handlePageChange) and reformat it so its JSX indentation
mirrors the GpaScoreTable pagination section.

In `@apps/admin/src/routes/auth/login.tsx`:
- Around line 56-86: The JSX indentation inside the login form is inconsistent:
ensure each <div className="space-y-1"> is indented as a child of the
surrounding <form>, align all props of the Input components (id, type,
placeholder, value, onChange, disabled, required, className) at the same
indentation level, and align the closing `/>` for each <Input> and the closing
`</div>` tags to match their opening tags; after fixing the whitespace, run
"biome format --write" to normalize formatting across the <Label>, <Input>, and
surrounding form markup (refer to the Input and Label usage in this login
component).

In `@apps/web/next.config.mjs`:
- Around line 97-98: Remove the unsupported transpileClientSDK option from
next.config.mjs (delete the transpileClientSDK: false line and its IE11-related
comment); reference the `@sentry/nextjs` change (v8+ removed this option) and, if
IE11/older-browser support is required, instruct to implement explicit
transpilation and polyfills via Next.js webpack/babel config instead of using
transpileClientSDK.

In `@apps/web/package.json`:
- Line 50: The dependency `@next/bundle-analyzer` in apps/web package.json is
pinned to ^16.1.6 which mismatches the project's Next.js version (^14.2.35);
update the "@next/bundle-analyzer" entry to a 14.x compatible version (e.g.
^14.0.0 or the specific v14.x that matches Next 14) so the `@next/`* major
versions align, then reinstall deps (npm/yarn/pnpm install) and run the
app/build to verify compatibility; locate the "@next/bundle-analyzer" entry in
package.json to make this change.
๐Ÿงน Nitpick comments (7)
apps/web/src/components/ui/FloatingUpBtn/hooks/useFloatingUpHandler.ts (1)

10-15: handleClick๋„ useCallback์œผ๋กœ ๊ฐ์‹ธ๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

handleScroll์€ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ–ˆ์ง€๋งŒ, handleClick์€ ๋งค ๋ Œ๋”๋งˆ๋‹ค ์ƒˆ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๊ฐ€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— prop์œผ๋กœ ์ „๋‹ฌ๋œ๋‹ค๋ฉด ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ํ˜„์žฌ ์‚ฌ์šฉ ํŒจํ„ด์—์„œ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด ๋ฌด์‹œํ•˜์…”๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

โ™ป๏ธ ์„ ํƒ์  ๊ฐœ์„ ์•ˆ
-  const handleClick = () => {
-    window.scrollTo({
-      top: 0,
-      behavior: "smooth",
-    });
-  };
+  const handleClick = useCallback(() => {
+    window.scrollTo({
+      top: 0,
+      behavior: "smooth",
+    });
+  }, []);
apps/web/src/app/university/score/page.tsx (1)

6-6: loading ํด๋ฐฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด UX๊ฐ€ ๋” ์ข‹์•„์งˆ ์ˆ˜ ์žˆ์–ด์š”.

ssr: false๋กœ ๋™์  ์ž„ํฌํŠธํ•˜๋ฉด JS ์ฒญํฌ๊ฐ€ ๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ํ•ด๋‹น ์˜์—ญ์ด ๋น„์–ด ๋ณด์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์Šค์ผˆ๋ ˆํ†ค์ด๋‚˜ ์Šคํ”ผ๋„ˆ๋ฅผ loading ์˜ต์…˜์— ๋„ฃ์–ด์ฃผ๋ฉด ์‚ฌ์šฉ์ž ์ฒด๊ฐ์ด ์ž์—ฐ์Šค๋Ÿฌ์›Œ์ง‘๋‹ˆ๋‹ค.

๐Ÿ’ก ์˜ˆ์‹œ
-const ScoreScreen = dynamic(() => import("./ScoreScreen"), { ssr: false });
+const ScoreScreen = dynamic(() => import("./ScoreScreen"), {
+  ssr: false,
+  loading: () => <div className="flex h-40 items-center justify-center">๋กœ๋”ฉ ์ค‘...</div>,
+});
apps/web/src/app/university/search/page.tsx (1)

6-7: ๋™์  ์ž„ํฌํŠธ์— loading ํด๋ฐฑ์ด ์—†์–ด์š”.

  1. SearchBar์™€ SchoolSearchForm ๋ชจ๋‘ ssr: false๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด์„œ, JS๊ฐ€ ๋กœ๋“œ๋˜๊ธฐ ์ „๊นŒ์ง€ ํ•ด๋‹น ์˜์—ญ์ด ๋น„์–ด ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. dynamic์˜ loading ์˜ต์…˜์œผ๋กœ ๊ฐ„๋‹จํ•œ ์Šค์ผˆ๋ ˆํ†ค์ด๋‚˜ ์Šคํ”ผ๋„ˆ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ์‚ฌ์šฉ์ž ์ฒด๊ฐ ๋กœ๋”ฉ ์†๋„๊ฐ€ ๊ฐœ์„ ๋ฉ๋‹ˆ๋‹ค.
next/dynamic loading option usage
๐Ÿ’ก ์˜ˆ์‹œ
-const SearchBar = dynamic(() => import("./SearchBar"), { ssr: false });
-const SchoolSearchForm = dynamic(() => import("./PageContent"), { ssr: false });
+const SearchBar = dynamic(() => import("./SearchBar"), {
+  ssr: false,
+  loading: () => <div className="h-10 animate-pulse rounded-lg bg-gray-100" />,
+});
+const SchoolSearchForm = dynamic(() => import("./PageContent"), {
+  ssr: false,
+  loading: () => <div className="h-40 animate-pulse rounded-lg bg-gray-100" />,
+});
apps/admin/src/lib/api/scores.ts (1)

30-44: ์–ดํ•™ ์„ฑ์  ์กฐํšŒ ๋ฐ ์ˆ˜์ • API ๋กœ์ง ํ™•์ธ ์™„๋ฃŒ

ํฌ๋งทํŒ… ์ •๋ฆฌ๊ฐ€ ์ž˜ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ํ–ฅํ›„ ํƒ€์ž… ์•ˆ์ „์„ฑ ๊ฐœ์„ ์„ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Line 38์˜ as LanguageTestType ํƒ€์ž… ๋‹จ์–ธ์€ ์„œ๋ฒ„์—์„œ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฐ’์ด ์˜ฌ ๊ฒฝ์šฐ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•„์š”์‹œ ํƒ€์ž… ๊ฐ€๋“œ๋ฅผ ํ†ตํ•œ ๊ฒ€์ฆ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”.

apps/web/src/lib/react-query/useMutationWithFailure.ts (2)

77-99: mutate/mutateAsync๊ฐ€ ๋งค ๋ Œ๋”๋งˆ๋‹ค ์ƒˆ ์ฐธ์กฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  1. mutate์™€ mutateAsync๊ฐ€ useCallback ์—†์ด ๋งค ๋ Œ๋”์‹œ ์žฌ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  2. React Query ์ž์ฒด์˜ mutation.mutate๋„ ์•ˆ์ •์  ์ฐธ์กฐ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์‹ค์งˆ์  ๋ฌธ์ œ๋Š” ์•„๋‹ˆ์ง€๋งŒ, ์ด ํ•จ์ˆ˜๋“ค์„ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์˜ prop์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ํ˜„์žฌ ๊ทœ๋ชจ์—์„œ๋Š” ํฐ ์˜ํ–ฅ์ด ์—†์œผ๋ฏ€๋กœ, ํ•„์š”ํ•ด์ง€๋ฉด useCallback์œผ๋กœ ๊ฐ์‹ธ๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด ์ฃผ์„ธ์š”.

43-62: normalizeMutationOptions / normalizeMutateOptions โ€” ํƒ€์ž… ์บ์ŠคํŒ…์— ๋Œ€ํ•œ ๋ฉ”๋ชจ.

  1. Line 49, 60์—์„œ as ์บ์ŠคํŒ…์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ด๋Š” mergeOnError๊ฐ€ TData๋ฅผ unknown์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  2. ์•ˆ์ „์„ฑ ์ธก๋ฉด์—์„œ ๋ฌธ์ œ๋Š” ์—†์ง€๋งŒ, mergeOnError์˜ ์ œ๋„ค๋ฆญ์— TData๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์บ์ŠคํŒ… ์—†์ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โ™ป๏ธ ์บ์ŠคํŒ… ์ œ๊ฑฐ๋ฅผ ์œ„ํ•œ ์ œ์•ˆ
-const mergeOnError = <TError, TVariables, TContext>(
-  onError?: UseMutationOptions<unknown, TError, TVariables, TContext>["onError"],
+const mergeOnError = <TData, TError, TVariables, TContext>(
+  onError?: UseMutationOptions<TData, TError, TVariables, TContext>["onError"],
   onFailure?: (error: TError, variables: TVariables, context: TContext | undefined) => void,
-): UseMutationOptions<unknown, TError, TVariables, TContext>["onError"] => {
+): UseMutationOptions<TData, TError, TVariables, TContext>["onError"] => {
   if (!onError && !onFailure) return undefined;
-  return (...args: Parameters<NonNullable<UseMutationOptions<unknown, TError, TVariables, TContext>["onError"]>>) => {
+  return (...args: Parameters<NonNullable<UseMutationOptions<TData, TError, TVariables, TContext>["onError"]>>) => {
     onError?.(...args);
     onFailure?.(args[0], args[1], args[2]);
   };
 };

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด normalizeMutationOptions์™€ normalizeMutateOptions ๋‚ด๋ถ€์˜ as ์บ์ŠคํŒ…์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

apps/web/sentry.client.config.ts (1)

35-44: lazyLoadIntegration Promise์— ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋„คํŠธ์›Œํฌ ์‹คํŒจ ๋“ฑ์œผ๋กœ lazy load๊ฐ€ ์‹คํŒจํ•  ๊ฒฝ์šฐ unhandled promise rejection์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด์š”. Session Replay๋Š” ๋น„ํ•„์ˆ˜ ๊ธฐ๋Šฅ์ด๋‹ˆ ์กฐ์šฉํžˆ ์‹คํŒจํ•ด๋„ ๊ดœ์ฐฎ์ง€๋งŒ, ๋ช…์‹œ์ ์œผ๋กœ .catch()๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ›ก๏ธ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€ ์ œ์•ˆ
   Sentry.lazyLoadIntegration("replayIntegration").then((replay) => {
     Sentry.addIntegration(
       replay({
         maskAllText: true,
         blockAllMedia: true,
       }),
     );
-  });
+  }).catch(() => {
+    // Session Replay lazy load ์‹คํŒจ ์‹œ ๋ฌด์‹œ (๋น„ํ•„์ˆ˜ ๊ธฐ๋Šฅ)
+  });

Comment on lines +97 to +98
// IE11 ์ง€์› ๋ถˆํ•„์š” - ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ๋น„ํ™œ์„ฑํ™”
transpileClientSDK: false,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

๐Ÿงฉ Analysis chain

๐ŸŒ Web query:

@sentry/nextjs v10 transpileClientSDK option documentation

๐Ÿ’ก Result:

transpileClientSDK is not available in @sentry/nextjs v10 (or any v8+). It was removed in @sentry/nextjs 8.0.0 when Sentry dropped support for IE11/older browsers; the release notes explicitly say the option was removed and that you must down-compile the SDK yourself via your Next.js/Webpack setup if you still need that compatibility. [1]

Historically (pre-v8), transpileClientSDK: true told the Next.js SDKโ€™s Webpack config to transpile Sentryโ€™s client bundle to match your appโ€™s transpilation level (to support older browsers). [2]

If your goal is โ€œsupport older browsers,โ€ note that current Sentry JavaScript SDKs target modern syntax (ES2020) and Sentryโ€™s docs recommend transpiling + polyfills on your side if you need earlier browser versions. [3]

Sources: [1] [2] [3]


๐ŸŒ Web query:

Sentry SDK transpileClientSDK option removed deprecated v8 v9 v10

๐Ÿ’ก Result:

  • transpileClientSDK was added to the Sentry Next.js SDK in the v7 line (to force Webpack to transpile Sentryโ€™s client bundle for older browsers like IE11). (newreleases.io)
  • It was removed in @sentry/nextjs 8.0.0 (Sentry JS SDK v8) because v8 dropped support for IE11 / older browsers, so the SDK no longer provides this built-in transpilation switch. (newreleases.io)
  • Therefore, the option is not available in v8, v9, or v10 of @sentry/nextjs. If you still need older-browser support, you must configure Next.js/Webpack to down-compile/transpile the Sentry packages yourself. (newreleases.io)

Citations:


๐ŸŒ Web query:

@sentry/nextjs changelog transpileClientSDK

๐Ÿ’ก Result:

transpileClientSDK was added to @sentry/nextjs in sentry-javascript v7.8.0 (โ€œfix(nextjs): Add transpileClientSDK optionโ€, PR #5472) as a Next.js Webpack config flag. It makes Next/Webpack transpile the Sentry client SDK code using the same transpilation rules as your app, which helps when targeting older browsers (e.g., missing ES6/ES6+ features like object spread). [1]

In the @sentry/nextjs type definitions (v7.x), itโ€™s documented as:

  • transpileClientSDK?: boolean; โ€” โ€œapply the same transpilation rules to the SDK code as apply to user codeโ€ฆโ€ [2]

Sources: [1] [2]


transpileClientSDK ์˜ต์…˜์€ @sentry/nextjs v10์—์„œ ์ง€์›๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ œ๊ฑฐ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค:

  1. ์˜ต์…˜ ์ œ๊ฑฐ
    @sentry/nextjs 8.0.0๋ถ€ํ„ฐ transpileClientSDK ์˜ต์…˜์ด ์™„์ „ํžˆ ์ œ๊ฑฐ๋˜์—ˆ์œผ๋ฏ€๋กœ, ์ด ๋ผ์ธ์€ ์‚ญ์ œํ•˜์„ธ์š”. ํ˜„์žฌ ์„ค์ •์€ v10์—์„œ ์ธ์‹๋˜์ง€ ์•Š์•„ ์ž๋™์œผ๋กœ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.

  2. IE11 ์ง€์› ์žฌํ‰๊ฐ€
    Sentry JavaScript SDK v8+ ์ดํ›„ IE11 ์ง€์›์ด ๊ณต์‹์ ์œผ๋กœ ์ค‘๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ด์ „ ๋ธŒ๋ผ์šฐ์ € ์ง€์›์ด ํ•„์ˆ˜๋ผ๋ฉด, Next.js์˜ webpack ์„ค์ •์„ ํ†ตํ•ด ์ง์ ‘ transpilation + polyfill์„ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ์ฃผ์„์˜ ์˜๋„(๋ฒˆ๋“ค ์ตœ์ ํ™”)๋ผ๋ฉด ์ฃผ์„๋„ ํ•จ๊ป˜ ์ œ๊ฑฐํ•˜์„ธ์š”.

๐Ÿค– Prompt for AI Agents
In `@apps/web/next.config.mjs` around lines 97 - 98, Remove the unsupported
transpileClientSDK option from next.config.mjs (delete the transpileClientSDK:
false line and its IE11-related comment); reference the `@sentry/nextjs` change
(v8+ removed this option) and, if IE11/older-browser support is required,
instruct to implement explicit transpilation and polyfills via Next.js
webpack/babel config instead of using transpileClientSDK.

"zustand": "^5.0.7"
},
"devDependencies": {
"@next/bundle-analyzer": "^16.1.6",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

โš ๏ธ Potential issue | ๐ŸŸ  Major

๐Ÿงฉ Analysis chain

๐Ÿ Script executed:

cat apps/web/package.json | grep -A 100 '"dependencies"' | head -30

Repository: solid-connection/solid-connect-web

Length of output: 1085


๐Ÿ Script executed:

cat apps/web/package.json | grep -E '"next"|"@next/bundle-analyzer"'

Repository: solid-connection/solid-connect-web

Length of output: 141


๐ŸŒ Web query:

@next/bundle-analyzer Next.js 14 compatibility requirements version

๐Ÿ’ก Result:

For Next.js 14, use @next/bundle-analyzer v14.x (same major as Next). In practice, keep it in lockstep with your next version (e.g., next@14.2.30 โ†’ @next/bundle-analyzer@14.2.30). The npm registry shows published 14.x releases (e.g., 14.2.30) for @next/bundle-analyzer. [1]

Requirements to run it with Next 14:

  • Next.js 14 requires Node.js >= 18.17. [2]
  • Itโ€™s a Webpack-based analyzer; if you run next dev --turbo (Turbopack), you may see warnings because Webpack config/plugins (like bundle analyzer) arenโ€™t supported the same way. [3]

Install example (pin to your Next 14 version):

npm i -D `@next/bundle-analyzer`@14.2.30

Sources: [1] [2] [3]


@next/bundle-analyzer ๋ฒ„์ „์ด Next.js ๋ฉ”์ด์ € ๋ฒ„์ „๊ณผ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„œ next๋Š” ^14.2.35์ด์ง€๋งŒ, @next/bundle-analyzer๋Š” ^16.1.6์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด์š”. @next/* ํŒจํ‚ค์ง€๋“ค์€ Next.js์˜ ๋ฉ”์ด์ € ๋ฒ„์ „๊ณผ ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•ด์•ผ ํ˜ธํ™˜์„ฑ์ด ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค. ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋„ Next.js 14์—๋Š” @next/bundle-analyzer v14.x๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ถŒ์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •์„ ์ œ์•ˆ๋“œ๋ฆฝ๋‹ˆ๋‹ค:

  1. @next/bundle-analyzer ๋ฒ„์ „์„ Next.js 14๊ณผ ๋งž์ถฐ์„œ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ธฐ
๐Ÿ”ง ๋ฒ„์ „ ์ˆ˜์ • ๋ฐฉ์•ˆ
-    "@next/bundle-analyzer": "^16.1.6",
+    "@next/bundle-analyzer": "^14.2.35",
๐Ÿ“ 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.

Suggested change
"@next/bundle-analyzer": "^16.1.6",
"@next/bundle-analyzer": "^14.2.35",
๐Ÿค– Prompt for AI Agents
In `@apps/web/package.json` at line 50, The dependency `@next/bundle-analyzer` in
apps/web package.json is pinned to ^16.1.6 which mismatches the project's
Next.js version (^14.2.35); update the "@next/bundle-analyzer" entry to a 14.x
compatible version (e.g. ^14.0.0 or the specific v14.x that matches Next 14) so
the `@next/`* major versions align, then reinstall deps (npm/yarn/pnpm install)
and run the app/build to verify compatibility; locate the
"@next/bundle-analyzer" entry in package.json to make this change.

manNomi and others added 2 commits February 9, 2026 02:16
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

๐Ÿค– Fix all issues with AI agents
In @.npmrc:
- Around line 3-5: The .npmrc contains conflicting hoisting settings: remove the
redundant public-hoist-pattern[]='*' entries (and the negations '!@types/react'
/ '!@types/react-dom' which are ineffective when shamefully-hoist=true) or else
remove shamefully-hoist=true so public-hoist-patterns take effect; then move
bundle-size optimizations into Next.js config by adjusting next.config.js (use
transpilePackages and optimizePackageImports) rather than relying on broad pnpm
hoisting.

.npmrc Outdated
Comment on lines 3 to 5
public-hoist-pattern[]='*'
public-hoist-pattern[]='!@types/react'
public-hoist-pattern[]='!@types/react-dom'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

โš ๏ธ Potential issue | ๐ŸŸ  Major

๐Ÿงฉ Analysis chain

๐ŸŒ Web query:

pnpm public-hoist-pattern shamefully-hoist interaction configuration

๐Ÿ’ก Result:

shamefully-hoist and public-hoist-pattern both control public hoisting (putting selected packages into the root node_modules so โ€œphantomโ€ deps become resolvable by app/tooling).

Interaction / precedence

  • shamefully-hoist=true is effectively the same as public-hoist-pattern[]=* (public-hoist everything). It also overrides any public-hoist-pattern you set. [1][2]
  • shamefully-hoist=false means pnpm uses public-hoist-pattern normally (only patterns you specify are publicly hoisted). [2]

Recommended configuration approach

Prefer targeted public hoisting via public-hoist-pattern (only for broken tooling that expects flat/root deps), instead of shamefully-hoist=true. [1]

Example .npmrc

# Targeted public hoisting (recommended)
public-hoist-pattern[]=*plugin*
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*

pnpm also supports excluding matches with ! (so you can broadly hoist, then carve out exceptions). [1][3]

public-hoist-pattern[]=*types*
public-hoist-pattern[]=!@types/react

โ€œHoist everythingโ€ (legacy/last resort)

shamefully-hoist=true
# equivalent to: public-hoist-pattern[]=*

[1]

Rule of thumb: if you set shamefully-hoist=true, donโ€™t bother setting public-hoist-patternโ€”it will be treated as * anyway. [1][2]

Sources: pnpm .npmrc settings docs (public-hoist-pattern + shamefully-hoist) [1], pnpm 5.2.0 release notes describing override behavior [2], pnpm .npmrc docs noting exclusion patterns with ! [3].


๐ŸŒ Web query:

pnpm monorepo hoisting best practices Next.js bundle optimization

๐Ÿ’ก Result:

pnpm monorepo hoisting: best practices (so you donโ€™t break Next.js or hide missing deps)

  1. Prefer pnpmโ€™s default โ€œisolatedโ€ linker (node-linker=isolated) to keep dependency boundaries correct and avoid โ€œphantom dependencyโ€ bugs (packages importing deps they didnโ€™t declare). Only switch to node-linker=hoisted if you must support tooling/filesystems that canโ€™t handle symlinks. [1]
  2. Avoid blanket โ€œpublicโ€ hoisting (publicHoistPattern=['*'] / shamefullyHoist=true) unless youโ€™re working around a specific broken tool, because it intentionally makes phantom deps available to app code. [2]
  3. If you need hoisting, make it targeted:
    • Use hoistPattern to hoist only the problematic toolchain deps (recommended by pnpm) instead of everything. [2]
    • Use publicHoistPattern sparingly for tools that incorrectly resolve plugins/deps and require root-level visibility. [2]

Typical .npmrc / pnpm config approach

# default / recommended
node-linker=isolated

# if some tool breaks, prefer targeted hoisting (examples)
# hoist-pattern[]=*eslint*
# hoist-pattern[]=*babel*
# public-hoist-pattern[]=*plugin*

(Exact config file can be .npmrc or workspace config depending on how you manage pnpm settings; the knobs are nodeLinker, hoistPattern, publicHoistPattern.) [1][2]


Next.js in a pnpm monorepo: bundle optimization checklist

  1. Bundle/transpile your internal workspace packages (the usual monorepo fix) using transpilePackages so Next can compile code coming from workspace packages / node_modules. [3][4]
// next.config.js
module.exports = {
  transpilePackages: ['@acme/ui', '@acme/shared'],
}
  1. Measure first with the official bundle analyzer so you can see whatโ€™s actually inflating the client/server bundles. [5]
ANALYZE=true pnpm build
  1. Fix โ€œbarrel exportโ€ bloat with experimental.optimizePackageImports (or rely on defaults for popular libs). This can reduce work during builds and avoid pulling in huge module graphs for big โ€œnamed exportโ€ packages. [5][6][7]
module.exports = {
  experimental: {
    optimizePackageImports: ['some-big-barrel-lib'],
  },
}
  1. Keep server-only deps out of bundling when appropriate using serverExternalPackages (useful for native/binary deps or packages that shouldnโ€™t be bundled). [5]

How this ties together (pnpm hoisting โ†” Next bundling)

  • Donโ€™t use broad hoisting to โ€œmake Next find things.โ€ If Next canโ€™t compile/import a workspace package cleanly, the right fix is usually transpilePackages (and proper dependency declarations), not making everything visible via public hoisting. [3][4][2]
  • Use hoisting only as a compatibility escape hatch, and keep it pattern-based. [2][1]

Sources: pnpm settings for nodeLinker/hoisting knobs [1][2]; Next.js docs for bundle analyzer, transpilePackages, and optimizePackageImports [5][3][4][6]; Vercel guidance on optimizePackageImports and barrel-export impact [7].


๊ณต์กดํ•  ์ˆ˜ ์—†๋Š” ์„ค์ •: ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๊ณ  ๋ฒˆ๋“ค ์ตœ์ ํ™” ๋ฐฉ์‹์„ ์žฌ๊ฒ€ํ† ํ•˜์„ธ์š”

ํ˜„์žฌ ์„ค์ •์— ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ์„ค์ • ์ค‘๋ณต์œผ๋กœ ์ธํ•œ ๋น„ํšจ์œจ

    • 2๋ฒˆ ๋ผ์ธ์˜ shamefully-hoist=true๊ฐ€ ์ด๋ฏธ ๋ชจ๋“  ์˜์กด์„ฑ์„ ๊ณต๊ฐœ ํ˜ธ์ด์ŠคํŒ…ํ•ฉ๋‹ˆ๋‹ค
    • 3~5๋ฒˆ ๋ผ์ธ์˜ public-hoist-pattern[]='*'๋Š” ์œ„ ์„ค์ •๊ณผ ์ •ํ™•ํžˆ ๋™์ผํ•œ ๋™์ž‘์„ ํ•˜๋ฏ€๋กœ ๋ถˆํ•„์š”ํ•ฉ๋‹ˆ๋‹ค
    • pnpm ๊ณต์‹ ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด, shamefully-hoist=true๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋‹ค๋ฅธ public-hoist-pattern ์„ค์ •์€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค
  2. ์˜๋„ํ•œ ํšจ๊ณผ๋ฅผ ๋‚ด์ง€ ๋ชปํ•  ๊ฐ€๋Šฅ์„ฑ

    • 4~5๋ฒˆ ๋ผ์ธ์˜ React ํƒ€์ž… ์ œ์™ธ ์„ค์ •(!@types/react ๋“ฑ)์€ shamefully-hoist=true ์•ž์—์„œ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
    • React ํƒ€์ž…๋„ ๊ฒฐ๊ตญ ๊ณต๊ฐœ ํ˜ธ์ด์ŠคํŒ…๋˜๋ฏ€๋กœ, ์˜์กด์„ฑ ์ถฉ๋Œ ๋ฐฉ์ง€ ํšจ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค
  3. ๋ฒˆ๋“ค ์ตœ์ ํ™” ๋ชฉํ‘œ ์žฌ๊ฒ€ํ† 

    • ๊ด‘๋ฒ”์œ„ํ•œ ํ˜ธ์ด์ŠคํŒ…๋งŒ์œผ๋กœ๋Š” Next.js ๋ฒˆ๋“ค ํฌ๊ธฐ๋ฅผ ์ค„์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค
    • ์‹ค์ œ ์ตœ์ ํ™”๋Š” next.config.js์˜ transpilePackages์™€ optimizePackageImports ์„ค์ •์œผ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค

๊ถŒ์žฅ ์กฐ์น˜:

  • ๋ถˆํ•„์š”ํ•œ public-hoist-pattern[]='*'๋ฅผ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜
  • shamefully-hoist=true๋กœ ํ†ต์ผํ•˜๋˜, ๋ฒˆ๋“ค ์ตœ์ ํ™”๋Š” Next.js ์„ค์ •์œผ๋กœ ์ง„ํ–‰ํ•˜์„ธ์š”
๐Ÿค– Prompt for AI Agents
In @.npmrc around lines 3 - 5, The .npmrc contains conflicting hoisting
settings: remove the redundant public-hoist-pattern[]='*' entries (and the
negations '!@types/react' / '!@types/react-dom' which are ineffective when
shamefully-hoist=true) or else remove shamefully-hoist=true so
public-hoist-patterns take effect; then move bundle-size optimizations into
Next.js config by adjusting next.config.js (use transpilePackages and
optimizePackageImports) rather than relying on broad pnpm hoisting.

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