아티클 페이지 Open Graph 메타 분리로 SEO 파이프라인 완성
목차
Base.astro에 article 전용 메타 props를 뚫고, [slug] 페이지에서 그걸 내려보내는 작업을 했다.
작업 자체는 심플해 보이지만, SEO 파이프라인을 제대로 닫는 작업이라 짚고 넘어갈 게 꽤 있다.
왜 지금 이 작업이었나
블로그나 콘텐츠 사이트에서 Base 레이아웃은 모든 페이지가 공유하는 껍데기다. 문제는 공용 껍데기이다 보니 처음엔 최소한의 메타만 박아두는 경우가 많다 — <title>, <meta name="description"> 정도.
그런데 아티클 페이지는 요구사항이 다르다. Open Graph의 og:type은 article이어야 하고, article:published_time, article:author 같은 article 전용 프로퍼티도 있어야 소셜 카드나 검색 엔진이 콘텐츠를 제대로 읽는다. 이걸 Base에 그냥 때려박으면 블로그 홈이나 태그 페이지 같은 non-article 페이지에도 엉뚱한 메타가 딸려 나간다.
그래서 나온 패턴이 "Base는 공통 뼈대만, article 전용 props는 선택적으로 받아서 조건부 렌더링"이다. 이번 커밋이 딱 그 구조를 만든 것.
작업 내용
변경된 파일은 두 개.
| 파일 | 역할 | 이번 변경 |
|---|---|---|
src/layouts/Base.astro |
전역 레이아웃, <head> 관리 |
article 메타 props 인터페이스 추가 + 조건부 렌더링 |
src/pages/t/[slug]/index.astro |
개별 아티클 페이지 | Base에 article 메타 데이터 전달 |
Base.astro 쪽에서 props 인터페이스를 열어줬을 거고, 대략 이런 패턴이다.
---
interface Props {
title: string;
description?: string;
// article 전용
articleMeta?: {
publishedTime?: string;
author?: string;
tags?: string[];
};
}
const { title, description, articleMeta } = Astro.props;
---
<head>
<title>{title}</title>
<meta name="description" content={description} />
{articleMeta && (
<>
<meta property="og:type" content="article" />
<meta property="article:published_time" content={articleMeta.publishedTime} />
<meta property="article:author" content={articleMeta.author} />
</>
)}
</head>
articleMeta가 없으면 og:type도 기본값(보통 website)으로 내려가고, article 전용 태그는 아예 렌더 안 된다. 페이지 타입에 따라 <head>가 달라지는 구조가 이렇게 잡힌다.
[slug]/index.astro에서는 frontmatter나 content collection에서 긁어온 데이터를 articleMeta에 조립해서 Base로 던지는 식.
---
const { slug } = Astro.params;
const post = await getEntry('posts', slug);
const articleMeta = {
publishedTime: post.data.pubDate.toISOString(),
author: post.data.author,
tags: post.data.tags,
};
---
<Base title={post.data.title} description={post.data.description} articleMeta={articleMeta}>
<!-- 본문 -->
</Base>
이 구조에서 챙겨야 할 것들
Astro 기반 콘텐츠 사이트에서 이런 작업을 할 때 몇 가지 포인트가 있다.
- props optional 처리 —
articleMeta를 optional로 두면 기존 페이지들은 아무것도 안 바꿔도 된다. 새 props 추가했다고 Base 쓰는 모든 페이지 손댈 필요가 없음. - og:type 기본값 — article 메타가 없을 때
og:type을website로 fallback하는 거 명시적으로 처리하는 게 깔끔하다. 소셜 미리보기 디버거에서og:type빠진 페이지는 경고 뜨기도 함. - 날짜 포맷 —
article:published_time은 ISO 8601 형식이어야 한다.pubDate.toISOString()같이 명시적으로 변환하지 않으면 소셜 크롤러가 못 읽는 경우 생김. - 태그 → article:tag —
tags배열이 있으면article:tag를 여러 개 찍어야 한다. 하나로 합쳐서 넣으면 의미 없음.
회고
Base 레이아웃 처음 짤 때 article 메타까지 미리 설계해두는 팀이 많지 않다. 초반엔 페이지 뜨는 것 자체에 집중하니까. 그러다 나중에 "소셜 공유했는데 카드가 이상해요" 이슈가 들어오면 그제야 <head> 뜯게 되는데, 그 시점에 이미 페이지가 많아져 있으면 수정 범위가 커진다.
이번처럼 props 인터페이스를 잘 잡아두면 나중에 article:section이나 article:modified_time 같은 필드 추가해도 Base만 건드리면 된다. [slug] 페이지에서 데이터만 얹어주면 끝.
SEO 작업이 "나중에 하면 되지" 하고 밀리기 쉬운 작업인데, 콘텐츠가 쌓이기 전에 파이프라인 잡아두는 게 훨씬 낫다는 걸 매번 느낀다.
다음은 article:tag 여러 개 렌더 처리랑 og:image 동적 생성 쪽 볼 것 같다.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.