블로그가 어떻게 동작하는지 알아보기 - SEO
2024년 09월 05일SEO를 알아보자 Search Engine Optimization
SEO는 한국어로 검색 엔진 최적화입니다. 네이버나 구글에서 검색했을 때 검색 엔진이 더 잘 찾을 수 있도록 도와주는 역할을 합니다.
SEO에는 크게 3가지 종류가 있습니다:
- Technical SEO
- On-Page SEO
- Off-page SEO
Technical SEO 이란
검색을 하기 위해 검색엔진 봇이 돌아다니는데, 이 봇들이 쉽게 크롤링하고 인덱싱할 수 있도록 기술적 요소를 최적화하는 작업입니다. 예를 들어, 사이트 로딩 속도, 모바일 친화성, SSL 인증서, 사이트맵 등이 포함됩니다.
On-Page SEO 이란
웹사이트 내부의 콘텐츠와 소스를 최적화하는 작업입니다. 여기에는 키워드, 메타 태그, 이미지 최적화, 콘텐츠 품질 등이 포함됩니다.
Off-page SEO 이란
웹사이트 외부에서 최적화 작업을 하는 것으로, 다른 웹사이트들이 내 사이트에 링크를 걸면 사이트의 권위를 높이고 검색 엔진에서 높은 점수를 얻게 됩니다.
웹 개발자가 할 수 있는 최적화 작업은 위 3가지 중 2가지입니다. 이제 이 두 가지를 살펴보겠습니다.
Technical SEO 최적화 작업을 알아보자.
전 글에서 사이트 로딩 속도에 대해 언급했었죠. Google의
Lighthouse
의 Performance
가 사이트 속도를 측정하는 주요 지표입니다.Lighthouse
를 사용하면 사이트의 성능을 분석하고 개선할 수 있는 구체적인 항목들을 확인할 수 있습니다.위 사진은 제 블로그 Performance 점수입니다.
Performance 세부 항목에는 FCP, LCP, TBT, CLS, SI 총 5개가 있습니다. 하나씩 살펴보겠습니다:
- FCP : 웹 페이지에서 첫 번째 콘텐츠가 렌더링되기까지 걸리는 시간
- LCP : 페이지에서 가장 큰 콘텐츠가 렌더링되는 시간
- TBT : 페이지가 로드되는 동안 사용자가 상호작용할 수 없는 시간의 총합
- CLS : 페이지 로드 중 레이아웃이 얼마나 자주, 얼마나 크게 이동하는지를 측정
- SI : 페이지가 시각적으로 완성되는 데 걸리는 시간
현재 블로그는 SSG로 렌더링되기 때문에 빠를 수밖에 없습니다.
Next.js App Router 에서 SiteMap 생성방법을 알아보자
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://acme.com</loc> <lastmod>2023-04-06T15:02:24.021Z</lastmod> <changefreq>yearly</changefreq> <priority>1</priority> </url> <url> <loc>https://acme.com/about</loc> <lastmod>2023-04-06T15:02:24.021Z</lastmod> <changefreq>monthly</changefreq> <priority>0.8</priority> </url> <url> <loc>https://acme.com/blog</loc> <lastmod>2023-04-06T15:02:24.021Z</lastmod> <changefreq>weekly</changefreq> <priority>0.5</priority> </url> </urlset>
간단한 페이지들은 수동으로 입력해도 됩니다. 그러나 블로그처럼 많은 게시글을 올리는 사이트에서는 하나하나 입력하기 어려우므로 Next.js에서 제공하는 함수를 사용해보겠습니다.
import type { MetadataRoute } from 'next'; import { useReadMdx as ReadMDX } from '../hooks/useReadMdx'; import { MDX } from '@/interface'; export default async function sitemap(): Promise<MetadataRoute.Sitemap> { const baseUrl = 'https://bittenlog.vercel.app'; const posts: MDX.Metadata[] = (await ReadMDX()) as MDX.Metadata[]; const indexPage = { url: baseUrl, lastModified: new Date().toISOString().split('T')[0], }; const article = posts?.map((post) => { return { url: `${baseUrl}/article/${post.path}`, lastModified: new Date(post.date).toISOString().split('T')[0], }; }); return [indexPage, ...article]; }
이게 끝이야?
기본적인 설정은 끝났지만,
sitamp.xml
에는 한계가 있습니다.
최대 50,000개의 Sitemap을 포함할 수 있지만 크기는 50MB(52,428,800바이트)를 초과할 수 없습니다
라고 명시되어 있습니다.공식 문서를 보고 응용해보겠습니다.
import type { MetadataRoute } from 'next'; export async function generateSitemaps() { return [{ id: 'test1' }, { id: 'test2' }, { id: 'test3' }]; } export default async function sitemap({ id }: { id: string }): Promise<MetadataRoute.Sitemap> { const products = new Array(5000).fill(null).map((_, index) => ({ id: index + 1, date: new Date().toISOString(), })); return products.map((product) => ({ url: `http://localhost:3000/product/${product.id}`, lastModified: product.date, })); }
페이지에 사용되는 ID 목록을 생성하고, ID에 따른 사이트맵을 생성합니다.
● /sitemap/[__metadata_id__] 0 B 0 B ├ /sitemap/test1.xml ├ /sitemap/test2.xml └ /sitemap/test3.xml
이렇게 하면 SiteMap이 여러 개 생성되고, 파일 한 개당 5000개씩 채워져서
output
으로 나온 SiteMap을 구글에 등록하면 됩니다. 이 블로그는 50,000개 정도의 게시글을 올릴 일이 없으니 간단하게 적용했습니다.On-Page SEO 최적화 작업을 알아보자.
메타 태그
사이트 링크를 공유하든 검색창에서 처음으로 마주하는 것이 메타 태그이기 때문에 메타 태그는 가장 중요합니다. 그러면 Next.js에서 메타 태그를 어떻게 간단히(?) 설정할 수 있는지 알아보겠습니다.
다시 공식문서로 가보면:
export const metadata = { title: 'Blog', openGraph: { title: 'Blog', }, };
위와 같은 형식으로 되어 있습니다. 이제 블로그에 적용해보겠습니다.
export const metadata: Metadata = { metadataBase: new URL('https://bittenlog.vercel.app'), title: { default: 'Bitten Dev', template: '%s | Bitten Dev', }, category: 'tech blog', description: '성장 욕구가 많은 개발자로서, 공부한 내용을 정리하는 개발 블로그 입니다.', authors: [{ name: '비튼', url: 'https://bittenlog.vercel.app' }], openGraph: { images: ogImage.src, title: { default: 'Bitten Dev', template: '%s | Bitten', }, description: '성장 욕구가 많은 개발자로서, 공부한 내용을 정리하는 개발 블로그 입니다.', }, verification: { google: 'uBovfhvYdbEJvqXAGE44EfvyNswgNRSOmXXEApmtV_g', }, };
app/layout.tsx
블로그에는 기본적인 것들만 설정해놓았습니다.
title.template
을 보면 %s | Bitten Dev
라고 되어 있는데, %s는 변수를 나타냅니다.export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> { const data = await getFiles(params.slug); if (!data) return {}; return { title: data.meta.title, description: data.meta.description, openGraph: { images: data.meta.thumbnail, }, keywords: [...(data.meta.tags ?? [])], }; }
app/article[slug]/page.tsx 에서 Metadata설정한 코드입니다.
이렇게 title만 정의해 놓으면
| Bitten Dev
는 계속 뒤에 따라다니게 됩니다. title을 정하지 않으면 title.default
의 값인 Bitten Dev
으로 나오게 됩니다.category 태그는 웹사이트의 종류나 범주를 명시하면 됩니다.
description 태그는 웹사이트의 설명을 적으면 검색 시 미리보기로 보여집니다.
authors 태그는 필수는 아니지만, 작성자의 정보를 추가하면 웹 문서의 출처를 명확히 할 수 있습니다.
keywords 태그는 이제 사용하지 않습니다. 구글에서 사용하지 않는다고 명시해놨다.
openGrap
소셜 미디어에서 가장 먼저 보여지는 항목입니다.
title , description은 그대로 사용하면 됩니다. 원래는 상속되었지만, 테스트할 때 문제가 있어 적용했습니다.
images가 가장 중요합니다. 파일 형식은 JPEG, PNG, GIF를 지원하며, PNG로 하는 것이 좋습니다. 해상도는 원래 200 X 200 이였지만 최근에는 1200 X 630 을 권장합니다.
Off-page SEO 최적화 작업을 알아보자
이 작업은 마케팅이 중요하고 협력사끼리 서로 링크를 공유하여 검색엔진 순위를 올리는 방식입니다. 공유가 많을 만한 글이 아닌 이상 올리기 어렵고, 백링크를 구매하여 순위를 올리기도 합니다.
다른 웹사이트에 링크를 남발하거나 구매할 수 있지만, 이상한 웹사이트에 남발하면 오히려 본인 웹사이트에 나쁜 영향을 미칠 수 있습니다. 최적화에 가장 좋은 방법은 돈을 주고 업체에 맡기는 것이라고 생각합니다.
마치면서
오늘은 Next.js의 함수를 이용하여 SEO 최적화를 알아보았습니다. 앞으로는 CS 기초 다지기를 들어갈 것이므로, 개발 CS 관련 글을 작성할 예정입니다.