[fix] 초기 로드 렌더 차단 리소스 제거 - #1945
seongwon030 wants to merge 2 commits into
Conversation
manualChunks가 react-datepicker와 date-fns를 같은 'dates' 청크로 묶고 있었다. date-fns는 getDeadLineText 등 메인 진입 경로에서 정적 import되므로, 관리자 화면에서만 쓰는 react-datepicker까지 초기 그래프로 끌려와 JS 103.9KB가 모든 페이지에서 modulepreload되고 CSS 22KB가 렌더를 차단했다.
Krona One은 관리자 로그인 화면의 'Log in' 제목 한 곳에서만 쓰는데, index.html의 동기 stylesheet라 전체 방문자의 첫 렌더를 막고 있었다.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 57 minutes Limit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?Wait for the limit to reset, then comment An organization admin can change what happens after included review limits in Billing. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
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 |
#️⃣연관된 이슈
📝작업 내용
Lighthouse가 짚은 렌더 차단 요청 4건을 추적한 결과, 원인이 서로 다른 두 가지였습니다.
1. react-datepicker가 초기 청크에 딸려오던 문제 (
vite.config.ts)manualChunks가react-datepicker와date-fns를 둘 다'dates'청크로 묶고 있었습니다.date-fns는getDeadLineText.ts,formatTimeAgo.ts등 메인 진입 경로에서 정적 import 되기 때문에, 관리자 모집 설정 탭에서만 쓰는react-datepicker까지 초기 그래프로 끌려왔습니다.react-datepicker를'datepicker'별도 청크로 분리했습니다.AdminRoutes지연 청크로 이동2. 관리자 전용 폰트가 전체 렌더를 막던 문제 (
index.html)Krona One은 관리자 로그인 화면의
Log in제목 한 곳(LoginTab.styles.ts:31)에서만 쓰는데, 동기 stylesheet라 관리자 페이지를 볼 일 없는 방문자 전원의 첫 렌더를 잡고 있었습니다.media="print" onload="this.media='all'"로 비동기 로드로 바꿨습니다.검증 방법
tsc --noEmit통과jest52 suites / 444 tests 전부 통과vite build후dist/index.html에 datepicker 관련<link>가 없고,AdminRoutes-*.js의__vitePreload의존 목록에만 문자열로 남는 것 확인<link>에media="print" onload속성이 유지되는 것 확인측정 결과 (로컬 Lighthouse 12, before/after 교차 측정)
두 빌드를 같은 로컬 서버(
vite preview+ dev API 프록시)에서 devtools 스로틀링 10Mbps/40ms·CPU 4x로 교차 측정했습니다. LCP 요소는 두 빌드 모두 앱 다운로드 팝업 이미지(app-download.webp)로 프로덕션과 동일합니다.결과가 ~950ms / ~2270ms 이중 분포로 갈립니다. before는 9회 중 8회가 느린 모드, after는 9회 중 7회가 빠른 모드였습니다. 트레이스를 보면 느린 회차는 1315ms에 페이지 전체를 Paint까지 해놓고 compositor가 2263ms까지 한 프레임도 화면에 내보내지 않습니다(필름스트립에도 그 사이 프레임 없음). 차단 CSS는 모든 회차에서 300ms 안에 끝나므로, Lighthouse가 표시한 "160ms 절감" 모델과는 다른 경로입니다.
두 변경을 분리해 측정한 결과 Krona One 비차단 전환이 이 지연을 없앱니다. datepicker 분리만 적용한 빌드는 before와 같고(빠른 모드 1/4), Krona One만 비차단으로 바꾼 빌드는 after와 같습니다(3/4). datepicker 분리의 가치는 LCP가 아니라 초기 JS 103.9KB / CSS 22KB 제거입니다.
조건을 붙입니다. 이 지연은 headless Chrome(신·구 모드 모두)에서 재현한 것이고, 실사용자 Chrome에서 같은 정도로 나는지는 배포 후 Sentry Web Vitals p75 LCP로 확인해야 합니다. Google Fonts 차단 stylesheet가 Chrome 내부에서 왜 이 stall을 만드는지는 특정하지 못했습니다.
영향 범위
Log in제목은 Krona One이 늦게 적용되어 잠깐 폴백 폰트로 보일 수 있습니다.onload핸들러는 차단되지 않는 것을 확인했습니다.논의하고 싶은 부분
Pretendard는 판단이 갈려서 이번에 손대지 않았습니다.
pretendard.css는 이미 9개@font-face전부font-display: swap이라, 차단이 FOUT을 막아주고 있지 않습니다. 다만 빠른 회선에서 스왑이 매번 보이게 됩니다. FCP는 좋아지고 CLS는 나빠질 수 있습니다. 이번 측정에서도 빠른 모드 회차는 CLS 0.076, 느린 모드는 0이었습니다.🫡 참고사항
별건이지만 같이 확인하다 발견했습니다. 현재 쓰는
static/pretendard.css는 weight당 woff2가 765~791KB입니다(Regular 765,892 / Bold 791,156 바이트). 이번 측정 트레이스에서도 Regular·Medium·SemiBold·Bold 4개가 각각 ~6초 동안 내려오는 것이 확인됐습니다(10Mbps 기준).font-display: swap이라 LCP는 막지 않지만 대역폭을 크게 잡습니다.dist/web/static/pretendard-dynamic-subset.css로 URL 한 줄만 바꾸면 unicode-range 분할 서브셋이라 실제 쓰는 글자 범위만 받습니다.font-family와 weight가 동일한 드롭인이라 시각적 변화가 없습니다. 렌더 차단과는 다른 축이라 이 PR에는 넣지 않았습니다.