Afaik

SEO (검색 엔진 최적화)

중요도: ⭐⭐⭐⭐⭐

웹사이트의 검색 가시성을 높이는 핵심 기술입니다.

개념

SEO(Search Engine Optimization)는 검색 엔진 최적화를 뜻하며, 검색 엔진에서 찾기 쉽도록 사이트를 개선하는 프로세스입니다.

SEO의 핵심 요소

1. HTML 메타 태그

Title 태그

<!-- 각 페이지마다 고유하고 설명적인 제목 -->
<title>React 면접 질문 모음 | Frontend Developer Guide</title>

<!-- 길이: 50-60자 권장 -->
<!-- 키워드를 앞쪽에 배치 -->
<title>JavaScript 클로저 완벽 가이드 - 개념부터 실무까지</title>

Meta Description

<!-- 검색 결과에 표시되는 설명문 -->
<meta
  name="description"
  content="JavaScript 클로저의 개념부터 실무 활용까지 상세히 설명합니다. 렉시컬 환경, 스코프 체인, 메모리 관리 등 핵심 내용을 다룹니다."
/>

<!-- 길이: 150-160자 권장 -->
<!-- 액션 지향적 문구 포함 -->

Open Graph 태그

<!-- 소셜 미디어 공유 시 표시되는 정보 -->
<meta property="og:title" content="JavaScript 클로저 완벽 가이드" />
<meta
  property="og:description"
  content="클로저의 개념부터 실무 활용까지 상세히 설명합니다."
/>
<meta
  property="og:image"
  content="https://example.com/images/closure-guide.jpg"
/>
<meta property="og:url" content="https://example.com/javascript/closure" />
<meta property="og:type" content="article" />

<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="JavaScript 클로저 완벽 가이드" />
<meta
  name="twitter:description"
  content="클로저의 개념부터 실무 활용까지 상세히 설명합니다."
/>
<meta
  name="twitter:image"
  content="https://example.com/images/closure-guide.jpg"
/>

2. 시맨틱 HTML

시맨틱 마크업은 검색 엔진이 콘텐츠의 의미를 이해하는 데 도움을 줍니다.

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <title>웹 개발 블로그</title>
  </head>
  <body>
    <header>
      <nav>
        <ul>
          <li><a href="/frontend">Frontend</a></li>
          <li><a href="/backend">Backend</a></li>
        </ul>
      </nav>
    </header>

    <main>
      <article>
        <header>
          <h1>JavaScript 클로저 이해하기</h1>
          <time datetime="2024-01-15">2024년 1월 15일</time>
          <address>작성자: <a href="/author/john">John Doe</a></address>
        </header>

        <section>
          <h2>클로저란 무엇인가?</h2>
          <p>클로저는 함수와 그 함수가 선언된 렉시컬 환경의 조합입니다.</p>
        </section>

        <aside>
          <h3>관련 글</h3>
          <ul>
            <li><a href="/javascript/scope">스코프 체인</a></li>
            <li><a href="/javascript/hoisting">호이스팅</a></li>
          </ul>
        </aside>
      </article>
    </main>

    <footer>
      <p>&copy; 2024 웹 개발 블로그. All rights reserved.</p>
    </footer>
  </body>
</html>

3. 헤딩 구조 (H1-H6)

<!-- 계층적 구조로 작성 -->
<h1>JavaScript 완벽 가이드</h1>
<!-- 페이지 제목 (한 페이지에 하나) -->
<h2>기본 개념</h2>
<!-- 주요 섹션 -->
<h3>변수와 데이터 타입</h3>
<!-- 하위 섹션 -->
<h4>원시 타입</h4>
<!-- 세부 항목 -->
<h5>Number</h5>
<!-- 더 세부적인 항목 -->
<h5>String</h5>
<h4>참조 타입</h4>
<h3>함수</h3>
<h2>고급 개념</h2>
<h3>클로저</h3>
<h3>프로토타입</h3>

4. 이미지 최적화

<!-- Alt 속성은 필수 -->
<img
  src="closure-diagram.jpg"
  alt="JavaScript 클로저의 렉시컬 환경 다이어그램"
/>

<!-- 반응형 이미지 -->
<picture>
  <source
    media="(max-width: 768px)"
    srcset="closure-mobile.webp"
    type="image/webp"
  />
  <source
    media="(max-width: 768px)"
    srcset="closure-mobile.jpg"
    type="image/jpeg"
  />
  <source srcset="closure-desktop.webp" type="image/webp" />
  <img
    src="closure-desktop.jpg"
    alt="JavaScript 클로저 개념 설명"
    loading="lazy"
  />
</picture>

<!-- 구조화된 데이터 -->
<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": "JavaScript 클로저 완벽 가이드",
    "image": "https://example.com/images/closure-guide.jpg",
    "author": {
      "@type": "Person",
      "name": "John Doe"
    },
    "publisher": {
      "@type": "Organization",
      "name": "웹 개발 블로그"
    },
    "datePublished": "2024-01-15",
    "dateModified": "2024-01-20"
  }
</script>

5. URL 구조

// ✅ SEO 친화적 URL
https://example.com/javascript/closure-complete-guide
https://example.com/react/hooks/useeffect-guide
https://example.com/blog/2024/web-performance-optimization

// ❌ SEO에 불리한 URL
https://example.com/page?id=123&category=js
https://example.com/article/2024/01/15/post-456789
https://example.com/#/javascript/closure

