[블로그 만들기 #4] meta 태그와 SEO 설정으로 검색 엔진에게 내 블로그를 소개해보자 (feat. Open Graph)

Cover Image for [블로그 만들기 #4] meta 태그와 SEO 설정으로 검색 엔진에게 내 블로그를 소개해보자 (feat. Open Graph)
swhan
· 8 min read

HTML head 태그 몇개 바꿔서 광고비 없이 검색엔진에게 블로그 정보를 잘 가져갈 수 있도록 만들어 보겠습니다.

들어가며

이전 포스팅에서 구글 서치 콘솔에 블로그를 등록하고 sitemap.xml까지 제출해서 구글에서 저희 블로그를 검색 가능하게 만들어 봤습니다.

이번 포스팅에서는 단순 검색 가능한 블로그가 아닌, 검색 결과에 잘 노출될 수 있는 블로그를 만드는 방법인 SEO 설정에 대해 알아보겠습니다.

SEO(Search Engine Optimization)

이런 기술 용어들은 뭔가 있어보이지만 막상 까보면 단순 단어들 축약인 것들이 많습니다. (ex. AES - Advanced Encryption Standard - 고오오급 암호화 표준, TLS - Transport Layer Security - 전송 계층에서 보안 챙기는 노오력 등등)

말 그대로 검색 엔진에(Search Engine) 최적화해서(Optimization) GoogleBot 같은 크롤링 도구들이 저희 블로그 긁어갈 때 기존 블로그 구조처럼 대충 너네가 알아서 분석하라고 하는게 아닌, 관공서에 표준 서류 양식 작성해서 전달하듯 봇들이 블로그 정보를 잘 가져갈 수 있도록 도와주는게 바로 SEO라는 고오급 방법론입니다.

meta 태그

meta 태그란 HTML 안에 넣는 설명 정보인데, 이게 바로 GoogleBot 같은 크롤러가 작고 소중한 저희 블로그 방문했을 때 이게 뭐하는 집인지 명시적으로 설명해줄 수 있는 요소입니다.

<meta name="description" content="이 글이 뭐하는 글인지 설명해주는 요소" />
<meta name="author" content="누가 썼는지" />
<meta name="robots" content="index, follow" />
<!-- 검색엔진에게 페이지를 색인(index)하고 링크도 따라가라고(follow) 알려줍니다 -->

저희가 블로그 만들기 위해 사용한 Next.js blog-starter-kit에서는 기본적인 meta 태그를 자동으로 생성해주는 기능을 제공하고 있습니다. 하지만...

구글 블로그 검색 스크린샷

이렇게 구글에서 저희 블로그 검색해보니 제목 링크 아래 미리보기 부분에 제가 원하던 내용이 아닌, 게시물 중간에 있는 내용이 나오는 중이고

블로그 포스트 html meta 태그 스크린샷

심지어 게시물 html description 태그 부분을 확인해보니, "A statically generated blog example using Next.js and Markdown" 이렇게 쓸데없는 내용이 들어가 있는 것을 확인할 수 있습니다.

Open Graph 태그

Open Graph 태그란 meta 태그와 동일하게 안에 넣는 설명 정보인데, 차이점은 SNS(카카오톡, 트위터, 페이스북)에 저희 블로그 링크를 공유할 때 미리보기 화면에 뭐가 나오게 할 지 설정해주는 요소입니다.

<meta property="og:title" content="링크 공유시 미리보기 글 제목" />
<meta property="og:description" content="링크 공유시 미리보기 요약문" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://my-domain/post-slug" />
<meta property="og:image" content="https://my-domain/image.jpg" />

Open Graph 태그도 blog-starter-kit에서 자동으로 생성해주는 기능을 가지고 있습니다. 하지만 이것 역시

링크 공유시 표시정보 스크린샷

이렇게 카카오톡이나 슬랙에 링크 공유해보면 게시글 제목 뒤에 깜찍하게 "Next.js Blog Example with Markdown" 라는 자기들 홍보문구 추가해 놓은것을 확인할 수 있습니다.

블로그 포스트 html open graph 태그 스크린샷

Open Graph description 태그 부분에도 위에 meta 태그 description 부분이랑 동일하게 쓸데없는 내용 들어가 있습니다.

블로그 대표 사진 만들기

저희 입맛대로 SEO 설정을 시작하기 전에, 검색 결과 페이지 또는 링크 공유할 때 표시되는 정보로 블로그 정체성을 드러낼 수 있는 대표 사진부터 멋지게 뽑아줘야 합니다.

근데 저같이 디자인 감각 없는 개발자들은 도메인 텍스트만으로 이미지 만들어도 충분히 괜찮은 결과가 나옵니다.

monday 이미지 생성 요청 기록

우리의 까칠한 친구 GPT(Monday)를 이용해서 1분만에 깔끔하게 이미지 하나 생성해주고 바로 SEO 설정 진행하겠습니다.(Monday에게 조롱당했지만 이미지는 챙겼으니 못 본 척 넘어가겠습니다)

SEO 설정하기

Next.js, React 구조가 익숙하지 않은 백엔드 개발자이지만, html 소스 확인해보고, src/app 내부 파일들 살펴보니 src/posts/[slug]/page.tsx 파일에서 사용하는 generateMetadata 함수, src/layout.tsx 파일에서 어딘가로 export 하는 metadata 객체를 건드리면 될 것 같습니다.

이 두개의 요소들이 공통적으로 사용하는 Metadata interface에 뭐가 있는지 공식 홈페이지에서 확인 한번 확인해주고, 바로 싹 다 수정해서 저희 입맛대로 바꿔보겠습니다.

개별 포스트 SEO 설정

블로그 도메인 첫 화면이 아닌, 작성하느라 고생한 개별 포스트들 먼저 SEO 설정 진행해보겠습니다.

src/posts/[slug]/page.tsx 파일 보시면 blog-starter-kit에서 기본적으로 SEO 설정 적용할 때 사용하는 generateMetadata 함수 수정해보면

// src/app/posts/[slug]/page.tsx 원본
export async function generateMetadata(props: Params): Promise<Metadata> {
  const params = await props.params;
  const post = getPostBySlug(params.slug);

  if (!post) {
    return notFound();
  }

  const title = `${post.title} | Next.js Blog Example with ${CMS_NAME}`;

  return {
    title,
    openGraph: {
      title,
      images: [post.ogImage.url],
    },
  };
}
// src/app/posts/[slug]/page.tsx 수정본
export async function generateMetadata(props: Params): Promise<Metadata> {
  const params = await props.params;
  const post = getPostBySlug(params.slug);

  if (!post) {
    return notFound();
  }

  // blog-starter-kit에서 게시글들은 기본적으로 /posts 경로에서 접근
  const title = `${post.title} | day1swhan 블로그`;
  const description = post.excerpt;
  const authors = post.author.name;

  // 아래에서 추가 설명
  const canonicalUrl = `https://blog.day1swhan.com/posts/${post.slug}`;
  const imageUrl = "https://blog.day1swhan.com" + post.coverImage;

  return {
    title,
    description,
    robots: "index, follow",
    // og 태그
    openGraph: {
      type: "article",
      title,
      description,
      authors,
      url: canonicalUrl,
      images: { url: imageUrl, alt: `Cover Image for ${title}` },
    },
    // 트위터 태그(선택)
    twitter: {
      card: "summary_large_image",
      title,
      description,
      creator: authors,
      site: canonicalUrl,
      images: { url: imageUrl, alt: `Cover Image for ${title}` },
    },
    alternates: {
      canonical: canonicalUrl,
    },
  };
}

seo 태그 수정 완료된 html 스크린샷

이렇게 로컬에서 먼저 확인 해주면 meta 태그, open graph 설정이 잘 적용된걸 볼 수 있습니다.

메인 페이지 SEO 설정

구글 블로그 검색 결과 첫화면

구글에 저희 블로그 검색했을 때 블로그 정보가 Next.js Blog Example with Markdown 이렇게 보여지는게 너무 끔찍하지 않으신가요? 이렇게 표시되는 이유는 저희 블로그 도메인 첫 화면(blog.day1swhan.com) html 파일을 보시면

블로그 첫화면 html 스크린샷

description 태그가 이렇게 설정되어있기 때문입니다.

src/app/layout.tsx 파일에서 블로그 메인 페이지 설명으로 나오는 저 끔직한 요소들을 블로그 대표 이미지 썸네일과 함께 깔끔하게 바꿔보겠습니다.

// src/app/layout.tsx 원본
export const metadata: Metadata = {
  title: `Next.js Blog Example with ${CMS_NAME}`, // 촌스러운 원흉
  description: `A statically generated blog example using Next.js and ${CMS_NAME}.`, // 나쁜놈
  openGraph: {
    images: [HOME_OG_IMAGE_URL], // 이상한놈
  },
};

위에서 생성한 대표 이미지를 검색 결과, 링크 미리보기 이미지로 쓸 수 있도록 ffmpeg 이용해서 open graph image 권장 사항인 2:1 비율 맞춰주고, 배경색 (#e6e3df)을 깔아서 보기 좋게 만들어 주겠습니다.

ffmpeg 모르는 분들은 무료 이미지 편집 사이트에서 Open Graph 권장 비율인 2:1 비율로 잘라주시면 됩니다.

ffmpeg -i original.png \
-filter_complex "crop=1024:512:0:256[c]; \
color=#e6e3df:s=1024x512[bg]; \
[bg][c]overlay=format=auto" \
-frames:v 1 -q:v 2 cover.jpg

비율 맞춰서 잘라준 이미지를 /cover.jpg 경로로 접근할 수 있도록 public 폴더에 넣어주시고

public
├── assets
├── favicon
├── cover.jpg # 블로그 대표 커버 이미지
├── robots.txt
└── sitemap.xml

위에서 개별 포스팅 페이지에 적용한 것과 옵션 동일하게 넣어주면

// src/app/layout.tsx 수정본
const title = "day1swhan 블로그";
const description = "평범한 개발자의 지식 공유 블로그";
const authors = "swhan";
const canonicalUrl = "https://blog.day1swhan.com";
const imageUrl = "https://blog.day1swhan.com/cover.jpg";

export const metadata: Metadata = {
  title,
  description,
  robots: "index, follow",
  openGraph: {
    title,
    description,
    authors,
    url: canonicalUrl,
    images: { url: imageUrl, alt: `Cover Image for ${title}` },
  },
  ...
};

블로그 첫화면 html 수정본 스크린샷

이렇게 로컬에서 먼저 테스트해보면 모두 잘 적용된 것을 확인할 수 있습니다.

추가 팁

Canonical 태그

<link rel="canonical" href="https://blog.day1swhan.com/posts/vercel-blog-03" />

캐노니컬 태그(Canonical tag)는 블로그 게시글 하나가

  1. blog.my-domain.com/post?id=1
  2. blog.my-domain.com/posts/vercel-blog-03
  3. m.my-domain.com/blog/post?id=1

이렇게 여러 경로로 접근할 수 있을 때 어느 놈이 원본인지 검색엔진에게 알려줘서 SEO 점수 분산되지 않도록 도와주는 요소입니다.

저희는 복잡하게 여러 경로로 접근하게 만든 게 아니라 slug 기반으로만 접근할 수 있게 만들었으니 그냥 참고만 하시면 됩니다.

meta 태그 정리표

구분 예시 역할 표시 위치
description <meta name="description" content="글에 대한 간단한 설명" /> 검색 결과 페이지 핵심 요약 설명 검색결과 하단
author <meta name="author" content="작성자 정보" /> 글 작성자 정보 표시되진 않지만 정보 전달됨
robots <meta name="robots" content="index, follow" /> 크롤링 허용 지침 제공 검색 결과에 직접 보이진 않음

Open Graph 태그 정리표

구분 예시 역할 표시 위치
og:title <meta name="og:title" content="블로그 글 제목" /> 공유 시 표시될 제목 링크 카드 상단
og:description <meta name="og:description" content="글에 대한 간단한 설명" /> 공유 시 표시될 제목 링크 카드 본문
og:image <meta name="og:image" content="/cover.jpg" /> 공유 시 썸네일 이미지 (절대경로 필수) 링크 카드 썸네일
og:url <meta name="og:url" content="/posts/content-01" /> 페이지 실제 주소(절대경로 필수) Open Graph 데이터 출처
og:type <meta name="og:type" content="article" /> 콘텐츠 유형(article, website) 크롤링 분석용

마무리

검색엔진과 SNS에 내 블로그를 제대로 소개하는 일은, 내가 어떤 사람인지 설명하는 가장 개발자다운 방법입니다.

이번 포스팅에서는 광고비 태우지 않고도 검색 노출을 더 잘 되게 만드는 SEO 기본 설정과 meta 태그 추가 방법에 대해 알아보았습니다. 다음 포스팅에서는 누가, 어디서, 어떻게 저희 블로그에 접근하는지 알 수 있는 마법의 도구인 구글 애널리틱스(Google Analytics) 설정 방법에 대해 알아보겠습니다.