☰ 분류

Astro v6 아키텍처 프롬프트

Astro 프로젝트 질문이나 코드를 넣으면 HTML 우선, Islands Architecture, 명시적 hydration, 서버 우선 로직을 기준으로 답하게 합니다.

분류개발 › 코딩
태그초안작성검토개발자코드
프롬프트 (영어 본문 · 답은 한국어로 옵니다)
# Astro v6 Architecture Rules (Strict Mode)

## 1. Core Philosophy

- Follow Astro’s “HTML-first / zero JavaScript by default” principle:
  - Everything is static HTML unless interactivity is explicitly required.
  - JavaScript is a cost → only add when it creates real user value.

- Always think in “Islands Architecture”:
  - The page is static HTML
  - Interactive parts are isolated islands
  - Never treat the whole page as an app

- Before writing any JavaScript, always ask:
  "Can this be solved with HTML + CSS or server-side logic?"

---

## 2. Component Model

- Use `.astro` components for:
  - Layout
  - Composition
  - Static UI
  - Data fetching
  - Server-side logic (frontmatter)

- `.astro` components:
  - Run at build-time or server-side
  - Do NOT ship JavaScript by default
  - Must remain framework-agnostic

- NEVER use React/Vue/Svelte hooks inside `.astro`

---

## 3. Islands (Interactive Components)

- Only use framework components (React, Vue, Svelte, etc.) for interactivity.

- Treat every interactive component as an isolated island:
  - Independent
  - Self-contained
  - Minimal scope

- NEVER:
  - Hydrate entire pages or layouts
  - Wrap large trees in a single island
  - Create many small islands in loops unnecessarily

- Prefer:
  - Static list rendering
  - Hydrate only the minimal interactive unit

---

## 4. Hydration Strategy (Critical)

- Always explicitly define hydration using `client:*` directives.

- Choose the LOWEST possible priority:

  - `client:load`
    → Only for critical, above-the-fold interactivity

  - `client:idle`
    → For secondary UI after page load

  - `client:visible`
    → For below-the-fold or heavy components

  - `client:media`
    → For responsive / conditional UI

  - `client:only`
    → ONLY when SSR breaks (window, localStorage, etc.)

- Default rule:
  ❌ Never default to `client:load`
  ✅ Prefer `client:visible` or `client:idle`

- Hydration is a performance budget:
  - Every island adds JS
  - Keep total JS minimal

📌 Astro does NOT hydrate components unless explicitly told via `client:*` :contentReference[oaicite:0]{index=0}  

---

## 5. Server vs Client Logic

- Prefer server-side logic (inside `.astro` frontmatter) for:
  - Data fetching
  - Transformations
  - Filtering / sorting
  - Derived values

- Only use client-side state when:
  - User interaction requires it
  - Real-time updates are needed

- Avoid:
  - Duplicating logic on client
  - Moving server logic into islands

---

## 6. State Management

- Avoid client state unless strictly necessary.

- If needed:
  - Scope state inside the island only
  - Do NOT create global app state unless required

- For cross-island state:
  - Use lightweight shared stores (e.g., nano stores)
  - Avoid heavy global state systems by default

---

## 7. Performance Constraints (Hard Rules)

- Minimize JavaScript shipped to client:
  - Astro only loads JS for hydrated components :contentReference[oaicite:1]{index=1}  

- Prefer:
  - Static rendering
  - Partial hydration
  - Lazy hydration

- Avoid:
  - Hydrating large lists
  - Repeated islands in loops
  - Overusing `client:load`

- Each island:
  - Has its own bundle
  - Loads independently
  - Should remain small and focused :contentReference[oaicite:2]{index=2}  

---

## 8. File & Project Structure

- `/pages`
  - Entry points (SSG/SSR)
  - No client logic

- `/components`
  - Shared UI
  - Islands live here

- `/layouts`
  - Static wrappers only

- `/content`
  - Markdown / CMS data

- Keep `.astro` files focused on composition, not behavior

---

## 9. Anti-Patterns (Strictly Forbidden)

- ❌ Using hooks in `.astro`
- ❌ Turning Astro into SPA architecture
- ❌ Hydrating entire layout/page
- ❌ Using `client:load` everywhere
- ❌ Mapping lists into hydrated components
- ❌ Using client JS for static problems
- ❌ Replacing server logic with client logic

---

## 10. Preferred Patterns

- ✅ Static-first rendering
- ✅ Minimal, isolated islands
- ✅ Lazy hydration (`visible`, `idle`)
- ✅ Server-side computation
- ✅ HTML + CSS before JS
- ✅ Progressive enhancement

---

## 11. Decision Framework (VERY IMPORTANT)

For every feature:

1. Can this be static HTML?
   → YES → Use `.astro`

2. Does it require interaction?
   → NO → Stay static

3. Does it require JS?
   → YES → Create an island

4. When should it load?
   → Choose LOWEST priority `client:*`

---

## 12. Mental Model (Non-Negotiable)

- Astro is NOT:
  - Next.js
  - SPA framework
  - React-first system

- Astro IS:
  - Static-first renderer
  - Partial hydration system
  - Performance-first architecture

- Think:
  ❌ “Build an app”
  ✅ “Ship HTML + sprinkle JS”

어떤 프롬프트인가

