refactor: 랜딩페이지 web vital 지표 개선 작업#263
Conversation
There was a problem hiding this comment.
Pull request overview
랜딩 페이지의 Web Vitals 개선을 목표로, 미디어 로딩 전략(이미지 lazy-load, 비디오 poster/프리로드)과 번들 분리(섹션 dynamic import) 등을 적용한 PR입니다.
Changes:
- 랜딩 섹션 이미지들에
loading="lazy"추가 및 일부 스타일 보강 - 비디오에
poster추가, 인트로 비디오preload조정 및 poster preload를 위한head.tsx추가 - 랜딩 섹션들을
next/dynamic으로 분리하고, 애니메이션 설정 오타(opcity) 수정 + Next Image 포맷 설정 추가
Reviewed changes
Copilot reviewed 15 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/composite/landing/suggestion/index.tsx | 섹션 이미지 lazy-load 적용 |
| src/composite/landing/storyVideo/StoryVideo.tsx | 스토리 비디오에 poster 지정 |
| src/composite/landing/questioning/index.tsx | 섹션 이미지 lazy-load 적용 |
| src/composite/landing/manageTodo/index.tsx | 섹션 이미지 lazy-load 적용 |
| src/composite/landing/launch/index.tsx | 로고 이미지 lazy-load 및 JSX 포맷팅 |
| src/composite/landing/intro/index.tsx | 인트로 비디오 preload 조정 + poster 지정 |
| src/composite/landing/goalAdvice/index.tsx | 섹션 이미지 lazy-load 적용 |
| src/composite/landing/fundingDiscount/index.tsx | 이미지 className 보강 + lazy-load 적용 |
| src/composite/landing/constants.ts | 애니메이션 초기값 오타 수정 (opacity) |
| src/composite/landing/collectPlanet/index.tsx | 섹션 이미지 lazy-load 적용 |
| src/composite/landing/addGoal/index.tsx | 섹션 이미지 lazy-load 적용 |
| src/composite/landing/DonationSection/DonationImage.tsx | 도네이션 이미지 lazy-load 적용 |
| src/app/page.tsx | 랜딩 섹션들을 next/dynamic으로 로딩하도록 변경 |
| src/app/head.tsx | opening poster 이미지 preload 추가 |
| public/landing/landing-story-thumbnail.webp | 스토리 비디오 poster용 썸네일 추가 |
| next.config.ts | Next Image 포맷(avif, webp) 설정 추가 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const QuestioningSection = dynamic(() => import('@/composite/landing/questioning').then(mod => mod.QuestioningSection)); | ||
| const SuggestionSection = dynamic(() => import('@/composite/landing/suggestion').then(mod => mod.SuggestionSection)); | ||
| const StoryVideoSection = dynamic(() => import('@/composite/landing/storyVideo').then(mod => mod.StoryVideoSection)); | ||
| const AddGoalFeatureSection = dynamic(() => | ||
| import('@/composite/landing/addGoal').then(mod => mod.AddGoalFeatureSection) | ||
| ); | ||
| const ManageTodoFeatureSection = dynamic(() => | ||
| import('@/composite/landing/manageTodo').then(mod => mod.ManageTodoFeatureSection) | ||
| ); | ||
| const GoalAdviceFeatureSection = dynamic(() => | ||
| import('@/composite/landing/goalAdvice').then(mod => mod.GoalAdviceFeatureSection) | ||
| ); | ||
| const CollectPlanetFeatureSection = dynamic(() => | ||
| import('@/composite/landing/collectPlanet').then(mod => mod.CollectPlanetFeatureSection) | ||
| ); | ||
| const FundingDiscountSection = dynamic(() => | ||
| import('@/composite/landing/fundingDiscount').then(mod => mod.FundingDiscountSection) | ||
| ); | ||
| const LaunchSection = dynamic(() => import('@/composite/landing/launch').then(mod => mod.LaunchSection)); | ||
| const DonationSection = dynamic(() => import('@/composite/landing/DonationSection').then(mod => mod.default)); |
There was a problem hiding this comment.
next/dynamic is being used to import several landing sections that are Server Components (e.g. questioning/index.tsx, suggestion/index.tsx, etc. have no 'use client'). If the goal is to defer below-the-fold client JS, this setup typically won’t achieve client-side lazy loading (Server Components can’t be shipped to the browser), and it can also introduce extra loading boundaries/chunk requests without clear benefit. Consider keeping these as static imports, or only dynamically importing truly client-heavy sections (or client-only subparts) with an explicit strategy (e.g. ssr: false + a placeholder) so the Web Vitals improvement is guaranteed.
| return ( | ||
| <> | ||
| <link rel="preload" as="image" href="/landing/opening-poster.webp" fetchPriority="high" /> | ||
| </> | ||
| ); |
There was a problem hiding this comment.
src/app/head.tsx is the root head for the entire App Router tree, so this preload will run on every route (e.g. auth/home pages) and can waste bandwidth by preloading a landing-only asset. Consider scoping the preload to the landing route by moving the landing page into a route group (e.g. src/app/(landing)/page.tsx) and adding (landing)/head.tsx, or otherwise ensuring the preload is only emitted on /.
| return ( | |
| <> | |
| <link rel="preload" as="image" href="/landing/opening-poster.webp" fetchPriority="high" /> | |
| </> | |
| ); | |
| return <></>; |
No description provided.