diff options
Diffstat (limited to 'components/client-table-v2/GUIDE.md')
| -rw-r--r-- | components/client-table-v2/GUIDE.md | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/components/client-table-v2/GUIDE.md b/components/client-table-v2/GUIDE.md new file mode 100644 index 00000000..4ccadfc7 --- /dev/null +++ b/components/client-table-v2/GUIDE.md @@ -0,0 +1,178 @@ +# Table Component & Data Fetching Guide + +이 가이드는 `ClientVirtualTable`을 사용하여 테이블을 구현하고, 데이터를 페칭하는 3가지 주요 패턴을 설명합니다. + +## 개요 + +프로젝트의 복잡도와 요구사항에 따라 아래 3가지 패턴 중 하나를 선택하여 사용할 수 있습니다. + +| 모드 | 패턴 | 적합한 상황 | 특징 | +|---|---|---|---| +| **Client** | 1. Client-Side | 데이터가 적을 때 (< 1000건), 빠른 인터랙션 필요 | 전체 데이터 로드 후 브라우저에서 처리 | +| **Server** | 2. Factory Service | 단순 CRUD, 마스터 테이블 | 코드 1줄로 서버 액션 생성, 빠른 개발 | +| **Server** | 3. Custom Service | 복잡한 조인, 비즈니스 로직 | 완전한 쿼리 제어, Adapter를 도구로 사용 | + +--- + +## 1. Client-Side (기본 모드) + +데이터가 많지 않을 때 가장 간단한 방법입니다. 모든 데이터를 한 번에 받아와 `data` prop으로 넘깁니다. + +### 사용법 + +```tsx +// page.tsx +import { getAllUsers } from "@/lib/api/users"; +import { ClientVirtualTable } from "@/components/client-table-v2/client-virtual-table"; +import { columns } from "./columns"; + +export default async function UsersPage() { + const users = await getAllUsers(); // 전체 목록 조회 + + return ( + <ClientVirtualTable + fetchMode="client" + data={users} + columns={columns} + enablePagination + enableSorting + enableFiltering + /> + ); +} +``` + +--- + +## 2. Factory Service (추천 - 단순 조회용) + +`createTableService`를 사용하여 서버 사이드 페칭을 위한 액션을 자동으로 생성합니다. + +### 1) Server Action 생성 + +```typescript +// app/actions/user-table.ts +"use server" + +import { db } from "@/lib/db"; +import { users } from "@/lib/db/schema"; +import { columns } from "@/components/users/columns"; +import { createTableService } from "@/components/client-table-v2/adapter/create-table-service"; + +// 팩토리 함수로 액션 생성 (한 줄로 끝!) +export const getUserTableData = createTableService({ + db, + schema: users, + columns: columns +}); +``` + +### 2) 클라이언트 컴포넌트 연결 + +```tsx +// components/users/user-table.tsx +"use client" + +import { getUserTableData } from "@/app/actions/user-table"; +import { ClientVirtualTable } from "@/components/client-table-v2/client-virtual-table"; +import { columns } from "./columns"; +import { useState, useEffect } from "react"; + +export function UserTable() { + const [data, setData] = useState([]); + const [totalRows, setTotalRows] = useState(0); + const [loading, setLoading] = useState(false); + + // 테이블 상태 관리 + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); + const [sorting, setSorting] = useState([]); + const [columnFilters, setColumnFilters] = useState([]); + const [globalFilter, setGlobalFilter] = useState(""); + + // 데이터 페칭 + useEffect(() => { + const fetchData = async () => { + setLoading(true); + const result = await getUserTableData({ + pagination, + sorting, + columnFilters, + globalFilter + }); + setData(result.data); + setTotalRows(result.totalRows); + setLoading(false); + }; + + fetchData(); + }, [pagination, sorting, columnFilters, globalFilter]); + + return ( + <ClientVirtualTable + fetchMode="server" + data={data} + rowCount={totalRows} + columns={columns} + isLoading={loading} + // 상태 연결 + pagination={pagination} onPaginationChange={setPagination} + sorting={sorting} onSortingChange={setSorting} + columnFilters={columnFilters} onColumnFiltersChange={setColumnFilters} + globalFilter={globalFilter} onGlobalFilterChange={setGlobalFilter} + /> + ); +} +``` + +--- + +## 3. Custom Service (복잡한 로직용) + +여러 테이블을 조인하거나, 특정 권한 체크 등 복잡한 로직이 필요할 때는 `DrizzleTableAdapter`를 직접 사용합니다. + +### 1) Custom Server Action 작성 + +```typescript +// app/actions/order-table.ts +"use server" + +import { db } from "@/lib/db"; +import { orders, users } from "@/lib/db/schema"; +import { DrizzleTableAdapter } from "@/components/client-table-v2/adapter/drizzle-table-adapter"; +import { count, eq } from "drizzle-orm"; + +export async function getOrderTableData(tableState) { + // 1. 어댑터로 조건절 생성 + const adapter = new DrizzleTableAdapter(orders, columns); + const { where, orderBy, limit, offset } = adapter.getQueryParts(tableState); + + // 2. 커스텀 쿼리 작성 (예: 유저 조인) + const data = await db + .select({ + orderId: orders.id, + amount: orders.amount, + userName: users.name // 조인된 컬럼 + }) + .from(orders) + .leftJoin(users, eq(orders.userId, users.id)) + .where(where) + .orderBy(...orderBy) + .limit(limit) + .offset(offset); + + // 3. 카운트 쿼리 + const total = await db + .select({ count: count() }) + .from(orders) + .where(where); + + return { + data, + totalRows: total[0]?.count ?? 0 + }; +} +``` + +### 2) 클라이언트 연결 + +Factory Service 방식과 동일하게 `useEffect`에서 `getOrderTableData`를 호출하면 됩니다. |
