WebPiki
tutorial

개발자를 위한 SEO 완벽 가이드 — 기술적 SEO 중심으로

마케터가 아닌 개발자 관점의 SEO. 크롤링, 메타 태그, 사이트맵, Core Web Vitals까지 코드로 구현하는 기술적 SEO 정리.

SEO 관련 글을 검색하면 대부분 마케터 시점이다. "키워드를 잘 넣어라", "백링크를 확보해라" 같은 내용. 틀린 말은 아닌데, 개발자한테는 좀 뜬구름 잡는 느낌이 있다. 개발자가 실제로 컨트롤할 수 있는 건 **기술적 SEO(Technical SEO)**다. 코드와 인프라 레벨에서 검색 엔진이 사이트를 제대로 이해하고 평가할 수 있게 만드는 작업.

이 글은 그 부분에 집중한다.

검색 엔진이 사이트를 읽는 과정

구글이 내 사이트를 검색 결과에 보여주기까지 세 단계를 거친다.

  1. 크롤링 — Googlebot이 페이지를 방문해서 HTML을 가져감
  2. 인덱싱 — 가져간 HTML을 분석해서 검색 데이터베이스에 저장
  3. 랭킹 — 검색어에 맞는 페이지를 관련도 순으로 정렬

개발자가 기술적으로 영향을 줄 수 있는 건 주로 1번과 2번이다. 크롤러가 사이트를 잘 돌아다닐 수 있게 만들고, 각 페이지의 내용을 검색 엔진이 제대로 파악할 수 있게 만드는 거다.

메타 태그 — 기본 중의 기본

<head>
  <title>페이지 제목 — 사이트명</title>
  <meta name="description" content="120자 내외의 페이지 설명" />
  <link rel="canonical" href="https://example.com/page" />
  <meta name="robots" content="index, follow" />
</head>

title — 검색 결과에 파란 링크로 표시되는 그거. 60자 내외가 적당하다. 핵심 키워드를 앞쪽에 넣되, 자연스러운 문장으로 만들어야 한다. "Next.js | React | 프레임워크 | 웹개발" 이런 식으로 키워드를 나열하는 건 역효과다.

description — 검색 결과에서 제목 아래 회색 텍스트로 나오는 부분. 클릭률에 직접 영향을 주니까 대충 쓰면 안 된다. 120~155자 사이로, 해당 페이지에서 사용자가 얻을 수 있는 가치를 명확하게 적는다.

canonical — 같은 콘텐츠가 여러 URL로 접근 가능할 때 "이게 원본이야"라고 지정하는 태그. ?sort=price 같은 쿼리 파라미터로 여러 URL이 생기는 경우에 특히 중요하다. 안 넣으면 검색 엔진이 중복 콘텐츠로 판단해서 랭킹이 깎일 수 있다.

Open Graph & 트위터 카드

SNS에 링크를 공유했을 때 미리보기로 표시되는 정보다. SEO 랭킹에 직접 영향을 주지는 않지만, 공유를 통한 트래픽 유입에 영향을 주니까 무시할 건 아니다.

<meta property="og:title" content="페이지 제목" />
<meta property="og:description" content="설명" />
<meta property="og:image" content="https://example.com/og-image.png" />
<meta property="og:url" content="https://example.com/page" />
<meta property="og:type" content="article" />

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="페이지 제목" />

OG 이미지 사이즈는 1200×630px이 표준이다. 이걸 빠뜨리면 SNS에 링크를 공유했을 때 썸네일이 안 뜨거나 깨진 이미지가 나온다.

사이트맵과 robots.txt

sitemap.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>2026-03-18</lastmod>
  </url>
  <url>
    <loc>https://example.com/blog/my-post</loc>
    <lastmod>2026-03-15</lastmod>
  </url>
</urlset>

Next.js에서는 app/sitemap.ts 파일을 만들면 자동으로 생성할 수 있다. 블로그 글이 추가될 때마다 수동으로 수정할 필요 없이, 데이터 소스에서 읽어서 동적으로 만드는 게 좋다.

robots.txt — 크롤러에게 "여기는 오지 마" 또는 "사이트맵은 여기 있어"를 알려주는 파일.

User-agent: *
Allow: /
Disallow: /api/
Sitemap: https://example.com/sitemap.xml

/api/ 같은 경로는 검색 결과에 나올 필요가 없으니까 Disallow로 막아두는 게 일반적이다.

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

