DPOT - Next.js 15 App Router 기반 Creators Support and donate platform frontend (https://dpot.web.or.kr)
app/
├── (auth)/ → 인증 (login, register, forgot-password, reset-password, welcome, approval)
├── (main)/ → 메인 레이아웃 그룹
│ ├── (account)/ → 계정 관리 (profile, change-password, change-email, change-name, change-thumb,
│ │ change-intro, change-summary, change-approve, verify-email,
│ │ login-log, my-posts, my-comments, exp-logs, withdraw)
│ ├── (forum)/ → 게시판 (board, post, comment, latest)
│ ├── support/ → 고객지원 (faq, guide, contact)
│ └── docs/ → 문서 페이지
├── api/ → Route Handler (auth, document, faq, forum, mypage, popup, uploads)
├── auth/ → 인증 관련
├── component/ → 공통 레이아웃 컴포넌트 (Layout, PopupModal, Editor, ChatSidebar 등)
└── styles/ → 글로벌 스타일
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)
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 → 인증 미들웨어 (토큰 검증, 리다이렉트)
memberID, postID (camelCase + 대문자 ID)'use client' 선언'use server' 선언 (Server Actions, lib/utils/server.ts)PopupModal.tsx, Layout.tsx)support/faq/)style.scss 파일| 문자 양쪽에 공백 제거해(예시로 string|null|undefined)'use client' 없으면 RSCapp/api/[도메인]/[...path]/route.ts → 백엔드
fetchJson() → 백엔드 직접 호출fetchApi<T>() — 클라이언트에서 Route Handler 호출 (lib/utils/client.ts)fetchJson<T>() — 서버에서 백엔드 직접 호출 (lib/utils/server.ts)ResultDto<T> — 모든 API 응답 래퍼 ({ success, status, message, data, errors })throwError(res) — 에러 응답 시 예외 발생cn() — Tailwind 클래스 병합 (clsx + tailwind-merge)dangerouslySetInnerHTML — 서버에서 받은 HTML 콘텐츠 렌더링(auth), (main)/(account), (main)/(forum) 으로 관련 페이지 그룹화notFound() — 데이터 없을 때 404 처리style.scss, 글로벌 globals.scsscommon.module.scss (레이아웃 그리드)components/ui/)--background, --foreground 등)ThemeProvider → SignalRProvider → AuthProvider → MemberProvider → ConfigProvider → {children}
ThemeProvider: 테마 관리 (라이트/다크 모드)SignalRProvider: WebSocket 연결 (채팅) — accessToken, signalRChatUrl propAuthProvider: 로그인 상태 관리, 토큰 갱신MemberProvider: 현재 사용자 정보ConfigProvider: initialConfig prop으로 서버에서 설정 전달 (React.cache)// 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);
}
# 개발 서버 (HTTPS, 포트 3000)
npm run dev
# 프로덕션 빌드
npm run build
# 프로덕션 실행
npm run start
# 린트
npm run lint