페이지 속도 최적화

페이지 로딩 속도는 SEO 순위에 직접적인 영향을 미칩니다.

Core Web Vitals 최적화

// 1. LCP (Largest Contentful Paint) 개선
// 중요 리소스 우선 로드
<link rel="preload" href="hero-image.jpg" as="image">
<link rel="preload" href="main-font.woff2" as="font" type="font/woff2" crossorigin>

// 2. FID (First Input Delay) 개선
// 긴 작업을 작은 단위로 분할
function processLargeData(data) {
  const chunks = chunkArray(data, 1000);

  function processChunk(index) {
    if (index >= chunks.length) return;

    // 현재 청크 처리
    processItems(chunks[index]);

    // 다음 청크를 다음 틱에 처리
    setTimeout(() => processChunk(index + 1), 0);
  }

  processChunk(0);
}

// 3. CLS (Cumulative Layout Shift) 개선
// 이미지와 광고에 크기 지정
<img src="hero.jpg" alt="Hero image" width="800" height="400" loading="lazy">

// 동적 콘텐츠를 위한 플레이스홀더
.skeleton {
  width: 100%;
  height: 200px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
}

모바일 친화성

<!-- 반응형 디자인 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<!-- 터치 친화적 인터페이스 -->
<style>
  .touch-target {
    min-height: 44px;
    min-width: 44px;
    padding: 12px;
  }

  @media (max-width: 768px) {
    body {
      font-size: 16px; /* iOS 줌 방지 */
    }
  }
</style>

내부 링크 구조

<!-- 관련 페이지로의 내부 링크 -->
<article>
  <p>
    JavaScript의 <a href="/javascript/scope">스코프</a>에 대해 이해했다면, 이제
    <a href="/javascript/closure">클로저</a>를 학습해보세요.
  </p>

  <!-- 브레드크럼 내비게이션 -->
  <nav aria-label="breadcrumb">
    <ol>
      <li><a href="/">홈</a></li>
      <li><a href="/javascript">JavaScript</a></li>
      <li aria-current="page">클로저</li>
    </ol>
  </nav>
</article>

사이트맵과 robots.txt

XML 사이트맵

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/</loc>
    <lastmod>2024-01-15</lastmod>
    <changefreq>weekly</changefreq>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://example.com/javascript/closure</loc>
    <lastmod>2024-01-15</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
</urlset>

robots.txt

User-agent: *
Allow: /
Disallow: /admin/
Disallow: /private/

Sitemap: https://example.com/sitemap.xml

JavaScript SEO (SPA)

Server-Side Rendering (SSR)

// Next.js SSR 예시
export async function getServerSideProps(context) {
  const { slug } = context.params;
  const post = await getPostBySlug(slug);

  return {
    props: {
      post,
      meta: {
        title: post.title,
        description: post.excerpt,
        openGraph: {
          title: post.title,
          description: post.excerpt,
          images: [{ url: post.featuredImage }],
        },
      },
    },
  };
}

function PostPage({ post, meta }) {
  return (
    <>
      <Head>
        <title>{meta.title}</title>
        <meta name="description" content={meta.description} />
        <meta property="og:title" content={meta.openGraph.title} />
        <meta property="og:description" content={meta.openGraph.description} />
        <meta property="og:image" content={meta.openGraph.images[0].url} />
      </Head>

      <article>
        <h1>{post.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.content }} />
      </article>
    </>
  );
}

Static Site Generation (SSG)

// Next.js SSG 예시
export async function getStaticPaths() {
  const posts = await getAllPosts();
  const paths = posts.map((post) => ({
    params: { slug: post.slug },
  }));

  return {
    paths,
    fallback: false,
  };
}

export async function getStaticProps({ params }) {
  const post = await getPostBySlug(params.slug);

  return {
    props: { post },
    revalidate: 86400, // 24시간마다 재생성
  };
}

성능 모니터링

// Core Web Vitals 측정
import { getCLS, getFID, getFCP, getLCP, getTTFB } from "web-vitals";

getCLS(console.log);
getFID(console.log);
getFCP(console.log);
getLCP(console.log);
getTTFB(console.log);

// Google Analytics에 전송
function sendToAnalytics(metric) {
  gtag("event", metric.name, {
    value: Math.round(
      metric.name === "CLS" ? metric.value * 1000 : metric.value,
    ),
    event_category: "Web Vitals",
    event_label: metric.id,
    non_interaction: true,
  });
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);

SEO 도구 및 분석

Search Console 설정

<!-- Google Search Console 인증 -->
<meta name="google-site-verification" content="your-verification-code" />

<!-- Bing Webmaster Tools 인증 -->
<meta name="msvalidate.01" content="your-verification-code" />

구조화된 데이터 (JSON-LD)

<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "WebSite",
    "name": "웹 개발 블로그",
    "url": "https://example.com",
    "potentialAction": {
      "@type": "SearchAction",
      "target": "https://example.com/search?q={search_term_string}",
      "query-input": "required name=search_term_string"
    }
  }
</script>

면접 팁

SEO는 단순히 메타 태그 설정만이 아닙니다. 사용자 경험, 페이지 속도, 모바일 친화성, 콘텐츠 품질 등 다양한 요소가 복합적으로 작용한다는 것을 이해하고 설명할 수 있어야 합니다.