--- id: wiki-2026-0508-성능-및-seo-최적화-프로젝트 title: 성능 및 SEO 최적화 프로젝트 category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Performance and SEO Project, Web Vitals Optimization Project] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [project, performance, seo, web-vitals, lighthouse] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: typescript framework: nextjs --- # 성능 및 SEO 최적화 프로젝트 ## 매 한 줄 > **"매 Web Vitals + SEO 의 simultaneous improvement project"**. 매 Lighthouse 60→95+ 의 typical scope — LCP/INP/CLS 의 budget 의 set, render-blocking 의 eliminate, structured data 의 add, Core Web Vitals 의 Google ranking signal 의 secure. ## 매 핵심 ### 매 project goals (KPI) - **LCP** ≤ 2.5s (good). - **INP** ≤ 200ms (replaces FID, 2024+). - **CLS** ≤ 0.1. - **Lighthouse Performance** ≥ 90. - **organic traffic** +30% (post 1Q). - **conversion** +10%. ### 매 phase plan 1. **Audit** (week 1): Lighthouse + WebPageTest + RUM (CrUX) baseline. 2. **Quick wins** (week 2-3): image lazy + dimensions, font-display, defer JS. 3. **Architecture** (week 4-6): RSC migration, route-split, edge caching. 4. **SEO** (week 4-6): meta + OG + JSON-LD + sitemap + canonical. 5. **Monitoring** (ongoing): Vercel Speed Insights / SpeedCurve / Sentry. ### 매 SEO checklist - `` (50-60 chars), `<meta description>` (150-160). - Open Graph + Twitter Card. - JSON-LD (Article / Product / Breadcrumb). - canonical, hreflang, robots. - sitemap.xml + robots.txt. - semantic HTML (h1 unique, landmark). - internal link graph. ## 💻 패턴 ### Performance budget (CI) ```js // lighthouserc.js module.exports = { ci: { collect: { url: ['https://staging.example.com/'], numberOfRuns: 3 }, assert: { assertions: { 'categories:performance': ['error', { minScore: 0.9 }], 'largest-contentful-paint': ['error', { maxNumericValue: 2500 }], 'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }], 'interaction-to-next-paint': ['error', { maxNumericValue: 200 }], }, }, upload: { target: 'temporary-public-storage' }, }, }; ``` ### Next.js metadata (App Router) ```tsx // app/blog/[slug]/page.tsx export async function generateMetadata({ params }): Promise<Metadata> { const post = await getPost(params.slug); return { title: `${post.title} | MySite`, description: post.excerpt, alternates: { canonical: `https://mysite.com/blog/${post.slug}` }, openGraph: { title: post.title, description: post.excerpt, images: [{ url: post.cover, width: 1200, height: 630 }], type: 'article', }, twitter: { card: 'summary_large_image' }, }; } ``` ### JSON-LD structured data ```tsx function ArticleJsonLd({ post }: { post: Post }) { const ld = { '@context': 'https://schema.org', '@type': 'Article', headline: post.title, image: [post.cover], datePublished: post.publishedAt, author: [{ '@type': 'Person', name: post.author }], }; return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(ld) }} />; } ``` ### Image optimization ```tsx import Image from 'next/image'; <Image src="/hero.jpg" alt="hero" width={1200} height={630} priority sizes="(max-width: 768px) 100vw, 1200px" placeholder="blur" blurDataURL={post.lqip} /> ``` ### Font optimization (Next.js) ```tsx import { Inter } from 'next/font/google'; const inter = Inter({ subsets: ['latin'], display: 'swap', preload: true }); export default function Layout({ children }) { return <html className={inter.className}>{children}</html>; } ``` ### Web Vitals reporting ```tsx // app/web-vitals.tsx 'use client'; import { useReportWebVitals } from 'next/web-vitals'; export function WebVitals() { useReportWebVitals((m) => { fetch('/api/vitals', { method: 'POST', body: JSON.stringify(m), keepalive: true }); }); return null; } ``` ### Sitemap (Next.js 15) ```tsx // app/sitemap.ts export default async function sitemap() { const posts = await getAllPosts(); return posts.map(p => ({ url: `https://mysite.com/blog/${p.slug}`, lastModified: p.updatedAt, changeFrequency: 'weekly', priority: 0.7, })); } ``` ## 매 결정 기준 | 문제 | Action | |---|---| | LCP 느림 | hero image preload + `priority` + RSC streaming | | INP 느림 | hydration 의 reduce (RSC), long task 의 break | | CLS 발생 | image/font dimensions, ad slot reserve | | 매 SSR 필요 | Next.js App Router (RSC) | | 매 SEO 우선 | static generation (`generateStaticParams`) | | 매 대량 page | ISR (`revalidate`) | **기본값**: 매 Next.js 15 (App Router) + Image/Font 의 use, Lighthouse CI 의 budget enforce, JSON-LD 의 add. ## 🔗 Graph - 부모: [[브라우저 렌더링 파이프라인(Critical Rendering Path)]] - 변형: [[Web Vitals]] · [[Lighthouse CI]] ## 🤖 LLM 활용 **언제**: Lighthouse report 의 prioritize, regression 의 diagnose, meta tag 의 generate. **언제 X**: real RUM data analysis (BigQuery/CrUX 의 use). ## ❌ 안티패턴 - **Lighthouse 만 의 measure**: 매 lab data — 매 RUM (CrUX) 의 substitute. - **`priority` 의 모든 image**: 매 LCP 의 confused — 매 hero 만. - **Empty meta description**: 매 SERP 의 random snippet. - **Duplicate H1**: 매 SEO penalty — 매 unique 의 keep. ## 🧪 검증 / 중복 - Verified (web.dev/learn/performance, Next.js 15 docs, Google Search Central, Lighthouse CI docs). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — Web Vitals + Next.js metadata + Lighthouse CI 의 정리 |