Astro v6 개발에서 정적 HTML과 최소 JavaScript 원칙을 강제하는 아키텍처 규칙이다. client:* 지시문 선택과 섬 구조를 중시하며, 잘린 본문 기준으로는 초반 규칙만 확인된다.

모델 비교

ChatGPT가 가장 정확하고 목적에 맞게 간결하다. Claude는 구체적이나 과도하며, Gemini는 반복 아일랜드를 일부 남긴다.

ChatGPT종합 1위
46/ 50

+ 핵심 판단과 수정안을 간결하고 정확히 제시했다.

- 상품 수만큼 별도 번들이 생긴다는 표현은 부정확하다.

Claude
40/ 50

+ 정적 카드와 최소 아일랜드 구조를 구체화했다.

- 가정한 장바구니 구현이 과하고 예시도 미완성이다.

Gemini
40/ 50

+ 각 요소의 문제와 대안을 체계적으로 비교했다.

- 버튼별 아일랜드로 반복 비용을 충분히 줄이지 못했다.

ChatGPT+ 핵심 판단과 수정안을 간결하고 정확히 제시했다. - 상품 수만큼 별도 번들이 생긴다는 표현은 부정확하다.

Claude+ 정적 카드와 최소 아일랜드 구조를 구체화했다. - 가정한 장바구니 구현이 과하고 예시도 미완성이다.

Gemini+ 각 요소의 문제와 대안을 체계적으로 비교했다. - 버튼별 아일랜드로 반복 비용을 충분히 줄이지 못했다.

기준ChatGPTClaudeGemini앞선 모델
지시 준수1098ChatGPT +11%
정확성977ChatGPT +29%
구체성899동점
구성·가독성999동점
분량 적정성1067ChatGPT +43%
답 전문 보기

같은 입력을 세 모델에 넣어 받은 답을 그대로 옮겼습니다. 각 CLI(에이전트 하네스)에서 실행했습니다. ChatGPT·Claude 앱이나 웹에서는 답이 다를 수 있습니다.

넣은 입력
[붙여 넣은 자료]
이 규칙에 맞춰서 아래 상품 목록 페이지 컴포넌트를 리뷰하고 고쳐줘. 전부 client:load를 걸어놔서 그런지 초기 로딩이 느리다는 피드백을 받았어.

```astro
---
import ProductCard from '../components/ProductCard.jsx';
import Header from '../components/Header.jsx';
import Footer from '../components/Footer.jsx';
import { getProducts } from '../lib/api';

const products = await getProducts();
---
<html>
  <body>
    <Header client:load />
    <main>
      {products.map((p) => (
        <ProductCard client:load product={p} />
      ))}
    </main>
    <Footer client:load />
  </body>
</html>
```

상품 카드처럼 반복되는 걸 이렇게 하이드레이트해도 되는지, Header/Footer는 굳이 client:load가 필요한지 판단해서 고쳐줘.
gpt-5.6-luna (codex CLI · 에이전트 하네스) · 실행일 2026-09-24

반복되는 ProductCard마다 client:load를 붙이는 것은 피해야 합니다. 상품 수만큼 JS 번들과 하이드레이션 작업이 발생해 초기 로딩이 느려집니다.

Header와 Footer도 정적 UI라면 client:load가 필요 없습니다. .astro 컴포넌트로 변경하고, 상호작용이 필요한 부분만 별도 island로 분리하는 것이 좋습니다.

---
import ProductCard from '../components/ProductCard.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import { getProducts } from '../lib/api';

const products = await getProducts();
---

<html lang="ko">
  <body>
    <Header />

    <main>
      {products.map((product) => (
        <ProductCard product={product} />
      ))}
    </main>

    <Footer />
  </body>
</html>

판단은 다음과 같습니다.

  • ProductCard: 상품명, 이미지, 가격, 링크처럼 정적인 내용이면 .astro로 작성하고 하이드레이트하지 않습니다.
  • Header: 로고와 내비게이션만 있으면 .astro로 작성합니다. 모바일 메뉴가 필요하다면 Header 전체가 아니라 메뉴 토글만 별도 컴포넌트로 분리합니다.
<!-- Header.astro -->
---
import MobileMenuButton from './MobileMenuButton.jsx';
---

<header>
  <a href="/">브랜드</a>
  <nav>...</nav>

  <MobileMenuButton client:idle />
</header>
  • Footer: 정적 링크와 정보만 있으면 하이드레이션하지 않습니다.
  • 상품 카드의 장바구니 버튼처럼 상호작용이 필요해도 카드 전체를 island로 만들지 말고, 버튼만 분리합니다. 다만 카드마다 island를 반복하면 비용이 커질 수 있으므로 가능하면 HTML <form>과 서버 처리 또는 링크 기반으로 구현하는 편이 좋습니다.

client:visible로 바꾸는 것만으로는 반복 island 문제가 해결되지 않습니다. 각 카드가 정말 클라이언트 상태를 필요로 할 때만 제한적으로 사용하세요.

같은 분류의 프롬프트

단일파일 쇼핑몰 제작 프롬프트
API 보안 테스트 프레임워크 프롬프트
음성 복제 전문가 프롬프트
2046 퍼즐 게임 제작 프롬프트
React 컴포넌트 통합 프롬프트
Astro v6 아키텍처 프롬프트