+ 핵심 판단과 수정안을 간결하고 정확히 제시했다.
- 상품 수만큼 별도 번들이 생긴다는 표현은 부정확하다.
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 | Claude | Gemini | 앞선 모델 |
|---|---|---|---|---|
| 지시 준수 | 10 | 9 | 8 | ChatGPT +11% |
| 정확성 | 9 | 7 | 7 | ChatGPT +29% |
| 구체성 | 8 | 9 | 9 | 동점 |
| 구성·가독성 | 9 | 9 | 9 | 동점 |
| 분량 적정성 | 10 | 6 | 7 | ChatGPT +43% |
gpt-5.6-sol가 모델 이름을 가린 채 1~10점으로 채점했습니다 (2026-09-24). 측정값이 아니라 AI 심사 결과입니다.
같은 입력을 세 모델에 넣어 받은 답을 그대로 옮겼습니다. 각 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가 필요한지 판단해서 고쳐줘.반복되는 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: 정적 링크와 정보만 있으면 하이드레이션하지 않습니다.<form>과 서버 처리 또는 링크 기반으로 구현하는 편이 좋습니다.client:visible로 바꾸는 것만으로는 반복 island 문제가 해결되지 않습니다. 각 카드가 정말 클라이언트 상태를 필요로 할 때만 제한적으로 사용하세요.
| 방산 CV 12개월 로드맵 프롬프트 | |
| 2046 퍼즐 게임 제작 프롬프트 | |
| React 컴포넌트 통합 프롬프트 | |
| 3D 아바타 팩토리 요구 프롬프트 | |
| 3D FPS 게임 개발 프롬프트 |