Astro Layout, OGP, GItHub Actions 30초 배포
GitHub Actions에서 push하면 30초 이내 배포됩니다. 이보다 단순한 CI/CD는 없습니다.
[Tip] CI/CD란?
CI/CD는 소프트웨어 개발에서 코드 변경 이후의 빌드, 테스트, 배포 과정을 자동화하는 개발 및 운영 방식이다.
CI(Continuous Integration, 지속적 통합)는 개발자가 코드를 저장소에 올릴 때마다 자동으로 빌드와 테스트를 실행해 오류를 빠르게 발견하고 코드 품질을 유지한다. CD(Continuous Delivery/Deployment)는 검증된 코드를 스테이징 또는 운영 환경에 자동으로 배포해 서비스 업데이트를 빠르고 안정적으로 진행하도록 돕는다. 이를 통해 개발 속도와 배포 안정성을 동시에 높일 수 있다.
이 장에서는 사이트의 골격이 되는 레이아웃, 컴포넌트, OGP 설정을 구현합니다.
특히 Layout.astro는 이후 구현할 다음 기능들의 기반이 되는 핵심 파일입니다.
메타 태그
JSON-LD 구조화 데이터
canonical URL
마크다운(Markdown) 엔드포인트 힌트(URL.md)
따라서 처음부터 확장 가능한 구조로 설계하는 것이 중요합니다.
즉 모든 페이지는 다음 구조를 따릅니다.
Layout.astro → 메타태그 / JSON-LD / canonical → 각 페이지 (*.astro)
Layout.astro는 모든 페이지에서 공통으로 사용되는 사이트의 기본 레이아웃입니다.
각 페이지는 이 레이아웃을 통해 <head> 영역의 메타 정보와 공통 구조를 상속받습니다.
핵심 포인트
Layout.astro는 디자인 레이아웃이 아니라 SEO와 LLMO의 메타 인프라입니다.
즉 이 파일은 단순히 페이지 레이아웃을 구성하는 역할을 넘어서,
검색 엔진과 AI 크롤러가 사이트를 이해하는 데 필요한 메타 정보의 중심 역할을 합니다.
여기에는 다음과 같은 요소들이 포함됩니다.
메타 태그
OGP(Open Graph)
Twitter Card
canonical URL
Markdown 엔드포인트 힌트
JSON-LD 구조화 데이터
따라서 Layout.astro를 올바르게 설계하면 모든 페이지가 자동으로 SEO와 LLMO 최적화 구조를 공유하게 됩니다.
특히 한국 환경에서는 다음 설정도 중요합니다.
lang="ko"
og:locale="ko_KR"
네이버 서치어드바이저 인증 태그
Layout.astro 기본 구조
---
interface Props {
title: string;
description?: string;
ogImage?: string;
}
const {
title,
description = '기본 설명문',
ogImage = 'og-image.jpg'
} = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const base = import.meta.env.BASE_URL.endsWith('/')
? import.meta.env.BASE_URL
: `${import.meta.env.BASE_URL}/`;
---
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description} />
<link rel="canonical" href={canonicalURL.href} />
<!-- 네이버 서치어드바이저 인증 (실제 코드로 교체) -->
<!-- <meta name="naver-site-verification" content="YOUR_CODE" /> -->
<!-- OGP — 구글·네이버·카카오톡 미리보기 공통 -->
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:type" content="website" />
<meta property="og:url" content={canonicalURL.href} />
<meta property="og:site_name" content="사이트명" />
<meta property="og:locale" content="ko_KR" />
<meta property="og:image" content={`${Astro.site}${base.slice(1)}images/${ogImage}`} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<!-- Twitter Card (X) -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content={`${Astro.site}${base.slice(1)}images/${ogImage}`} />
<meta name="twitter:site" content="@your_account" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<!-- AI 크롤러 힌트 — Markdown 버전 존재를 명시 -->
<link
rel="alternate"
type="text/markdown"
href={`${canonicalURL.href}.md`}
title="Markdown 버전"
/>
<!-- JSON-LD (제6장에서 상세 구현) -->
<script type="application/ld+json" set:html={JSON.stringify([...])} />
<title>{title}</title>
</head>
<body>
<slot />
</body>
</html>
코드 설명
각 페이지의 .astro 파일에서는 Layout 컴포넌트에 페이지별 메타 정보를 props로 전달합니다.
이 방식의 장점은 다음과 같습니다.
모든 페이지가 공통 메타 구조(Layout)를 공유
페이지마다 개별 OGP 이미지 설정 가능
SNS 공유 시 페이지 특성에 맞는 미리보기 생성
예를 들어 ai-workflow.astro 페이지는 다음과 같이 설정합니다.
<!—ai-workflow.astro -->
<Layout
title="AI-Marketing - AI기반 마케팅 자동화 워크플로우"
description="AI-Marketing는 마케팅 Agent Skills를..."
ogImage="ai-marketing.jpg"
지금 바로 작가의 멤버십 구독자가 되어
멤버십 특별 연재 콘텐츠를 모두 만나 보세요.
오직 멤버십 구독자만 볼 수 있는,
이 작가의 특별 연재 콘텐츠