예전 프로젝트에서는 Table.tsx라는 거대한 테이블 컴포넌트를 쓰고 있었습니다. 1,000줄이 넘는 코드에, props만 50개가 넘다 보니 새로운 기능을 추가하거나 버그를 수정할 때마다 손대기가 두려울 정도였죠.
이번에 아예 새로운 패키지(packages/table)로 분리해서 구조를 처음부터 다시 설계했고, 결과적으로 훨씬 쓰기 편하고 유지보수하기 좋은 테이블 컴포넌트를 만들 수 있었습니다.
기존 테이블
하나의 파일 안에 모든 기능이 다 들어있음 (약 1,100줄)
props만 50개 이상 → 어떤 게 어디서 쓰이는지 매번 헷갈림
상태 관리도 React Table v7의 훅을 직접 조합해야 해서 복잡
새 테이블
컴파운드 컴포넌트 패턴(Compound Component Pattern) 으로 전환
→ Table, TableMain, TableToolbar, TablePagination 같은 컴포넌트를 필요한 대로 조합해서 사용
TableProvider를 중심으로 상태를 공유해 코드가 깔끔해짐
각 컴포넌트가 자기 역할에 필요한 props만 받아서 헷갈릴 일이 없음
예전: React Table v7
지금: TanStack Table v8
덕분에 코드가 훨씬 단순해졌습니다.
// 예전 (복잡)
const { getTableProps, headerGroups, prepareRow, page } = useTable(
{ columns, data },
useFilters,
useGlobalFilter,
useSortBy,
usePagination
);
// 지금 (심플)
const table = useReactTable({
data,
columns,
});
이전 방식
<Table
data={data}
columns={columns}
isSearch
searchColumnId="name"
isPagination
manualPagination
onClickRow={handleRowClick}
// ... 20개 넘는 props
/>
지금 방식
<Table data={data} columns={columns} onClickRow={handleRowClick}>
<TableToolbar>
{({ onSearch }) => <SearchInput onSearch={onSearch} />}
</TableToolbar>
<TableMain useVirtualization />
<TablePagination total={1000} />
</Table>
검색 관련 props는 TableToolbar 안에서만 처리
페이지네이션 관련 props는 TablePagination에서만 관리
테이블 본체(data, columns)는 Table에만 전달
👉 덕분에 props를 외울 필요도 없고, 필요한 곳에서만 다루니 헷갈릴 일이 없습니다.
// 간단하게
<Table data={data} columns={columns}>
<TableMain useVirtualization />
<TablePagination total={1000} />
</Table>
// 복잡하게도 가능
<Table data={data} columns={columns}>
<TableToolbar>
{({ onSearch }) => <CustomSearch onSearch={onSearch} />}
</TableToolbar>
<TableFilterBar />
<TableMain fixedColumns={[{ index: 0, position: 'left' }]} />
<TablePagination total={1000} />
</Table>
이제는 불필요한 기능을 끼워 넣지 않아도 되고, 필요한 것만 골라서 조합할 수 있습니다.
props 개수 감소
개발자들이 사용하기 쉬워짐
결과적으로 코드 읽기가 훨씬 쉬워졌고, 새로운 기능을 추가하거나 버그를 고치는 속도도 크게 빨라졌습니다.
리팩토링하면서 크게 느낀 건 두 가지였습니다.
컴파운드 컴포넌트 패턴의 힘
→ props로 기능을 제어하는 방식보다, 필요한 컴포넌트를 조합하는 방식이 훨씬 직관적이고 확장성도 좋습니다.
props는 필요한 곳에서만
→ 모든 옵션을 한 컴포넌트에 몰아넣는 대신, 각 기능이 자기 자리에서만 props를 받게 하면 코드가 깔끔해지고 혼동이 줄어듭니다.
이번 테이블 리팩토링은 단순히 코드를 줄이는 작업이 아니라, “어떻게 하면 더 쓰기 편하고 유지보수하기 좋은 구조를 만들 수 있을까” 를 고민한 과정이었습니다.
앞으로도 이런 방식으로 다른 레거시 컴포넌트들도 하나씩 개선해 나갈 계획입니다.