Files
2nd/10_Wiki/Topics/Frontend/성능 및 SEO 최적화 프로젝트.md
T
2026-05-10 22:08:15 +09:00

5.8 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-성능-및-seo-최적화-프로젝트 성능 및 SEO 최적화 프로젝트 10_Wiki/Topics verified self
Performance and SEO Project
Web Vitals Optimization Project
none A 0.9 applied
project
performance
seo
web-vitals
lighthouse
2026-05-10 pending
language framework
typescript 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

  • <title> (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)

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

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

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

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)

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

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

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

🤖 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 의 정리