Astro 블로그에 AI 작성 배지 추가하기(프론트매터 스위치 패턴)

#Astro #TypeScript #Frontend #UI-Design

요즘 개발 블로그를 운영하다 보면 AI의 도움을 받아 글의 초안을 작성하거나 코드를 다듬는 경우가 많다. 투명성을 위해 포스트 하단에 “AI의 도움을 받았다”는 문구를 넣기로 했는데, 여기서 한 가지 고민이 생겼다. “모든 글이 AI의 도움을 받는 것은 아닌데, 어떻게 관리해야 할까?”

이 문제를 해결하기 위해 프론트매터(Frontmatter) 를 일종의 스위치처럼 사용하는 방식을 도입했다. 이를 통해 마크다운 파일 상단에서 손쉽게 배지의 표시 여부를 제어할 수 있다.

1. Zod를 활용한 프론트매터 스위치 정의

Astro는 src/content/config.ts 파일에서 Zod 를 통해 데이터의 타입을 엄격하게 관리할 수 있다. 여기에 showAiBadge라는 boolean 타입의 속성을 추가했다.

핵심은 .default(true)를 설정하는 것이다. 이렇게 하면 마크다운에 아무것도 적지 않아도 기본적으로 배지가 나타나며, 100% 직접 쓴 글에서만 명시적으로 false를 주어 숨길 수 있다.

// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const blogCollection = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    description: z.string(),
    pubDate: z.date(),
    tags: z.array(z.string()).optional(),
    category: z.enum(['Devlog', 'Blog-Build']).default('Devlog'),
    
    // 배지 표시 여부를 결정하는 스위치 (기본값: true)
    showAiBadge: z.boolean().default(true), 
  }),
});

export const collections = {
  blog: blogCollection,
};

2. 공통 문구 컴포넌트 만들기

매번 똑같은 긴 HTML 코드를 마크다운에 적는 것은 비효율적이므로, 문구를 렌더링하는 전용 컴포넌트인 AiComment.astro 를 만들었다.

---
// src/components/AiComment.astro
---
<div class="mt-10 flex justify-center">
  <p class="inline-block px-6 py-3 text-sm bg-gray-100 text-campfire-red dark:bg-zinc-700 dark:text-campfire-yellow-200 rounded-md italic">
    이 포스팅은 AI의 도움을 받아 초안을 작성하고, 직접 검수 및 편집한 글입니다.
  </p>
</div>

3. 포스트 레이아웃에 조건부 렌더링 적용

이제 포스트를 화면에 뿌려주는 동적 라우팅 페이지([...slug].astro) 또는 레이아웃 파일에서 이 스위치를 작동시킬 차례다. 포스트 데이터(post.data)에서 showAiBadge 값을 꺼내와, 조건이 참일 때만 컴포넌트를 보여주도록 작성했다.

---
// src/pages/blog/[...slug].astro
import { getCollection } from 'astro:content';
import Layout from '../../layouts/Layout.astro';
import AiComment from '../../components/AiComment.astro';

export async function getStaticPaths() {
  const posts = await getCollection('blog');
  return posts.map((post) => ({
    params: { slug: post.slug },
    props: { post },
  }));
}

const { post } = Astro.props;
const { Content } = await post.render();

// 프론트매터에서 스위치 값 가져오기
const { showAiBadge } = post.data; 
---

<Layout title={post.data.title}>
  <main class="w-full max-w-3xl shrink-0 pb-16">
    <h1>{post.data.title}</h1>
    <Content />

    {/* 스위치가 켜져 있을(true) 때만 렌더링 */}
    {showAiBadge && <AiComment />}
  </main>
</Layout>

프론트매터 스위치 방식은 정말 직관적이다. 개발자는 마크다운 상단에 showAiBadge: false 라고 단 한 줄만 적으면, 불필요한 레이아웃 수정을 피하고 콘텐츠 작성에만 집중할 수 있다.

앞으로도 반복되는 UI 요소가 있다면, 이러한 방식으로 프론트매터를 제어판처럼 활용해 보아야겠다.

이 포스팅은 AI의 도움을 받아 초안을 작성하고, 직접 검수 및 편집한 글입니다.