Nuxt 3 Content로 Git 기반 웹사이트 구축하기
James Reed
Infrastructure Engineer · Leapcell

헤드리스 콘텐츠 관리의 부상
빠르게 진화하는 웹 개발 환경에서 유연하고 효율적인 콘텐츠 관리 솔루션에 대한 수요는 계속 증가하고 있습니다. 전통적인 콘텐츠 관리 시스템(CMS)은 데이터베이스, 복잡한 인터페이스 및 광범위한 서버 구성을 필요로 하는 상당한 오버헤드를 종종 동반합니다. 속도, 단순성 및 버전 관리를 우선시하는 많은 개발자 및 프로젝트의 경우, 더 가볍고 통합된 접근 방식이 매우 바람직합니다. 여기서 "Git 기반 콘텐츠"라는 개념이 빛을 발합니다. Git과 같은 버전 관리 시스템과 Markdown과 같은 일반 텍스트 형식을 활용함으로써 개발자는 웹사이트 콘텐츠를 관리하기 위한 간소화된 워크플로를 달성할 수 있습니다. 이 접근 방식은 콘텐츠 생성 및 업데이트를 단순화할 뿐만 아니라 최신 프런트엔드 프레임워크와도 원활하게 통합됩니다.
Vue.js를 위한 강력하고 직관적인 메타 프레임워크인 Nuxt 3는 고성능 웹 애플리케이션 구축을 위한 탁월한 도구 세트를 제공합니다. 많은 기능 중에서 Nuxt Content 모듈은 콘텐츠가 풍부한 웹사이트를 위한 게임 체인저로 두드러집니다. 이 모듈은 Markdown, YAML, CSV 및 JSON 파일을 쿼리 가능한 데이터 계층으로 우아하게 변환하여 전통적인 데이터베이스 없이 콘텐츠를 표시하고 관리하기 매우 쉽게 만듭니다. Git 기반 콘텐츠의 원칙과 결합하면 Nuxt 3 Content는 개발자가 유지 관리가 용이하고 버전이 관리되며 성능이 뛰어난 웹사이트를 구축할 수 있도록 지원합니다. 이 기사는 Git 저장소 내의 Markdown 파일로 완전히 관리되는 웹사이트를 구축하기 위해 Nuxt 3 Content 모듈의 실질적인 구현을 탐구하며, 강력하고 개발자 친화적인 콘텐츠 관리 솔루션을 제공합니다.
핵심 개념 이해
구현에 들어가기 전에 논의의 중추를 형성하는 몇 가지 핵심 용어를 명확히 해 보겠습니다.
Nuxt 3: Vue 3, Nitropack 및 Vite를 기반으로 구축된 풀스택 웹 프레임워크입니다. 서버 측 렌더링(SSR), 정적 사이트 생성(SSG)을 단순화하고 고성능 웹 애플리케이션 구축을 위한 의견이 반영된 구조를 제공합니다.
Nuxt Content 모듈: Markdown, YAML, CSV 및 JSON과 같은 다양한 형식으로 콘텐츠를 작성하고 강력한 API를 통해 액세스할 수 있도록 하는 공식 Nuxt 모듈입니다. 이 모듈은 이러한 파일을 자동으로 구문 분석하고 콘텐츠 쿼리 빌더를 제공하여 콘텐츠를 쉽게 가져오고 표시할 수 있습니다.
Markdown: 일반 텍스트 편집기를 사용하여 서식이 있는 텍스트를 만드는 데 사용되는 경량 마크업 언어입니다. 단순성과 가독성으로 인해 콘텐츠 생성 및 버전 관리에 이상적입니다.
Git 기반 콘텐츠: 모든 웹사이트 콘텐츠가 Git 저장소 내의 일반 텍스트 파일(예: Markdown)로 저장되는 콘텐츠 관리 전략입니다. 콘텐츠 변경 사항은 표준 Git 워크플로를 사용하여 추적, 버전 관리 및 공동 작업합니다. 이를 통해 콘텐츠에 대해 별도의 데이터베이스나 CMS 인터페이스가 필요하지 않습니다.
Nuxt 3 Content로 Git 기반 웹사이트 구축하기
Nuxt 3 Content를 사용한 Git 기반 웹사이트의 기본 원칙은 프로젝트 리포지토리의 Markdown 파일을 웹사이트 콘텐츠의 단일 진실 공급원으로 취급하는 것입니다. 그런 다음 Nuxt Content는 이러한 파일을 구문 분석하여 Vue 구성 요소에서 사용할 수 있도록 합니다.
Nuxt 3 프로젝트 설정
먼저 아직 없는 경우 새 Nuxt 3 프로젝트를 만듭니다:
npx nuxi init git-content-blog cd git-content-blog npm install
Nuxt Content 모듈 설치
다음으로 Nuxt Content 모듈을 설치합니다:
npm install --save-dev @nuxt/content
그런 다음 nuxt.config.ts
에 추가합니다:
// nuxt.config.ts export default defineNuxtConfig({ modules: ['@nuxt/content'] })
콘텐츠 구조화
Nuxt Content 모듈은 콘텐츠 파일이 기본적으로 content/
라는 특정 디렉터리에 있는지 확인합니다. 이 디렉터리 내에서 Markdown 파일을 하위 디렉터리로 구성할 수 있으며, 이는 URL을 결정하게 됩니다.
블로그 게시물에 대한 몇 가지 예제 콘텐츠를 만들어 보겠습니다:
content/
├── blog/
│ ├── first-post.md
│ ├── second-post.md
│ └── third-post.md
└── about.md
content/blog/first-post.md
:
--- title: My First Blog Post date: 2023-10-26 author: John Doe description: This is my very first blog post exploring the world of Nuxt 3 and Git-driven content. --- ## Welcome to My Blog! This post marks the beginning of an exciting journey into web development. I'm thrilled to share my thoughts and experiences with you. ### What is Markdown? Markdown is a lightweight markup language that allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid HTML.
content/blog/second-post.md
:
--- title: Understanding Nuxt Content Queries date: 2023-11-01 author: Jane Smith description: A deep dive into how to effectively query content using the Nuxt Content module. --- ## Powerful Content Queries Nuxt Content provides a flexible API to fetch and filter your content. You can query based on file path, frontmatter properties, and more. ### Example Query ```vue <script setup> const { data: posts } = await useAsyncData('blog-posts', () => queryContent('blog') .limit(5) .sort({ date: -1 }) .find() ); </script>
**`content/about.md`:**
```markdown
---
title: About Us
layout: page
---
## Our Story
We are a passionate team dedicated to building amazing web experiences with modern technologies like Nuxt 3.
### Our Mission
To empower developers with accessible and efficient tools for content management.
콘텐츠 가져오기 및 표시
Nuxt Content는 queryContent()
및 useAsyncData()
(useFetch()
는 클라이언트 측 가져오기용)를 사용하여 콘텐츠를 가져오는 것을 매우 간단하게 만듭니다.
pages/index.vue
(모든 블로그 게시물 나열):
<template> <div class="container mx-auto px-4 py-8"> <h1 class="text-4xl font-bold mb-8">My Git-Powered Blog</h1> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> <NuxtLink v-for="post in posts" :key="post._path" :to="post._path" class="block p-6 border rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300"> <h2 class="text-2xl font-bold mb-2">{{ post.title }}</h2> <p class="text-gray-600 text-sm mb-4">By {{ post.author }} on {{ new Date(post.date).toLocaleDateString() }}</p> <p class="text-gray-700">{{ post.description }}</p> </NuxtLink> </div> </div> </template> <script setup> const { data: posts } = await useAsyncData('blog-posts', () => queryContent('blog') .sort({ date: -1 }) // Sort by date in descending order .find() ); </script> <style> /* Basic Tailwind CSS setup for demonstration */ body { font-family: sans-serif; } </style>
pages/blog/[slug].vue
(단일 블로그 게시물 표시):
개별 블로그 게시물을 표시하려면 동적 라우팅을 사용합니다. 파일 이름의 [slug]
는 Nuxt에게 content/blog/
의 각 파일에 대한 경로를 만들도록 지시합니다.
<template> <div class="container mx-auto px-4 py-8 max-w-2xl"> <ContentDoc v-if="post" class="prose lg:prose-xl mx-auto"> <h1>{{ post.title }}</h1> <p class="text-gray-600 text-sm">By {{ post.author }} on {{ new Date(post.date).toLocaleDateString() }}</p> <ContentRenderer :value="post" /> </ContentDoc> <div v-else> <p>Post not found.</p> </div> </div> </template> <script setup> const route = useRoute(); const { data: post } = await useAsyncData(`blog-post-${route.params.slug}`, () => queryContent('blog', route.params.slug).findOne() ); </script> <style> /* Add some basic styling for the prose content */ .prose h1 { font-size: 2.5rem; margin-bottom: 1rem; } .prose h2 { font-size: 2rem; margin-top: 2rem; margin-bottom: 1rem; } .prose p { margin-bottom: 1rem; line-height: 1.6; } /* You would typically use a typography plugin like @tailwindcss/typography here */ </style>
pages/about.vue
(정보 페이지 표시):
<template> <div class="container mx-auto px-4 py-8 max-w-2xl"> <ContentDoc v-if="page" class="prose lg:prose-xl mx-auto"> <h1>{{ page.title }}</h1> <ContentRenderer :value="page" /> </ContentDoc> <div v-else> <p>About page not found.</p> </div> </div> </template> <script setup> const { data: page } = await useAsyncData('about-page', () => queryContent('about').findOne() ); </script>
Git 통합 및 워크플로
"Git 기반" 측면은 자연스럽게 발생합니다. content/
디렉터리는 단순히 Git 리포지토리의 일부입니다.
- 콘텐츠 생성/편집: 콘텐츠 작성자(또는 개발자)는
content/
디렉터리에서 Markdown 파일을 직접 편집합니다. - 버전 관리: 모든 변경 사항은 Git에 커밋되어 완전한 기록, 롤백 기능 및 공동 작업 워크플로를 제공합니다.
- 배포: 메인 브랜치가 업데이트되면(예: 풀 리퀘스트 병합을 통해), CI/CD 파이프라인이 Nuxt 애플리케이션의 다시 빌드 및 다시 배포를 트리거합니다. 빌드 프로세스 중에 Nuxt Content는 최신 Markdown 파일을 구문 분석합니다.
이 워크플로는 콘텐츠 관리가 개발 워크플로와 완전히 통합되어 별도의 CMS 인터페이스가 필요 없다는 것을 의미합니다.
고급 Nuxt Content 기능
ContentRenderer
및ContentSlot
: 이러한 구성 요소를 사용하면 Vue 구성 요소에 Markdown 콘텐츠를 직접 렌더링할 수 있습니다.ContentRenderer
는 구문 분석된 Markdown을 HTML로 자동 렌더링하는 반면ContentSlot
은 사용자 정의 구문을 통해 Vue 구성 요소를 Markdown에 직접 삽입할 수 있습니다.- 쿼리 필터링 및 정렬:
limit()
및sort()
외에도 다양한 조건으로 콘텐츠를 필터링할 수 있습니다. 예를 들어queryContent().where({ layout: 'post' }).find()
. - 정적 사이트 생성(SSG): 최대 성능과 더 낮은 호스팅 비용을 위해 Nuxt 애플리케이션을 정적 사이트로 빌드합니다. Nuxt Content는 빌드 프로세스 중에 모든 페이지를 생성하여 Markdown 콘텐츠를 HTML 파일로 미리 렌더링합니다.
// nuxt.config.ts export default defineNuxtConfig({ ssr: true, // Enable SSR for pre-rendering // Generate all routes that Nuxt Content finds nitro: { prerender: { routes: ['/'] // Ensure the index route is prerendered } } })
콘텐츠 모듈에서 동적 경로를 생성하려면 nitro
모듈과 함께 _src/routes.ts
또는 _src/hooks.ts
를 사용합니다.
Nuxt 3의 경우 Content 모듈이 SSG 빌드 중에 콘텐츠 파일에 대한 경로 생성을 자동으로 처리합니다. 특정 가장자리 사례가 없는 한 콘텐츠 생성 경로에 대해 명시적인 prerender.routes
는 일반적으로 필요하지 않습니다.
Git 백업 콘텐츠의 단순성
Nuxt 3 Content 모듈은 Git 저장소에 저장된 Markdown 파일을 활용하여 웹사이트 콘텐츠를 관리하는 매우 강력하면서도 간단한 방법을 제공합니다. 이 접근 방식은 버전 관리, 공동 작업 및 간소화된 워크플로를 촉진하는 최신 개발 관행과 완벽하게 일치합니다. 핵심 개념을 이해하고 실질적인 구현 단계를 따르면 개발자는 콘텐츠 관리가 코드 관리만큼 효율적이고 안정적인 강력한 고성능 웹사이트를 구축할 수 있습니다.
본질적으로 Nuxt 3 Content는 Git 리포지토리를 완전한 기능을 갖춘 개발자 친화적인 CMS로 변환하여 콘텐츠가 번거로움 없이 관리되고 버전 관리되는 동안 훌륭한 사용자 경험을 구축하는 데 집중할 수 있도록 해줍니다.