-
Notifications
You must be signed in to change notification settings - Fork 1
Refactor(client): 이미지 최적화 및 코드 스플리팅 #205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedAn error occurred during the review process. Please try again later. Walkthrough온보딩 이미지 경로·형식 마이그레이션, 일부 온보딩 단계 컴포넌트의 지연 로딩 전환, 이미지 로딩 힌트 추가, 퍼블릭 Firebase 설정 삭제 및 서비스워커의 activate 단계에서 clients.claim() 호출 추가가 적용되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant OnBoardingPage
participant MainCard
participant Suspense
participant StepComponent
User->>OnBoardingPage: 온보딩 페이지 요청
OnBoardingPage->>MainCard: MainCard 렌더
MainCard->>Suspense: 현재 단계의 lazy 컴포넌트 렌더 시도
Suspense->>StepComponent: 번들 로드 (비동기)
StepComponent->>User: 단계 UI 표시
sequenceDiagram
participant SW as ServiceWorker
participant Clients
Note right of SW: activate 이벤트에서 즉시 클라이언트 제어 획득
SW->>SW: addEventListener('activate', ...)
SW->>Clients: clients.claim()
SW->>SW: 기존 로깅 유지
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ 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)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx (1)
201-201: 로딩 폴백 UI 고려 (선택사항)
fallback={null}로 설정되어 있어 lazy 컴포넌트 로딩 중에는 아무것도 표시되지 않습니다. 로컬 컴포넌트이고 로딩 시간이 짧을 것으로 예상되며, 애니메이션 시스템이 전환을 처리하고 있어 현재 구현도 충분할 수 있습니다.다만, 느린 네트워크 환경에서 더 나은 UX를 위해 간단한 로딩 인디케이터(예: 스피너 또는 스켈레톤)를 추가하는 것을 고려해볼 수 있습니다.
예시:
-<Suspense fallback={null}>{renderStep()}</Suspense> +<Suspense fallback={<div className="flex items-center justify-center">로딩 중...</div>}>{renderStep()}</Suspense>
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (10)
apps/client/public/assets/onBoarding/background/onBoardingBg.svgis excluded by!**/*.svgapps/client/public/assets/onBoarding/icons/chippi_bell.svgis excluded by!**/*.svgapps/client/public/assets/onBoarding/icons/chippi_morning.svgis excluded by!**/*.svgapps/client/public/assets/onBoarding/icons/chippi_night.svgis excluded by!**/*.svgapps/client/public/assets/onBoarding/icons/dotori.svgis excluded by!**/*.svgapps/client/public/assets/onBoarding/icons/header_logo.svgis excluded by!**/*.svgapps/client/public/assets/onBoarding/story/macNotice.svgis excluded by!**/*.svgapps/client/public/assets/onBoarding/story/story1.svgis excluded by!**/*.svgapps/client/public/assets/onBoarding/story/story2.svgis excluded by!**/*.svgapps/client/public/assets/onBoarding/story/story3.svgis excluded by!**/*.svg
📒 Files selected for processing (9)
apps/client/src/constants/alarms.ts(1 hunks)apps/client/src/constants/stories.tsx(2 hunks)apps/client/src/pages/onBoarding/OnBoarding.tsx(1 hunks)apps/client/src/pages/onBoarding/components/funnel/MainCard.tsx(2 hunks)apps/client/src/pages/onBoarding/components/funnel/step/AlarmStep.tsx(1 hunks)apps/client/src/pages/onBoarding/components/funnel/step/FinalStep.tsx(1 hunks)apps/client/src/pages/onBoarding/components/funnel/step/MacStep.tsx(1 hunks)apps/client/src/pages/onBoarding/components/funnel/step/StoryStep.tsx(1 hunks)apps/client/src/pages/onBoarding/components/header/Header.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-15T20:00:13.756Z
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 80
File: apps/client/src/shared/components/ui/modalPop/ModalPop.tsx:36-41
Timestamp: 2025-07-15T20:00:13.756Z
Learning: In apps/client/src/shared/components/ui/modalPop/ModalPop.tsx, the InfoBox component uses hardcoded values for title, location, and icon URL as temporary test data. These should be replaced with dynamic data from props when implementing actual functionality and should be marked with TODO comments for future changes.
Applied to files:
apps/client/src/pages/onBoarding/components/funnel/step/FinalStep.tsxapps/client/src/pages/onBoarding/components/header/Header.tsx
🔇 Additional comments (9)
apps/client/src/pages/onBoarding/components/funnel/step/MacStep.tsx (1)
1-2: 에셋 경로 마이그레이션이 올바르게 적용되었습니다.모듈 별칭에서 절대 경로로의 전환이 정확하며, CDN을 통한 에셋 제공을 위한
/public/assets구조와 일치합니다.apps/client/src/pages/onBoarding/components/header/Header.tsx (1)
1-9: 에셋 경로 변경이 정상적으로 적용되었습니다.헤더 로고의 import 경로가 절대 경로로 올바르게 업데이트되었으며, JSX 포맷팅 변경은 기능에 영향을 주지 않습니다.
apps/client/src/constants/alarms.ts (1)
1-3: 아이콘 에셋 경로가 일관되게 업데이트되었습니다.세 개의 치삐 아이콘 경로가 모두 절대 경로로 정확하게 마이그레이션되었으며, 아이콘에 적합한 SVG 포맷이 유지되었습니다.
apps/client/src/pages/onBoarding/components/funnel/step/FinalStep.tsx (1)
1-6: 에셋 경로 업데이트 및 포맷팅 변경이 올바릅니다.dotori 아이콘의 경로가 절대 경로로 정확하게 변경되었으며, 텍스트 포맷팅 변경은 기능에 영향을 주지 않습니다.
apps/client/src/pages/onBoarding/components/funnel/step/StoryStep.tsx (1)
16-17: 이미지 로딩 최적화가 효과적으로 적용되었습니다.
decoding="async"속성으로 이미지 디코딩을 백그라운드로 오프로드하여 메인 스레드 차단을 줄이고,fetchPriority="high"속성으로 네트워크 우선순위를 높여 LCP를 개선합니다. 스토리 이미지는 온보딩의 주요 시각적 콘텐츠이므로 높은 우선순위 설정이 적절합니다.apps/client/src/pages/onBoarding/components/funnel/step/AlarmStep.tsx (1)
1-1: 에셋 경로 마이그레이션이 정확합니다.dotori 아이콘의 import 경로가 절대 경로로 올바르게 변경되었습니다.
apps/client/src/pages/onBoarding/OnBoarding.tsx (1)
1-13: 배경 이미지 최적화가 올바르게 적용되었습니다.배경 에셋이 SVG에서 WebP 포맷으로 전환되어 파일 크기가 개선되었으며, 절대 경로를 통한 CDN 제공 구조와 일치합니다. 인라인 스타일을 통한 배경 이미지 적용도 정확합니다.
apps/client/src/constants/stories.tsx (2)
1-3: 스토리 이미지 포맷 및 경로 최적화가 올바릅니다.스토리 에셋들이 SVG에서 WebP 포맷으로 전환되어 복잡한 일러스트레이션에 더 적합한 포맷을 사용하게 되었으며, 절대 경로로의 변경은 CDN 제공을 위한 구조와 일치합니다.
43-43: 후행 쉼표 추가는 좋은 코딩 관행입니다.배열 마지막 요소에 후행 쉼표를 추가하여 향후 항목 추가 시 더 깔끔한 diff를 생성하고 문법 오류를 방지할 수 있습니다.
| import { useState, useEffect, lazy, Suspense } from 'react'; | ||
| import { motion, AnimatePresence } from 'framer-motion'; | ||
| import StoryStep from './step/StoryStep'; | ||
| import AlarmStep from './step/AlarmStep'; | ||
| import MacStep from './step/MacStep'; | ||
| import FinalStep from './step/FinalStep'; | ||
| const StoryStep = lazy(() => import('./step/StoryStep')); | ||
| const AlarmStep = lazy(() => import('./step/AlarmStep')); | ||
| const MacStep = lazy(() => import('./step/MacStep')); | ||
| const FinalStep = lazy(() => import('./step/FinalStep')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
코드 스플리팅 구현 완료, 에러 처리 확인 필요
단계별 컴포넌트에 대한 lazy loading 구현이 올바르게 되어 있습니다. 이를 통해 초기 번들 크기가 감소하고 각 단계가 필요할 때만 로드됩니다.
다만, lazy-loaded 컴포넌트의 로드 실패(네트워크 오류, 빌드 문제 등)를 처리하기 위한 Error Boundary가 현재 파일에 보이지 않습니다. 상위 컴포넌트에 Error Boundary가 구현되어 있는지 확인해 주세요.
다음 스크립트를 실행하여 상위 컴포넌트에서 Error Boundary 구현 여부를 확인하세요:
🏁 Script executed:
#!/bin/bash
# Description: MainCard를 사용하는 상위 컴포넌트에서 Error Boundary 구현 확인
# MainCard를 import하는 파일 찾기
echo "=== MainCard를 사용하는 파일 검색 ==="
rg -n --type=tsx --type=ts "import.*MainCard" -A 10 -B 5
# Error Boundary 관련 코드 검색
echo -e "\n=== Error Boundary 구현 검색 ==="
rg -n --type=tsx --type=ts -P "(class.*extends.*Component|ErrorBoundary|componentDidCatch)" apps/client/src/pages/onBoarding/Length of output: 114
🏁 Script executed:
#!/bin/bash
# Description: Find MainCard imports and Error Boundary implementations
# Search for MainCard imports using glob patterns
echo "=== MainCard를 사용하는 파일 검색 ==="
rg -n "import.*MainCard" --glob="**/*.tsx" --glob="**/*.ts" -A 5 -B 2
# Search for Error Boundary implementations
echo -e "\n=== Error Boundary 구현 검색 ==="
rg -n -i "error.*boundary|componentDidCatch|error" --glob="**/*.tsx" apps/client/src/pages/onBoarding/ -C 3
# Search for the onBoarding component tree structure
echo -e "\n=== onBoarding 디렉토리 파일 구조 ==="
find apps/client/src/pages/onBoarding -name "*.tsx" -o -name "*.ts" | head -20
# Look specifically for MainCard usage in index or parent files
echo -e "\n=== MainCard를 export하거나 사용하는 파일 ==="
rg -n "MainCard" --glob="**/*.tsx" --glob="**/*.ts" apps/client/src/pages/onBoarding/Length of output: 3413
🏁 Script executed:
#!/bin/bash
# Description: Check OnBoarding.tsx content to verify Error Boundary presence
echo "=== OnBoarding.tsx 전체 내용 검색 ==="
cat apps/client/src/pages/onBoarding/OnBoarding.tsx
echo -e "\n=== MainCard가 사용되는 부분 검색 ==="
grep -n -A 10 -B 10 "<MainCard" apps/client/src/pages/onBoarding/OnBoarding.tsx
echo -e "\n=== React ErrorBoundary import 확인 ==="
grep -r "ErrorBoundary" apps/client/src/pages/onBoarding/Length of output: 1154
Lazy-loaded 컴포넌트에 Error Boundary 추가 필요
코드 스플리팅 구현은 올바르게 되어 있으나, 검증 결과 lazy-loaded 컴포넌트의 로드 실패를 처리하기 위한 Error Boundary가 없습니다.
현재 구조:
OnBoarding.tsx에서 Error Boundary 없이<MainCard />를 직접 사용MainCard.tsx에서 네 개의 step 컴포넌트를 lazy() 및 Suspense로 감싸고 있음- 네트워크 오류, 누락된 청크 등으로 lazy 로드 실패 시 전체 OnBoarding 페이지가 중단될 수 있음
OnBoarding.tsx 또는 MainCard.tsx에 Error Boundary를 추가하여 lazy component 로드 실패에 대한 안정성을 확보하세요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/client/public/firebase-messaging-sw.js (2)
25-31: 중복된 activate 이벤트 리스너를 통합하세요.동일한
activate이벤트에 대해 두 개의 리스너가 등록되어 있습니다. 두 리스너 모두 실행되지만, 코드의 명확성과 유지보수성을 위해 하나의 리스너로 통합하는 것이 좋습니다.다음 diff를 적용하여 두 리스너를 통합하세요:
-self.addEventListener('activate', function () { - console.log('실행중..'); -}); - -self.addEventListener('activate', () => { - clients.claim(); -}); +self.addEventListener('activate', () => { + console.log('실행중..'); + clients.claim(); +});
14-19: Firebase SDK 버전을 9.23.0으로 업데이트하세요.현재 코드는 Firebase SDK 9.22.2를 사용 중입니다. 최신 Firebase JavaScript SDK 9.x 버전은 9.23.0입니다. 다음 두 줄의 URL 버전을 9.22.2에서 9.23.0으로 변경하세요:
importScripts( 'https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js' ); importScripts( 'https://www.gstatic.com/firebasejs/9.23.0/firebase-messaging-compat.js' );
🧹 Nitpick comments (1)
apps/client/src/constants/alarms.ts (1)
1-3: 온보딩 알람 아바타 경로/포맷 변경은 목적에 잘 맞습니다.
- SVG → WebP,
@assets→/assets/...webp변경은 PR에서 설명한 온보딩 이미지 최적화·공용 자산 경로 전략과 일관됩니다.AlarmType.img: string타입과도 호환되어 타입 측면 문제는 없어 보입니다.추가로, 아주 미세한 최적화 제안인데, 이 파일이 단순 상수 모듈인 점을 감안하면 다음처럼 import 없이 문자열 리터럴을 바로 쓰는 것도 고려해볼 수 있습니다. 이렇게 하면 번들링 시 별도의 asset 모듈 import가 줄어들고, public 경로 의미도 더 명확해집니다.
export const AlarmsType: AlarmType[] = [ { img: '/assets/onBoarding/icons/chippi_morning.webp', title: '아침형 치삐', time: '오전 9시' }, { img: '/assets/onBoarding/icons/chippi_night.webp', title: '저녁형 치삐', time: '오후 8시' }, { img: '/assets/onBoarding/icons/chippi_bell.webp', title: '사용자 설정', time: '' }, ];필수는 아니고, 현재 구현도 충분히 괜찮습니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/client/public/firebase-config.js(0 hunks)apps/client/public/firebase-messaging-sw.js(1 hunks)apps/client/src/constants/alarms.ts(1 hunks)
💤 Files with no reviewable changes (1)
- apps/client/public/firebase-config.js
⏰ 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 (1)
apps/client/public/firebase-messaging-sw.js (1)
4-12: Firebase 보안 규칙은 Firebase Console에서 직접 확인하세요.서비스 워커에 노출된 Firebase 설정의 API 키들은 클라이언트 측 사용을 위한 것이며, 공개되어도 문제없습니다. 실제 보안은 Firebase 보안 규칙(Firestore, Realtime Database 등)에 의해 결정됩니다.
이 규칙들은 일반적으로 버전 관리되지 않으며 Firebase Console에서 직접 관리됩니다. 다음을 확인하세요:
- Firestore 보안 규칙이 인증된 사용자만 접근하도록 설정되었는지
- Realtime Database 규칙이 적절히 제한되어 있는지
- Storage 규칙이 권한을 올바르게 검증하는지
📌 Related Issues
📄 Tasks
++ FCM 알람 중복 파일 제거 및 백그라운드 확인 기능 제거
⭐ PR Point (To Reviewer)
decoding="async" 처리
디코딩 과정이 메인 스레드를 잠깐 멈추는 경우가 있음.
저
decoding="async"처리를 통해서 디코딩을 백그라운드에서 처리-> 메인 스레드 점유 줄어듦
-> 화면 깜빡임 / 끊김 줄어듦
fetchPriority="high" 처리
== “이 이미지는 가장 중요한 이미지다. 최우선으로 다운로드해라.”
브라우저는 원래 어떤 리소스를 먼저 받을지 판단하는데, 이걸 알려주는거 (우선로드 지시함!)
fetchPriority="high"를 주면, 이미지가 즉시 네트워크 큐 최상단으로 올라감
폰트보다, CSS보다, JS보다 먼저 불려옴 -> LCP 개선
📷 Screenshot
[초기 성능 측정지표: 35.... 실화냐]

[최적화 이후 : 로컬 상에서의 성능 지표 개선]

Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.