진행중인 프로젝트의 검색 노출도를 높이기 위해 SEO(Search Engine Optimization; 검색엔진 최적화) 개선 작업을 진행하게 되었다.
검색 엔진 최적화를 하면 내가 만든 웹사이트가 검색이 잘 되게 해주고 그로 인해 유저 유입이 늘어날 수 있다.
검색 엔진 최적화를 하는 방법은 검색 엔진이 콘텐츠를 잘 이해하도록 해주는 것이다.
구글의 검색엔진 최적화(SEO) 기본 가이드를 요약하면 다음과 같다.
https://www.example.com/pets/cats.html
: pets, cats 키워드https://www.example.com/2/6772756D707920636174
: 임의의 식별자가 포함되어 있어 도움이 되지 않는다. <meta name="description">
태그를 사용해 검색 결과 스니펫의 텍스트로 사용하기도 한다.HTML의 <header>
에 메타 태그를 추가함으로써 웹페이지의 정보를 추가한다.
검색 엔진은 크롤링시 메타 태그를 읽으므로 상세 정보를 명시함에 따라 검색 결과를 최적화할 수 있다.
웹 페이지 제목을 나타내는 태그로, 브라우저 파비콘 옆의 텍스트로 나타나기도 한다.
<meta name="title" content="별별부동산 | 솔직하고 간편한 공인중개사 리뷰 서비스" />
웹페이지의 상세정보를 명시하는 태그로, title 태그보다 더 자세한 내용을 담을 수 있다.
구글은 description 태그의 정보가 페이지를 잘 설명한다면 이를 이용해 스니펫(검색 결과 설명 또는 요약)을 만들기도 한다.
구글의 우수한 메타 설명을 만들기 위한 권장사항의 예시는 다음과 같다.
<meta name="description" content="재봉틀로 옷을 만들 때 필요한 모든 제품이 준비되어 있습니다. 영업 시간: 월요일~금요일, 오후 8~5시, 위치: 패션 디스트릭트">
<meta name="description" content="작은 마을인 후빌을 뒤흔든 사건이 발생했습니다. 이 지역에 거주하는 한 노인이 중요한 행사가 있기 전날 밤 모든 사람들의 선물을 훔칩니다. 이 사건에 관한 실시간 업데이트를 기대해 주세요.">
<meta name="description" content="이 완벽 가이드와 함께 1시간 이내에 달걀을 요리하는 모든 방법을 알아보세요. 오버이지, 서니 사이드업, 삶기, 수란 등 모든 방식을 다룹니다.">
<meta name="description" content="손글씨를 자동으로 교정해 주는 셀프샤프닝 방식의 샤프펜슬입니다. 2B 자동 충전 리드가 포함됩니다. 빈티지 핑크와 스쿨버스 옐로우 색상이 있습니다. 50개 이상 주문하고 무료 배송 혜택을 받으세요.">
Open Graph는 웹페이지를 링크로 공유할 때 콘텐츠 미리보기에 표시되는 메타 태그다.
og:site_name
웹사이트 이름og:title
: 웹페이지 제목og:description
: 웹페이지 상세 설명og:type
: 웹페이지 유형og:url
: 웹페이지 주소og:image
: 웹페이지 썸네일 (권장크기: 1200x630, 2:1)og:image:alt
: 웹페이지 썸네일 설명og:type
: 웹페이지 유형Next.js는 MPA(Multi Page Application)이다.
따라서 각 페이지마다 HTML을 생성하고 <head>
내에 페이지에 맞는 메타태그를 동적으로 주입할 수 있으므로 SEO 최적화에 적합하다.
document와 app 모두 공통으로 적용되는 공통점이 있다.
하지만 document는 무조건 모든 헤더에 포함되고, app은 페이지별로 적용되므로 중복을 제거할 수 있다.
따라서 app 컴포넌트에 기본 meta 태그를 넣고, 페이지별로 필요한 meta 태그를 추가했다.
같은 meta 태그를 덮어쓰려면 key 속성을 사용하면 된다.
// _app.tsx
const MyApp: AppType = ({ Component, pageProps }) => {
const shareData = {
title: '별별부동산 | 솔직하고 간편한 공인중개사 리뷰 서비스',
description: '이제 별별부동산에서 리뷰 검색하고, 안전하게 거래하세요!',
}
return (
<>
<Head>
<title>{shareData.title}</title>
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="title" content={shareData.title} key="title" />
<meta name="description" content={shareData.description} key="description" />
<meta property="og:title" content={shareData.title} key="og_title" />
<meta property="og:description" content={shareData.description} key="og_description" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="별별부동산" key="og_site_name" />
<meta property="og:image" content="/thumbnail.png" key="og_image" />
<meta property="og:image:alt" content="starstaragent_logo" key="og_image_alt" />
<meta property="og:url" content={process.env.NEXT_PUBLIC_API + pathname} key="og_url" />
<link rel="icon" href="/favicon.ico" />
</Head>
(...)
</>
// pages/detail.tsx
export default function Detail = () => {
(...)
const shareData = {
title: `${name} | 별별부동산`,
text: `${agency.address_short} ${agency.name}, ${shareText} 등의 정보를 확인해보세요`,
image,
}
return (
<>
<Head>
<title>{shareData.title}</title>
<meta name="title" content={shareData.title} key="title" />
<meta name="description" content={shareData.text} key="description" />
<meta property="og:title" content={shareData.title} key="og_title" />
<meta property="og:description" content={shareData.text} key="og_description" />
{image && <meta property="og:image" content={shareData.image} key="og_image" />}
<meta property="og:image:alt" content="agent_image" key="og_image_alt" />
</Head>
</>
)
}
${process.env.NEXT_PUBLIC_API}/signup
로 적용된다.