fe-stack

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Frontend Tech Stack Convention

前端技术栈规范

기술스택

技术栈

항목선택
언어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
类别选型
编程语言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

프로젝트 구조 (Next.js App Router)

项目结构 (Next.js App Router)

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 권장)
src/
├── app/                    # App Router 路由
│   ├── layout.tsx          # Root layout
│   ├── page.tsx            # Home page
│   ├── globals.css         # Global styles (Tailwind)
│   ├── (auth)/             # 路由分组
│   │   ├── login/page.tsx
│   │   └── signup/page.tsx
│   └── api/                # API Route Handlers
├── components/
│   ├── ui/                 # shadcn/ui 组件(自动生成)
│   ├── common/             # 通用组件
│   └── [feature]/          # 按功能划分的组件
├── hooks/                  # 自定义Hook
├── lib/                    # 工具函数、辅助方法
│   ├── utils.ts            # cn() 等通用工具
│   └── api.ts              # API 客户端
├── types/                  # 全局类型定义
├── stores/                 # 状态管理(Zustand)
├── constants/              # 常量定义
└── __tests__/              # 测试文件(推荐就近放置)

TypeScript 컨벤션

TypeScript 规范

  • strict: true
    필수
  • interface
    로 객체 타입 정의 (확장 가능),
    type
    은 유니온/인터섹션에 사용
  • any
    사용 금지 →
    unknown
    + type guard 사용
  • 컴포넌트 Props는
    interface
    로 정의,
    React.FC
    사용하지 않음
  • as
    타입 단언 최소화, 타입 가드 함수 선호
  • enum
    대신
    as const
    객체 사용
typescript
// 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];
  • 必须开启
    strict: true
  • 使用
    interface
    定义对象类型(支持扩展),
    type
    用于联合/交叉类型
  • 禁止使用
    any
    ,改用
    unknown
    + 类型守卫
  • 组件Props使用
    interface
    定义,不使用
    React.FC
  • 尽量减少
    as
    类型断言,优先使用类型守卫函数
  • 使用
    as const
    对象替代
    enum
typescript
// 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];

React 컨벤션

React 规范

  • 함수 선언문으로 컴포넌트 정의 (
    function Component()
    , 화살표 함수도 허용)
  • Props destructuring 사용
  • 단일 책임 원칙: 컴포넌트는 하나의 역할만 담당
  • 조건부 렌더링: 삼항 연산자 또는
    &&
    (falsy 값 주의)
  • 이벤트 핸들러:
    handle[Event]
    네이밍 (예:
    handleClick
    ,
    handleSubmit
    )
  • 커스텀 훅:
    use[Name]
    네이밍, 단일 관심사
  • key
    prop에 index 사용 금지 (안정적인 고유 ID 사용)
tsx
function 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>
  );
}
  • 使用函数声明式定义组件(
    function Component()
    ,箭头函数也可)
  • 使用Props解构
  • 单一职责原则:组件仅承担一个职责
  • 条件渲染:使用三元运算符或
    &&
    (注意假值陷阱)
  • 事件处理器:采用
    handle[Event]
    命名方式(如:
    handleClick
    handleSubmit
  • 自定义Hook:采用
    use[Name]
    命名方式,遵循单一关注点
  • 禁止在
    key
    属性中使用索引,需使用稳定的唯一ID
tsx
function 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>
  );
}

Next.js App Router 규칙

