Loading...
Loading...
React, Next.js 16+, TypeScript, shadcn/ui, Tailwind CSS v4, Vite, Vitest 기반 프론트엔드 프로젝트의 기술스택 컨벤션 및 아키텍처 가이드. FE 코드 작성, 리뷰, 리팩토링 시 자동 참조.
npx skill4agent add ingpdw/pdw-fe-dev-tool fe-stack| 항목 | 선택 |
|---|---|
| 언어 | TypeScript 5+ (strict mode) |
| UI 프레임워크 | React 19+ |
| 메타 프레임워크 | Next.js 16+ (App Router) |
| UI 컴포넌트 | shadcn/ui + Radix UI |
| 스타일링 | Tailwind CSS v4 |
| 빌드 도구 | Vite |
| 테스트 | Vitest + React Testing Library |
| 패키지 매니저 | pnpm |
| 린팅 | ESLint + Prettier |
src/
├── app/ # App Router 라우트
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Home page
│ ├── globals.css # Global styles (Tailwind)
│ ├── (auth)/ # Route group
│ │ ├── login/page.tsx
│ │ └── signup/page.tsx
│ └── api/ # API Route Handlers
│ └── [resource]/route.ts
├── components/
│ ├── ui/ # shadcn/ui 컴포넌트 (자동 생성)
│ ├── common/ # 공용 컴포넌트
│ └── [feature]/ # 기능별 컴포넌트
├── hooks/ # 커스텀 훅
├── lib/ # 유틸리티, 헬퍼
│ ├── utils.ts # cn() 등 공용 유틸
│ └── api.ts # API 클라이언트
├── types/ # 전역 타입 정의
├── stores/ # 상태 관리 (Zustand)
├── constants/ # 상수 정의
└── __tests__/ # 테스트 파일 (co-location 권장)strict: trueinterfacetypeanyunknowninterfaceReact.FCasenumas const// Props 정의
interface ButtonProps {
variant?: "default" | "destructive" | "outline";
size?: "sm" | "md" | "lg";
children: React.ReactNode;
onClick?: () => void;
}
// as const 패턴
const STATUS = {
IDLE: "idle",
LOADING: "loading",
ERROR: "error",
} as const;
type Status = (typeof STATUS)[keyof typeof STATUS];function Component()&&handle[Event]handleClickhandleSubmituse[Name]keyfunction UserCard({ name, email, onEdit }: UserCardProps) {
const handleEditClick = () => onEdit(email);
return (
<Card>
<CardHeader>
<CardTitle>{name}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground">{email}</p>
<Button variant="outline" onClick={handleEditClick}>
Edit
</Button>
</CardContent>
</Card>
);
}"use client""use client"async/await"use server"loading.tsxerror.tsxnot-found.tsxgenerateMetadata()metadataGETPOST[param]generateStaticParams()@slot(.)npx shadcn@latest add [component]components/ui/cn()globals.cssimport { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
<Button className={cn("w-full", isActive && "bg-primary")} variant="outline">
Click
</Button>@applysm:md:lg:xl:2xl:dark:clsxcn()useStateuseReduceruseSearchParamsnuqs| 대상 | 규칙 | 예시 |
|---|---|---|
| 컴포넌트 | PascalCase | |
| 훅 | camelCase (use 접두사) | |
| 유틸리티 | camelCase | |
| 타입 | PascalCase | |
| 상수 | camelCase 파일, UPPER_SNAKE 변수 | |
| 테스트 | 원본명.test | |
| 페이지 (App Router) | 소문자 폴더 | |
// 1. React/Next.js
import { useState } from "react";
import Link from "next/link";
// 2. 서드파티 라이브러리
import { useQuery } from "@tanstack/react-query";
import { z } from "zod";
// 3. 내부 컴포넌트 (shadcn/ui 포함)
import { Button } from "@/components/ui/button";
import { UserCard } from "@/components/user/UserCard";
// 4. 훅, 유틸, 타입
import { useAuth } from "@/hooks/useAuth";
import { cn } from "@/lib/utils";
import type { User } from "@/types";