# React Nextjs App

> Next.js App Router 프로젝트 컨벤션. Server/Client Components, metadata API, 특수 파일 패턴, Route Groups.

- **Type:** Skill
- **Install:** `agentstack add skill-ggombee-code-forge-react-nextjs-app`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ggombee](https://agentstack.voostack.com/s/ggombee)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [ggombee](https://github.com/ggombee)
- **Source:** https://github.com/ggombee/code-forge/tree/main/modules/frameworks/react-nextjs-app

## Install

```sh
agentstack add skill-ggombee-code-forge-react-nextjs-app
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# React & Next.js App Router 컨벤션

이 프로젝트는 **Next.js App Router**를 사용한다. `app/` 디렉토리 기반의 파일 시스템 라우팅을 따른다.

---

## 디렉토리 구조

```
app/
├── layout.tsx          # 루트 레이아웃 (필수)
├── page.tsx            # 루트 페이지
├── loading.tsx         # 로딩 UI
├── error.tsx           # 에러 UI
├── not-found.tsx       # 404 UI
├── (auth)/             # Route Group (URL에 포함되지 않음)
│   ├── login/
│   │   └── page.tsx
│   └── register/
│       └── page.tsx
├── dashboard/
│   ├── layout.tsx      # 중첩 레이아웃
│   ├── page.tsx
│   └── @analytics/     # Parallel Route
│       └── page.tsx
└── api/                # Route Handlers
    └── users/
        └── route.ts
```

---

## Server vs Client Components

### Server Component (기본값)

```typescript
// app/orders/page.tsx - 서버 컴포넌트 (기본값)
import { db } from '@/lib/db';

// async 함수 사용 가능
export default async function OrdersPage() {
  const orders = await db.orders.findMany();

  return (
    
      {orders.map((order) => (
        {order.name}
      ))}
    
  );
}
```

### Client Component

```typescript
// app/orders/OrderFilters.tsx
'use client'; // 반드시 파일 최상단에 선언

import { useState } from 'react';

export function OrderFilters() {
  const [filter, setFilter] = useState('all');

  return (
     setFilter(e.target.value)}>
      전체
      대기중
    
  );
}
```

```typescript
// ✅ 좋은 예: Server Component가 Client Component를 children으로 받음
// app/orders/layout.tsx (Server Component)
import { OrderFilters } from './OrderFilters'; // Client Component

export default function OrdersLayout({ children }: { children: React.ReactNode }) {
  return (
    
      
      {children}
    
  );
}

// ❌ 나쁜 예: 불필요하게 'use client' 추가
'use client';
// useState, useEffect 없이 'use client' 선언
export default function StaticCard({ title }: { title: string }) {
  return {title};
}
```

---

## metadata API

```typescript
// app/orders/page.tsx - 정적 메타데이터
import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: '주문 목록',
  description: '전체 주문 내역을 확인합니다.',
};

export default function OrdersPage() { ... }
```

```typescript
// app/orders/[id]/page.tsx - 동적 메타데이터
import type { Metadata } from 'next';

interface Props {
  params: { id: string };
}

export async function generateMetadata({ params }: Props): Promise {
  const order = await fetchOrder(params.id);
  return {
    title: `주문 #${order.id}`,
    description: `${order.status} 상태의 주문입니다.`,
  };
}

export default async function OrderDetailPage({ params }: Props) { ... }
```

---

## 특수 파일 패턴

### loading.tsx

```typescript
// app/orders/loading.tsx
// Suspense 경계를 자동으로 생성
export default function OrdersLoading() {
  return 로딩 중...;
}
```

### error.tsx

```typescript
// app/orders/error.tsx
'use client'; // 에러 컴포넌트는 반드시 Client Component

import { useEffect } from 'react';

interface Props {
  error: Error & { digest?: string };
  reset: () => void;
}

export default function OrdersError({ error, reset }: Props) {
  useEffect(() => {
    console.error(error);
  }, [error]);

  return (
    
      주문을 불러오는 중 오류가 발생했습니다.
      다시 시도
    
  );
}
```

### layout.tsx

```typescript
// app/dashboard/layout.tsx - 중첩 레이아웃
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    
      대시보드 네비게이션
      {children}
    
  );
}
```

---

## Route Groups

```typescript
// app/(marketing)/about/page.tsx
// URL: /about (그룹명 (marketing)은 URL에 포함되지 않음)

// app/(marketing)/layout.tsx - 마케팅 페이지 전용 레이아웃
export default function MarketingLayout({ children }: { children: React.ReactNode }) {
  return {children};
}
```

---

## Parallel Routes

```typescript
// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
  analytics,
  team,
}: {
  children: React.ReactNode;
  analytics: React.ReactNode; // @analytics 슬롯
  team: React.ReactNode;      // @team 슬롯
}) {
  return (
    
      {children}
      {analytics}
      {team}
    
  );
}

// app/dashboard/@analytics/page.tsx - analytics 슬롯
export default function AnalyticsPage() {
  return 분석 데이터;
}
```

---

## Route Handlers

```typescript
// app/api/orders/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams;
  const status = searchParams.get('status');

  const orders = await fetchOrders(status);
  return NextResponse.json(orders);
}

export async function POST(request: NextRequest) {
  const body = await request.json();
  const order = await createOrder(body);
  return NextResponse.json(order, { status: 201 });
}
```

---

## 데이터 페칭 패턴

```typescript
// ✅ Server Component에서 직접 fetch
export default async function Page() {
  // Next.js가 자동으로 캐싱/중복 제거
  const data = await fetch('https://api.example.com/data', {
    next: { revalidate: 3600 }, // 1시간마다 재검증
  });
  const json = await data.json();
  return {json.title};
}

// ✅ 병렬 데이터 페칭
export default async function Page() {
  const [orders, users] = await Promise.all([
    fetchOrders(),
    fetchUsers(),
  ]);
  return ;
}
```

---

## 체크리스트

- [ ] 인터랙션 없는 컴포넌트는 Server Component(기본값) 사용?
- [ ] useState/useEffect 사용 시 'use client' 선언?
- [ ] error.tsx에 'use client' 선언?
- [ ] metadata export로 SEO 설정?
- [ ] loading.tsx로 Suspense UI 제공?

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ggombee](https://github.com/ggombee)
- **Source:** [ggombee/code-forge](https://github.com/ggombee/code-forge)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-ggombee-code-forge-react-nextjs-app
- Seller: https://agentstack.voostack.com/s/ggombee
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
