Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const nextConfig: NextConfig = {
ignoreBuildErrors: false,
},
images: {
formats: ['image/avif', 'image/webp'],
remotePatterns: [
{
protocol: 'https',
Expand Down
Binary file removed public/landing/landing-story-thumbnail.png
Binary file not shown.
Binary file added public/landing/landing-story-thumbnail.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/landing/opening-poster.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/app/head.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function Head() {
return (
<>
<link rel="preload" as="image" href="/landing/opening-poster.webp" fetchPriority="high" />
</>
);
Comment on lines +2 to +6
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

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

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 /.

Suggested change
return (
<>
<link rel="preload" as="image" href="/landing/opening-poster.webp" fetchPriority="high" />
</>
);
return <></>;

Copilot uses AI. Check for mistakes.
}
32 changes: 22 additions & 10 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import dynamic from 'next/dynamic';
import { Header } from '@/shared/components/layout';
import { HeaderActions } from '@/composite/landing/headerAction';
import { IntroSection } from '@/composite/landing/intro';
import { QuestioningSection } from '@/composite/landing/questioning';
import { SuggestionSection } from '@/composite/landing/suggestion';
import { StoryVideoSection } from '@/composite/landing/storyVideo';
import { AddGoalFeatureSection } from '@/composite/landing/addGoal';
import { ManageTodoFeatureSection } from '@/composite/landing/manageTodo';
import { GoalAdviceFeatureSection } from '@/composite/landing/goalAdvice';
import { CollectPlanetFeatureSection } from '@/composite/landing/collectPlanet';
import { FundingDiscountSection } from '@/composite/landing/fundingDiscount';
import { LaunchSection } from '@/composite/landing/launch';
import DonationSection from '@/composite/landing/DonationSection';

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));
Comment on lines +6 to +25
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.

export default function LandingPage() {
return (
Expand Down
1 change: 1 addition & 0 deletions src/composite/landing/DonationSection/DonationImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const DonationImage = () => {
sizes="(max-width: 768px) 200px, 350px"
className="w-50 md:w-87.5 h-auto shrink-0"
alt="donation-section-image"
loading="lazy"
/>
<ToolTip text={renderToolTipText()} position="top-left" tailPosition="top-right" />
</article>
Expand Down
1 change: 1 addition & 0 deletions src/composite/landing/addGoal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const AddGoalFeatureSection = () => {
sizes="(max-width: 768px) 200px, 350px"
className="w-50 md:w-87.5 h-auto shrink-0"
alt="fifth-section-image"
loading="lazy"
/>
</MotionWrapper>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/composite/landing/collectPlanet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const CollectPlanetFeatureSection = () => {
sizes="(max-width: 768px) 200px, 350px"
className="w-50 md:w-87.5 h-auto shrink-0"
alt="eighth-section-image"
loading="lazy"
/>
</MotionWrapper>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/composite/landing/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const LandingPageCommonStyle = {
transition: { duration: 0.8, ease: 'easeOut' },
},
left: {
initial: { opcity: 0, x: -40 },
initial: { opacity: 0, x: -40 },
whileInView: { opacity: 1, x: 0 },
viewport: { once: true, amount: 0.3 },
transition: { duration: 0.8, ease: 'easeOut' },
Expand Down
2 changes: 2 additions & 0 deletions src/composite/landing/fundingDiscount/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const FundingDiscountSection = () => {
height={400}
sizes="(max-width: 768px) 300px 200px"
alt="character-key-ring-image"
className="w-75 md:w-125 h-auto shrink-0"
loading="lazy"
/>
</MotionWrapper>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/composite/landing/goalAdvice/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const GoalAdviceFeatureSection = () => {
sizes="(max-width: 768px) 200px, 350px"
className="w-50 md:w-87.5 h-auto shrink-0"
alt="seventh-section-image"
loading="lazy"
/>
</MotionWrapper>
</div>
Expand Down
7 changes: 5 additions & 2 deletions src/composite/landing/intro/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@ export const IntroSection = () => {
autoPlay
muted
loop
preload="auto"
preload="none"
poster="/landing/opening-poster.webp"
className="w-full h-full object-cover"
>
<track kind="captions" />
</video>
</div>
{/* 오버레이 (그라디언트) */}
<div className="absolute inset-0 z-10 pointer-events-none bg-[linear-gradient(0deg,rgba(0,0,0,0.60)_0%,rgba(0,0,0,0.60)_100%)]" />
<div className={`relative z-20 flex flex-col items-center ${LandingPageCommonStyle.innerContainer} ${LandingPageCommonStyle.padding}`}>
<div
className={`relative z-20 flex flex-col items-center ${LandingPageCommonStyle.innerContainer} ${LandingPageCommonStyle.padding}`}
>
<MotionWrapper {...LandingPageCommonStyle.fadeIn.default}>
<h1 className="text-4xl md:text-6xl font-extrabold text-center text-text-strong animate-fade-in bg-clip-text leading-tight mb-6">
<span className="bg-linear-to-brand">그로잇</span>으로 너의 인생이 바뀔거야
Expand Down
6 changes: 4 additions & 2 deletions src/composite/landing/launch/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ export const LaunchSection = () => {
<Section className="relative w-full overflow-hidden bg-bg-default">
{/* 배경 & 오버레이 */}
<div className="absolute inset-0 z-10 pointer-events-none landing-ten-bg" />
<div className={`relative z-20 flex flex-col gap-y-7 items-center justify-center ${LandingPageCommonStyle.innerContainer} ${LandingPageCommonStyle.padding}`}>
<div
className={`relative z-20 flex flex-col gap-y-7 items-center justify-center ${LandingPageCommonStyle.innerContainer} ${LandingPageCommonStyle.padding}`}
>
<MotionWrapper
{...LandingPageCommonStyle.fadeIn.default}
className="flex flex-col gap-y-4 items-center text-center animate-fade-in"
>
<Image src="/landing/logo.png" width={64} height={64} alt="app-logo" />
<Image src="/landing/logo.png" width={64} height={64} alt="app-logo" loading="lazy" />
<h2 className="bg-linear-to-brand text-4xl font-extrabold leading-tight">2월 APP 런칭</h2>
</MotionWrapper>

Expand Down
1 change: 1 addition & 0 deletions src/composite/landing/manageTodo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const ManageTodoFeatureSection = () => {
sizes="(max-width: 768px) 200px, 350px"
className="w-50 md:w-87.5 h-auto shrink-0"
alt="sixth-section-image"
loading="lazy"
/>
</MotionWrapper>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/composite/landing/questioning/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const QuestioningSection = () => {
sizes="(max-width: 768px) 230px, 260px"
className="w-57.5 md:w-97.75 h-auto shrink-0"
alt="second-section-image"
loading="lazy"
/>
</MotionWrapper>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/composite/landing/storyVideo/StoryVideo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const StoryVideo = () => {
preload="metadata"
playsInline
muted
poster="/landing/landing-story-thumbnail.webp"
className="aspect-video lg:block rounded-lg"
/>
<PlayPauseButton videoRef={videoRef} isHovered={isHovered} />
Expand Down
1 change: 1 addition & 0 deletions src/composite/landing/suggestion/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const SuggestionSection = () => {
sizes="(max-width: 768px) 205px, 356px"
className="w-51.25 md:w-89 h-auto shrink-0"
alt="third-section-image"
loading="lazy"
/>
</MotionWrapper>
</div>
Expand Down
Loading