Next.js App Router 规则

  • Server Component 기본, 필요 시
    "use client"
    선언
  • "use client"
    는 가능한 트리의 말단에 배치 (클라이언트 경계 최소화)
  • 데이터 페칭: Server Component에서
    async/await
    로 직접 fetch
  • Server Actions:
    "use server"
    함수로 폼 처리, 뮤테이션
  • loading.tsx
    ,
    error.tsx
    ,
    not-found.tsx
    활용
  • Metadata:
    generateMetadata()
    또는 정적
    metadata
    객체
  • Route Handler:
    GET
    ,
    POST
    등 named export 함수
  • 동적 라우트:
    [param]
    폴더,
    generateStaticParams()
    로 정적 생성
  • Parallel Routes(
    @slot
    ), Intercepting Routes(
    (.)
    ) 적절히 활용
  • 默认使用Server Component,必要时声明
    "use client"
  • "use client"
    应尽可能放在组件树的末端(最小化客户端边界)
  • 数据获取:在Server Component中直接使用
    async/await
    进行fetch
  • Server Actions:使用
    "use server"
    函数处理表单、数据变更
  • 使用
    loading.tsx
    error.tsx
    not-found.tsx
    处理状态
  • 元数据:使用
    generateMetadata()
    或静态
    metadata
    对象
  • 路由处理器:使用
    GET
    POST
    等具名导出函数
  • 动态路由:使用
    [param]
    文件夹,通过
    generateStaticParams()
    生成静态路由
  • 合理使用Parallel Routes(
    @slot
    )、Intercepting Routes(
    (.)

shadcn/ui 규칙

shadcn/ui 规则

  • npx shadcn@latest add [component]
    로 컴포넌트 추가
  • components/ui/
    에 생성된 코드를 프로젝트 요구에 맞게 커스터마이즈
  • cn()
    유틸리티로 조건부 클래스 합성
  • Radix UI primitives 기반으로 접근성 내장
  • 테마 커스터마이즈는
    globals.css
    의 CSS 변수로 관리
tsx
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";

<Button className={cn("w-full", isActive && "bg-primary")} variant="outline">
  Click
</Button>
  • 使用
    npx shadcn@latest add [component]
    命令添加组件
  • 根据项目需求自定义
    components/ui/
    中生成的代码
  • 使用
    cn()
    工具函数组合条件类名
  • 基于Radix UI primitives,内置无障碍支持
  • 通过
    globals.css
    中的CSS变量管理主题自定义
tsx
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";

<Button className={cn("w-full", isActive && "bg-primary")} variant="outline">
  Click
</Button>

Tailwind CSS v4 규칙

Tailwind CSS v4 规则

  • 유틸리티 클래스 우선, 커스텀 CSS 최소화
  • @apply
    사용 최소화 (컴포넌트 추출 선호)
  • 반응형:
    sm:
    ,
    md:
    ,
    lg:
    ,
    xl:
    ,
    2xl:
    접두사 (mobile-first)
  • 다크 모드:
    dark:
    접두사 + CSS 변수 기반 테마
  • clsx
    또는
    cn()
    (tailwind-merge)로 동적 클래스 합성
  • 优先使用工具类,尽量减少自定义CSS
  • 尽量减少
    @apply
    的使用(优先提取组件)
  • 响应式:使用
    sm:
    md:
    lg:
    xl:
    2xl:
    前缀(移动端优先)
  • 深色模式:使用
    dark:
    前缀 + 基于CSS变量的主题
  • 使用
    clsx
    cn()
    (tailwind-merge)组合动态类名

상태 관리

状态管理

  • 로컬 상태:
    useState
    ,
    useReducer
  • 서버 상태: TanStack Query (React Query)
  • 전역 클라이언트 상태: Zustand
  • URL 상태:
    useSearchParams
    ,
    nuqs
  • 폼 상태: React Hook Form + Zod 유효성 검사
  • 本地状态:
    useState
    useReducer
  • 服务端状态:TanStack Query (React Query)
  • 全局客户端状态:Zustand
  • URL状态:
    useSearchParams
    nuqs
  • 表单状态:React Hook Form + Zod 校验

파일 네이밍 규칙

文件命名规则

대상규칙예시
컴포넌트PascalCase
UserProfile.tsx
camelCase (use 접두사)
useAuth.ts
유틸리티camelCase
formatDate.ts
타입PascalCase
UserTypes.ts
상수camelCase 파일, UPPER_SNAKE 변수
apiEndpoints.ts
테스트원본명.test
UserProfile.test.tsx
페이지 (App Router)소문자 폴더
app/dashboard/page.tsx
对象规则示例
组件PascalCase
UserProfile.tsx
Hook小驼峰(以use为前缀)
useAuth.ts
工具函数小驼峰
formatDate.ts
类型定义文件PascalCase
UserTypes.ts
常量文件文件名小驼峰,变量名大写下划线分隔
apiEndpoints.ts
测试文件原文件名.test
UserProfile.test.tsx
页面(App Router)小写文件夹
app/dashboard/page.tsx

Import 순서

导入顺序

typescript
// 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";
typescript
// 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. Hook、工具函数、类型
import { useAuth } from "@/hooks/useAuth";
import { cn } from "@/lib/utils";
import type { User } from "@/types";