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

SEO 관련 글을 검색하면 대부분 마케터 시점이다. "키워드를 잘 넣어라", "백링크를 확보해라" 같은 내용. 틀린 말은 아닌데, 개발자한테는 좀 뜬구름 잡는 느낌이 있다. 개발자가 실제로 컨트롤할 수 있는 건 **기술적 SEO(Technical SEO)**다. 코드와 인프라 레벨에서 검색 엔진이 사이트를 제대로 이해하고 평가할 수 있게 만드는 작업.
이 글은 그 부분에 집중한다.
검색 엔진이 사이트를 읽는 과정
구글이 내 사이트를 검색 결과에 보여주기까지 세 단계를 거친다.
- 크롤링 — Googlebot이 페이지를 방문해서 HTML을 가져감
- 인덱싱 — 가져간 HTML을 분석해서 검색 데이터베이스에 저장
- 랭킹 — 검색어에 맞는 페이지를 관련도 순으로 정렬
개발자가 기술적으로 영향을 줄 수 있는 건 주로 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 이미지 사이즈는 1200x630px이 표준이다. 이걸 빠뜨리면 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 파일을 만들면 자동으로 생성할 수 있다. 블로그 글이 추가될 때마다 수동으로 수정할 필요 없이, 데이터 소스에서 읽어서 동적으로 만드는 게 좋다. lastmod 날짜를 정확하게 유지하는 것도 중요한데, 구글이 이 날짜를 참고해서 크롤링 빈도를 조절하기 때문이다.
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 타입을 쓰는 식이다. Google Rich Results Test로 구조화된 데이터가 제대로 인식되는지 테스트할 수 있다.
Core Web Vitals — 성능이 곧 SEO
구글은 2021년부터 페이지 성능을 랭킹 요소에 포함시켰다. 세 가지 지표가 핵심이다.
LCP (Largest Contentful Paint) — 화면에서 가장 큰 콘텐츠가 렌더링되는 시간. 2.5초 이내가 목표. 대부분 히어로 이미지나 큰 텍스트 블록이 대상이다.
개발자가 할 수 있는 것:
- 이미지에
width,height속성 명시 (레이아웃 시프트 방지) - Next.js의
<Image>컴포넌트 활용 (자동 최적화, lazy loading) - 폰트에
font-display: swap적용 - LCP 이미지에
fetchpriority="high"설정
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에서 크롤링 에러, 인덱싱 상태, 검색 성능을 정기적으로 확인하는 습관이 결국 가장 중요하다. 검색 노출이 갑자기 떨어지면 인덱싱 오류인 경우가 많으니, Search Console 알림을 설정해두는 것도 좋다.
기술적 SEO는 화려한 기술이 아니라 기본을 충실히 지키는 일에 가깝다. 메타 태그를 빠뜨리지 않고, 사이트맵을 최신으로 유지하고, 페이지 성능을 일정 수준 이상으로 관리하는 것. 이 기본만 잘 해도 대부분의 사이트에서 검색 노출이 눈에 띄게 개선된다.