CLAUDE.md 8.7 KB

CLAUDE.md

Project Overview

DPOT - Next.js 15 App Router 기반 Creators Support and donate platform frontend (https://dpot.web.or.kr)

  • Framework: Next.js 15.3+ (App Router, Server Components)
  • React: 19.1+
  • Language: TypeScript 5
  • Backend API: https://localhost:4000 (ASP.NET Core Minimal API)

Project Structure

app/
  ├── (auth)/          → 인증 (login, register, forgot-password, reset-password, welcome, approval)
  ├── (main)/          → 메인 레이아웃 그룹
  │   ├── (account)/   → 계정 관리 (profile, change-password, change-email 등)
  │   ├── (forum)/     → 게시판 (board, post, comment, latest)
  │   ├── channel/     → 채널 상세 ([channelSID])
  │   ├── note/        → 쪽지 (inbox, send)
  │   ├── notification/→ 알림 목록
  │   ├── support/     → 고객지원 (faq, guide, contact)
  │   └── docs/        → 문서 페이지
  ├── widget/          → OBS 위젯 (alert, goal, rank, crew — 별도 레이아웃)
  ├── remote/          → 후원 리모콘 ([channelSID] — 별도 레이아웃)
  ├── api/             → Route Handler (auth, channel, donation, note, notification, payment, forum 등)
  ├── auth/            → 인증 관련
  ├── component/       → 공통 레이아웃 컴포넌트
  │   ├── channel/     → ChannelSidebar (좌측), ChannelSidebarItem
  │   ├── NotificationBell, ProfileDropdown, ChargeModal
  │   └── Layout, PopupModal, Editor
  └── styles/          → 글로벌 + 컴포넌트 SCSS
components/ui/         → shadcn/ui 컴포넌트 (accordion, button, checkbox, dialog, dropdown-menu,
                          input, label, select, textarea, HotIndicator)
contexts/              → React Context Provider
  ├── authProvider.tsx      → 로그인 상태 관리, 토큰 갱신
  ├── memberProvider.tsx    → 현재 사용자 정보
  ├── configProvider.tsx    → 시스템 설정 (initialConfig prop, React.cache)
  ├── signalrProvider.tsx   → SignalR WebSocket (채팅)
  └── themeProvider.tsx     → 테마 관리
hooks/                 → 커스텀 훅 (useAuth, useChat, useDragScroll, useTheme, useErrorAlert,
                          useDonationAlert, useDonationHub, useNotification)
lib/
  ├── api/             → 서버 사이드 API 호출 함수 (Server Actions)
  │   ├── auth.ts      → 인증 API
  │   ├── account.ts   → 계정 관련 API
  │   ├── system.ts    → 시스템 설정 API
  │   ├── forum/       → board.ts, post.ts
  │   └── page/        → document.ts, faq.ts
  └── utils/
      ├── client.ts    → 클라이언트 유틸 (fetchApi, cn, formatDate, throwError)
      ├── server.ts    → 서버 유틸 (fetchJson, getAccessToken, checkPermission, getSignalRChatUrl)
      └── permission.ts → 권한 체크
types/                 → TypeScript 타입 정의
  ├── response/        → API 응답 타입 (common, account, forum, page)
  ├── request/         → 요청 페이로드 타입
  ├── forum/           → 게시판 도메인 타입 (post, comment, board, boardGroup 등)
  ├── account/         → 계정 타입 (member, loginLog)
  ├── chat.ts, broadcast.ts, config.ts
  └── editor.min.d.ts  → CKEditor 타입
constants/             → 상수 정의 (common.ts, forum.ts)
middleware.ts          → 인증 미들웨어 (토큰 검증, 리다이렉트)

Code Style Rules

  • 인덴트: 탭 사용
  • PK/ID 변수명: memberID, postID (camelCase + 대문자 ID)
  • 클라이언트 컴포넌트: 파일 최상단에 'use client' 선언
  • 서버 전용 함수: 'use server' 선언 (Server Actions, lib/utils/server.ts)
  • 컴포넌트 파일명: PascalCase (PopupModal.tsx, Layout.tsx)
  • 페이지/라우트: 소문자 kebab-case 디렉토리 (support/faq/)
  • 스타일: app/styles/ 에 컴포넌트별 SCSS 파일 (inline CSS 사용 금지 → SCSS 또는 Tailwind)
  • SCSS 클래스명: BEM 네이밍 (block__element--modifier)
  • 파일 내용의 마지막 줄 제거 (빈 줄 없이 끝남)
  • type 을 지정할 때 | 문자 양쪽에 공백 제거해(예시로 string|null|undefined)
  • button 태그에 submit type이 아니면 type="button" 필수
  • C# 람다 ) => { 한 줄에 붙여 작성 (개행 금지) — Frontend에서도 동일 스타일 적용
  • if (loading) return <p className="studio-page__empty">준비 중...</p>; 이런 식으로 한 줄로 처리하지 말고 중괄호 사용해줘 그리고 다음 줄로 개행을 하도록 해

Architecture Rules

  • 서버 컴포넌트가 기본'use client' 없으면 RSC
  • 클라이언트 상태: React Context (AuthProvider, MemberProvider, ConfigProvider)
  • API 프록시 패턴: 클라이언트 → app/api/[도메인]/[...path]/route.ts → 백엔드
    • 클라이언트에서 직접 백엔드 호출 안 함 (CORS, 쿠키 처리)
  • 서버 데이터 흐름: Server Component → fetchJson() → 백엔드 직접 호출
  • 인증: JWT Bearer 토큰 (accessToken/refreshToken, httpOnly 쿠키)
  • 실시간: SignalR WebSocket
    • AppHub (/hubs/app) — 채팅, 알림, 쪽지, 접속자, 크루 초대
    • DonationHub (/hubs/donation) — 후원 위젯/리모콘
  • 결제: 다날 PG (@danalpay/javascript-sdk)

Code Conventions

사용하는 패턴

  • fetchApi<T>() — 클라이언트에서 Route Handler 호출 (lib/utils/client.ts), 실패 시 자동 throw (에러 무시 시 { silent: true })
  • fetchJson<T>() — 서버에서 백엔드 직접 호출 (lib/utils/server.ts)
  • ResultDto<T> — 모든 API 응답 래퍼 ({ success, status, message, data, errors })
  • cn() — Tailwind 클래스 병합 (clsx + tailwind-merge)
  • dangerouslySetInnerHTML — 서버에서 받은 HTML 콘텐츠 렌더링
  • Route Group — (auth), (main)/(account), (main)/(forum) 으로 관련 페이지 그룹화
  • notFound() — 데이터 없을 때 404 처리

사용하지 않는 패턴 (제안 금지)

  • Redux, Zustand (Context + 로컬 상태 사용)
  • GraphQL (REST API만 사용)
  • 클라이언트에서 백엔드 직접 호출 (반드시 Route Handler 프록시 경유)
  • CSS-in-JS (Tailwind + SCSS 사용)
  • React Query / SWR (직접 fetch 사용)

Styling

  • Tailwind CSS — 기본 스타일링
  • SCSS — 컴포넌트별 style.scss, 글로벌 globals.scss
  • CSS Modulescommon.module.scss (레이아웃 그리드)
  • shadcn/ui — new-york 스타일, Radix UI 기반 (components/ui/)
  • CSS Variables — HSL 형식 테마 변수 (--background, --foreground 등)
  • Font Awesome — 아이콘 (@fortawesome 패키지)
  • Lucide React — shadcn/ui 아이콘

Provider 구조 (Root Layout)

ThemeProvider → SignalRProvider → AuthProvider → MemberProvider → ConfigProvider → {children}
  • ThemeProvider: 테마 관리 (라이트/다크 모드)
  • SignalRProvider: WebSocket 연결 (AppHub) — accessToken, signalRUrl prop
  • AuthProvider: 로그인 상태 관리, 토큰 갱신
  • MemberProvider: 현재 사용자 정보
  • ConfigProvider: initialConfig prop으로 서버에서 설정 전달 (React.cache)

용어 규칙

  • POINT (포인트): 후원 가능한 금액 (PG 충전 → PgCharged 잔액)
  • 머니 (Money): 후원 받은 금액 (Donation 잔액 → 출금 가능)

레이아웃 구조

  • 좌측 사이드바 (ChannelSidebar): 채널 목록, 온/오프라인 LED, 시청자 수, 다크모드/다국어/즐겨찾기
  • 우측: 방송 상세 페이지에서 채팅 표시 (고정 아님, 페이지별 조건부)
  • 모바일: 하단 네비게이션 제거 → 상단 가로 스크롤 탭 (YouTube 모바일 스타일)
  • 위젯/리모콘: 별도 Route Group, root layout 미사용

API Route Handler 패턴

// app/api/{도메인}/[...path]/route.ts
export async function POST(request: NextRequest, { params }: { params: Promise<{ path: string[] }> }) {
    const { path } = await params;
    const endpoint = `/api/${path.join('/')}`;
    const res: ResultDto = await fetchJson(endpoint, {
        method: 'POST',
        body: await request.arrayBuffer(),
        headers: { 'Content-Type': request.headers.get('content-type') || '' }
    });
    return NextResponse.json(res);
}

Build & Run

# 개발 서버 (HTTPS, 포트 3000)
npm run dev

# 프로덕션 빌드
npm run build

# 프로덕션 실행
npm run start

# 린트
npm run lint

사용 Domain