Astro Vibe Coding 가이드
Astro로 Vibe Coding을 활용하는 방법을 배웁니다. 콘텐츠 중심의 현대적 웹 프레임워크를 AI로 구현해보세요.
개요
Astro는 "콘텐츠 우선" 웹 프레임워크로, 기본적으로 정적 사이트를 생성합니다. Islands 아키텍처로 필요한 영역만 JavaScript로 렌더링하여 최고의 성능을 제공합니다.
- Zero JS 기본: JavaScript 없이 HTML만 생성, Lighthouse 100점 달성 용이
- Islands: 필요한 컴포넌트만 interactive로 hydrate
- 다양한 UI 프레임워크: React, Vue, Svelte 등 혼용 가능
- Content Collections: Zod 기반 타입 안전 콘텐츠 관리
- View Transitions: 네이티브 페이지 전환
- 이미지 최적화: WebP/AVIF 변환
적합한 상황
- 블로그, 문서 사이트, 마케팅/랜딩 페이지
- 포트폴리오, e커머스 카탈로그
- 성능이 중요한 콘텐츠 중심 사이트
Island Architecture 상세
Island Architecture는 페이지를 정적 HTML "바다"와 대화형 "섬(Island)"으로 분리합니다. SPA와 달리 대부분이 순수 HTML이고, 상호작용이 필요한 컴포넌트만 독립적으로 hydrate하는 Partial Hydration 방식입니다.
Island Architecture: 대부분 정적 HTML, 대화형 컴포넌트만 독립 hydrate
client:* 디렉티브 상세
Astro는 컴포넌트의 hydration 시점을 제어하기 위해 다양한 client:* 디렉티브를 제공합니다.
| 디렉티브 | hydration 시점 | 사용 사례 |
|---|---|---|
client:load | 페이지 로드 즉시 | 즉시 상호작용 필요 (모달, 카운터) |
client:idle | 브라우저 idle 시 | 우선순위 낮은 UI (채팅, 추천) |
client:visible | 뷰포트 진입 시 | 스크롤 하단 (차트, 댓글) |
client:media | 미디어 쿼리 매치 시 | 반응형 전용 (모바일 메뉴) |
client:only | SSR 없이 클라이언트만 | 서버 렌더링 불가 (Canvas, WebGL) |
| (없음) | hydrate 안 함 | 정적 컴포넌트 (헤더, 푸터) |
Islands 코드 예시
<Header /> <!-- 정적 HTML -->
<Counter client:load /> <!-- 즉시 hydrate -->
<Search client:visible /> <!-- 뷰포트 진입 시 -->
<Carousel client:idle /> <!-- idle 시 -->
<Menu client:media="(max-width:768px)" />
<Canvas client:only="react" />
client:visible은 Intersection Observer를 사용하므로 스크롤 하단의 무거운 컴포넌트에 적합합니다.
client:idle은 requestIdleCallback을 활용합니다.
두 디렉티브를 적절히 활용하면 초기 로드 성능을 크게 개선할 수 있습니다.
프로젝트 설정
프로젝트 생성 요청
Astro + TypeScript + Tailwind CSS + MDX로 기술 블로그를 만들어줘.
Content Collections, 태그 필터링, 다크 모드, SEO, RSS 피드,
View Transitions, 이미지 최적화(astro:assets) 포함.
폴더 구조
src/
├── content/ # Content Collections
│ ├── config.ts
│ └── blog/*.md
├── components/ # .astro, .jsx, .vue, .svelte
├── layouts/
├── pages/ # 파일 기반 라우팅
│ ├── index.astro
│ ├── blog/[slug].astro
│ └── rss.xml.js
└── styles/
astro.config.mjs 설정
import { defineConfig } from 'astro/config';
export default defineConfig({
site: 'https://example.com',
integrations: [react(), vue(), mdx(), sitemap()],
output: 'static', // 'static' | 'server' | 'hybrid'
});
빌드 파이프라인
Astro는 Vite 기반 빌드 파이프라인을 사용합니다.
.astro, .md, .mdx 파일들이 Vite를 통해 처리되며,
최종적으로 정적 HTML과 최소한의 JavaScript 번들이 생성됩니다.
Vite 기반 빌드 후 SSG/SSR/Hybrid 분기, Partial Hydration 적용
Vite 기반 빌드 특징
- 개발 모드:
astro dev- Vite HMR, 즉각적 변경 반영 - 빌드:
astro build- Rollup 번들링, 트리 쉐이킹, 코드 스플리팅 - 프리뷰:
astro preview- 빌드 결과물 로컬 확인
이미지 최적화
astro:assets의 <Image> 컴포넌트로 자동 WebP/AVIF 변환, 크기 최적화, lazy loading이 적용됩니다.
import { Image } from 'astro:assets';
import hero from '../assets/hero.png';
---
<Image src={hero} alt="히어로" width={800} format="webp" />
SSG vs SSR vs Hybrid 비교
Astro는 세 가지 렌더링 모드를 지원합니다.
| 구분 | SSG (Static) | SSR (Server) | Hybrid |
|---|---|---|---|
| 렌더링 시점 | 빌드 시 | 요청 시 | 페이지별 선택 |
| 설정 | output: 'static' | output: 'server' | output: 'hybrid' |
| 성능 | 최고 (CDN 캐시) | 동적 생성 오버헤드 | 페이지별 최적화 |
| 데이터 신선도 | 빌드 시점 고정 | 항상 최신 | 선택적 |
| 호스팅 | CDN/정적 호스팅 | 서버 필요 | 서버 필요 |
| 적합한 사이트 | 블로그, 문서 | 대시보드, 인증 | 블로그 + 대시보드 |
| 어댑터 | 불필요 | 필수 | 필수 |
Hybrid 모드 예시
---
export const prerender = false; // 이 페이지만 SSR
const user = await getUser(Astro.cookies.get('session'));
if (!user) return Astro.redirect('/login');
---
<h1>환영합니다, {user.name}님</h1>
SSR/Hybrid 모드 사용 시 @astrojs/vercel, @astrojs/netlify, @astrojs/cloudflare 등 어댑터 설치가 필수입니다.
Content Collections
Zod 기반 스키마 검증으로 빌드 시 콘텐츠 정합성을 보장하며, TypeScript 자동 완성과 타입 체크가 가능한 콘텐츠 관리 시스템입니다.
스키마 정의
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(), pubDate: z.date(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };
타입 안전한 쿼리
---
import { getCollection } from 'astro:content';
// draft 제외, 날짜순 정렬 (타입 자동 추론)
const posts = (await getCollection('blog'))
.filter((post) => !post.data.draft)
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
---
{posts.map((post) => (
<a href={`/blog/${post.id}`}>{post.data.title}</a>
))}
동적 페이지 생성
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(p => ({ params: {slug: p.id}, props: {post: p} }));
}
import { render } from 'astro:content';
const { Content } = await render(Astro.props.post);
---
<Content />
프레임워크 통합
Astro는 React, Vue, Svelte 등을 한 프로젝트에서 혼용할 수 있습니다. 각 컴포넌트는 독립적으로 hydrate되므로, 팀의 기존 기술 스택을 그대로 활용하면서 Astro의 성능 이점을 누릴 수 있습니다.
---
import Counter from '../components/Counter.jsx'; // React
import Search from '../components/SearchBox.vue'; // Vue
import Carousel from '../components/Carousel.svelte'; // Svelte
---
<Counter client:load />
<Search client:visible />
<Carousel client:idle />
MDX
Markdown에 JSX 컴포넌트를 추가하여 콘텐츠 작성과 인터랙티브 요소를 결합할 수 있습니다.
---
title: "Astro 너무 재밌어"
pubDate: 2024-01-01
---
import Counter from '../../components/Counter.jsx';
# 마크다운 콘텐츠 안에 컴포넌트 삽입
<Counter client:load />
View Transitions API
Astro는 네이티브 View Transitions API를 기본 지원하여 SPA 같은 부드러운 페이지 전환 효과를 MPA(Multi-Page App)에서 구현할 수 있습니다.
레이아웃 <head>에 <ViewTransitions />를 추가하여 활성화합니다.
전환 디렉티브
transition:animate="fade"- 페이드 인/아웃transition:animate="slide"- 슬라이드 전환transition:animate="none"- 전환 없음 (요소 유지)transition:name={`hero-${slug}`}- 요소 매칭으로 연속성 있는 전환transition:persist- 상태 유지 (비디오/오디오 플레이어)
transition:persist를 사용하면 음악 재생 중 다른 페이지로 이동해도 재생이 끊기지 않습니다.
목록/상세 페이지에 같은 transition:name을 부여하면 이미지가 자연스럽게 확대/이동합니다.
Astro vs Next.js vs Nuxt 비교
| 구분 | Astro | Next.js | Nuxt |
|---|---|---|---|
| 철학 | 콘텐츠 우선, Zero JS | React 풀스택 | Vue 풀스택 |
| 기본 JS | 0KB (Island만) | React 런타임 | Vue 런타임 |
| UI 프레임워크 | 혼용 가능 | React 전용 | Vue 전용 |
| Hydration | Partial (Island) | Full / Selective | Full Page |
| Lighthouse | 100점 용이 | 최적화 필요 | 최적화 필요 |
| 적합한 사이트 | 블로그, 문서 | 웹 앱, SaaS | 웹 앱, 기업 |
- 콘텐츠 중심: Astro (블로그, 문서, 포트폴리오)
- 복잡한 웹 앱: Next.js(React) 또는 Nuxt(Vue)
- 프레임워크 무관: Astro는 어떤 UI 라이브러리도 혼용 가능
배포
SSG는 정적 호스팅에, SSR/Hybrid는 서버 환경에 배포합니다.
배포 명령어
npx astro add vercel # 어댑터 설치
npx vercel deploy # Vercel 배포
npx astro add netlify # Netlify
npx astro add cloudflare # Cloudflare
- Vercel: zero-config, Edge Functions, 가장 간편
- Netlify: 공식 어댑터, Forms/Functions 통합
- Cloudflare Pages: 글로벌 엣지, 저렴한 가격
- Docker: Node 어댑터 + 멀티스테이지 빌드로 자체 서버 운영
- GitHub Pages: SSG 전용, 무료
모범 사례
- Islands 최소화:
client:*는 정말 필요한 곳에만 사용 - Content Collections: 모든 콘텐츠에 스키마 정의로 타입 안전성 확보
- Image:
astro:assets로 WebP/AVIF 자동 변환 - Partial Hydration:
client:visible/client:idle적극 활용 - View Transitions: 레이아웃에
<ViewTransitions />추가 - 환경 변수:
PUBLIC_접두사로 공개/비공개 구분
client:load남용 시 Astro 성능 이점이 사라집니다.client:visible/client:idle을 우선 사용하세요.- SSR 모드에서
window/document직접 접근 불가 -client:only사용 - 다중 프레임워크 사용 시 각 런타임이 별도 로드됩니다. 꼭 필요한 경우에만 혼용하세요.