구글 검색 결과에서 별점, FAQ, 레시피 카드 같은 **리치 스니펫(Rich Snippet)**을 본 적 있을 거다. 이걸 만들어내는 게 구조화된 데이터다. JSON-LD 형식으로 페이지 정보를 검색 엔진에 전달한다.

<script type="application/ld+json">
{JSON.stringify({
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "글 제목",
  "datePublished": "2026-03-18",
  "author": {
    "@type": "Person",
    "name": "작성자"
  }
})}
</script>

넣는다고 무조건 리치 스니펫이 표시되는 건 아니지만, 검색 엔진이 페이지 내용을 더 정확하게 파악하는 데 도움이 된다. 블로그 글에는 Article, 도구 페이지에는 WebApplication, FAQ가 있으면 FAQPage 타입을 쓰는 식이다.

Core Web Vitals — 성능이 곧 SEO

구글은 2021년부터 페이지 성능을 랭킹 요소에 포함시켰다. 세 가지 지표가 핵심이다.

LCP (Largest Contentful Paint) — 화면에서 가장 큰 콘텐츠가 렌더링되는 시간. 2.5초 이내가 목표. 대부분 히어로 이미지나 큰 텍스트 블록이 대상이다.

개발자가 할 수 있는 것:

  • 이미지에 width, height 속성 명시 (레이아웃 시프트 방지)
  • Next.js의 <Image> 컴포넌트 활용 (자동 최적화, lazy loading)
  • 폰트에 font-display: swap 적용

INP (Interaction to Next Paint) — 사용자 인터랙션 후 화면이 업데이트되기까지의 시간. 200ms 이내가 목표. 예전의 FID를 대체한 지표다.

  • 메인 스레드를 오래 차지하는 작업 분리
  • 무거운 연산은 Web Worker로 오프로드
  • React.memo, useMemo 등으로 불필요한 리렌더링 방지

CLS (Cumulative Layout Shift) — 페이지 로드 중 요소가 밀리는 정도. 0.1 이하가 목표. 광고나 이미지가 뒤늦게 로드되면서 텍스트가 갑자기 밀리는 현상.

  • 이미지/비디오에 크기 사전 지정
  • 동적으로 삽입되는 콘텐츠에 공간 예약
  • 웹 폰트 로딩 전략 최적화

Lighthouse나 PageSpeed Insights로 현재 점수를 확인하고, 하나씩 잡아나가는 게 현실적인 접근이다.

렌더링 방식과 SEO의 관계

SSR (Server-Side Rendering) — 서버에서 HTML을 만들어서 보내니까 크롤러가 바로 콘텐츠를 읽을 수 있다. SEO에 가장 유리한 방식.

SSG (Static Site Generation) — 빌드 시점에 HTML을 미리 생성. SSR과 마찬가지로 SEO 친화적이고, 서버 부하도 없다. 블로그나 문서 사이트에 적합.

CSR (Client-Side Rendering) — 브라우저에서 JavaScript로 콘텐츠를 렌더링. 구글봇이 JavaScript를 실행할 수 있긴 하지만, 크롤링 예산(crawl budget)을 더 쓰고, 인덱싱이 지연될 수 있다. SEO가 중요한 페이지에는 피하는 게 좋다.

Next.js App Router를 쓴다면 기본이 서버 컴포넌트(SSR/SSG)라서 별도로 신경 쓸 게 적다. "use client" 컴포넌트에 핵심 콘텐츠를 넣지 않는 것만 주의하면 된다.

실전 체크리스트

새 페이지를 만들 때마다 확인할 항목들:

  • <title><meta description> 설정했는가
  • canonical URL 지정했는가
  • OG 태그 + OG 이미지 설정했는가
  • 이미지에 alt 텍스트 넣었는가
  • heading 태그 계층 구조가 맞는가 (h1 → h2 → h3 순서)
  • sitemap에 포함되는가
  • 모바일에서 제대로 보이는가

이걸 매번 수동으로 체크하는 건 현실적이지 않으니까, 메타데이터 유틸 함수를 하나 만들어서 공통 처리하는 게 낫다. Next.js의 generateMetadata를 래핑해서 기본값을 넣어두면 빠뜨릴 일이 줄어든다.

SEO는 한 번 세팅하고 끝나는 게 아니라 지속적으로 모니터링해야 하는 영역이다. Google Search Console에서 크롤링 에러, 인덱싱 상태, 검색 성능을 정기적으로 확인하는 습관이 결국 가장 중요하다.

#SEO#기술적SEO#웹개발#CoreWebVitals#검색엔진최적화

관련 글